Ви не увійшли.
Поскольку дисплейные модули изначально продаются, в большинстве случаев, с SD или microSD картоприемником, первым их применением у меня стало создание фоторамок.
(На самом деле, это у меня было из подсознания - подаренная девушкой покупная рамка успешно взорвалась после моей попытки установить внутрь аккумулятор с плохим контроллером заряда).
На основе модуля QVGA TFT display 320x240 ili9340 собрана такая фоторамка
Я использовал часы реального времени, Arduino Mini Pro, батарейный модуль, кнопку питания и сам дисплейный модуль
Как всегда, при работе с дисплейными модулями, самое сложное - подобрать хорошую, годную библиотеку, мне помогли библиотеки Adafruit_ILI9340.h и Adafruit_GFX.h.
Ниже приведен код:
/*
* Commands:
* T(00-59)(00-59)(00-23)(1-7)(01-31)(01-12)(00-99) - T(sec)(min)(hour)(dayOfWeek)(dayOfMonth)(month)(year) -
* T - Sets the date of the RTC DS1307 Chip.
*T0007002210115
* T004519
* Example to set the time for 25-Jan-2012 @ 19:57:11 for the 4 day of the week, use this command - T1157194250112
* Q(1-2) - (Q1) Memory initialization (Q2) RTC - Memory Dump
* R - Read/display the time, day and date
*/
#include <Adafruit_GFX.h> // Core graphics library
#include "Adafruit_ILI9340.h" // Hardware-specific library
#include <SD.h>
#include <Wire.h>
#include "RTClib.h"
#include <SPI.h>
//#if defined(__SAM3X8E__)
// #undef __FlashStringHelper::F(string_literal)
// #define F(string_literal) string_literal
//#endif
// TFT display and SD card will share the hardware SPI interface..
#define TFT_RST 8
#define TFT_DC 9
#define TFT_CS 10
#define SD_CS 6
#define DS1307_I2C_ADDRESS 0x68 // This is the I2C address
// Arduino version compatibility Pre-Compiler Directives
#if defined(ARDUINO) && ARDUINO >= 100 // Arduino v1.0 and newer
#define I2C_WRITE Wire.write
#define I2C_READ Wire.read
#else // Arduino Prior to v1.0
#define I2C_WRITE Wire.send
#define I2C_READ Wire.receive
#endif
// Global Variables
byte zero;
byte second, minute, hour, dayOfWeek, dayOfMonth, month, year;
byte test;
int command = 0; // This is the command char, in ascii form, sent from the serial port
int i;
long previousMillis = 0; // will store last time Temp was updated
RTC_DS1307 rtc;
Adafruit_ILI9340 tft = Adafruit_ILI9340(TFT_CS, TFT_DC, TFT_RST);
File dir;
void setup(void) {
Serial.begin(9600);
Wire.begin();
tft.begin();
rtc.begin();
if (! rtc.isrunning()) {
Serial.println(F("RTC is NOT running!"));
// following line sets the RTC to the date & time this sketch was compiled
rtc.adjust(DateTime(__DATE__, __TIME__));
}
//
Serial.print(F("Initializing SD card..."));
if (!SD.begin(SD_CS)) {
Serial.println(F("failed!"));
return;
}
Serial.println(F("OK!"));
printtime ();
delay (1000);
freeMem();
// CheckCmd();
}
void loop() {
File dir=SD.open("/");
dir.rewindDirectory();
while (true) {
File entry = dir.openNextFile();
if (! entry) {
// no more files
Serial.println(F("**nomorefiles**"));
// break;
dir.rewindDirectory();
}
// Print the 8.3 name
Serial.print(entry.name());
// Recurse for directories, otherwise print the file size
if (entry.isDirectory()) {
Serial.println(F("/"));
}
else{
// files have sizes, directories do not
Serial.print(F("\t\t"));
Serial.println(entry.size(), DEC);
bmpDraw(entry.name(),0,0);
delay(3000);
}
entry.close();
printtime ();
}
dir.rewindDirectory();
}
uint16_t freeMem() {
char top;
extern char *__brkval;
extern char __bss_end;
Serial.println( __brkval ? &top - __brkval : &top - &__bss_end);
}
#define BUFFPIXEL 20
void bmpDraw(char *filename, uint8_t x, uint8_t y) {
File bmpFile;
int bmpWidth, bmpHeight; // W+H in pixels
uint8_t bmpDepth; // Bit depth (currently must be 24)
uint32_t bmpImageoffset; // Start of image data in file
uint32_t rowSize; // Not always = bmpWidth; may have padding
uint8_t sdbuffer[3*BUFFPIXEL]; // pixel buffer (R+G+B per pixel)
uint8_t buffidx = sizeof(sdbuffer); // Current position in sdbuffer
boolean goodBmp = false; // Set to true on valid header parse
boolean flip = true; // BMP is stored bottom-to-top
int w, h, row, col;
uint8_t r, g, b;
uint32_t pos = 0, startTime = millis();
if((x >= tft.width()) || (y >= tft.height())) return;
Serial.println();
Serial.print(F("Loading image '"));
Serial.print(filename);
Serial.println('\'');
// Open requested file on SD card
if ((bmpFile = SD.open(filename)) == NULL) {
Serial.print(F("File not found"));
return;
}
// Parse BMP header
if(read16(bmpFile) == 0x4D42) { // BMP signature
Serial.print(F("File size: ")); Serial.println(read32(bmpFile));
(void)read32(bmpFile); // Read & ignore creator bytes
bmpImageoffset = read32(bmpFile); // Start of image data
Serial.print(F("Image Offset: ")); Serial.println(bmpImageoffset, DEC);
// Read DIB header
Serial.print(F("Header size: ")); Serial.println(read32(bmpFile));
bmpWidth = read32(bmpFile);
bmpHeight = read32(bmpFile);
if(read16(bmpFile) == 1) { // # planes -- must be '1'
bmpDepth = read16(bmpFile); // bits per pixel
Serial.print(F("Bit Depth: ")); Serial.println(bmpDepth);
if((bmpDepth == 24) && (read32(bmpFile) == 0)) { // 0 = uncompressed
goodBmp = true; // Supported BMP format -- proceed!
Serial.print(F("Image size: "));
Serial.print(bmpWidth);
Serial.print(F("x"));
Serial.println(bmpHeight);
// BMP rows are padded (if needed) to 4-byte boundary
rowSize = (bmpWidth * 3 + 3) & ~3;
// If bmpHeight is negative, image is in top-down order.
// This is not canon but has been observed in the wild.
if(bmpHeight < 0) {
bmpHeight = -bmpHeight;
flip = false;
}
// Crop area to be loaded
w = bmpWidth;
h = bmpHeight;
if((x+w-1) >= tft.width()) w = tft.width() - x;
if((y+h-1) >= tft.height()) h = tft.height() - y;
// Set TFT address window to clipped image bounds
tft.setAddrWindow(x, y, x+w-1, y+h-1);
for (row=0; row<h; row++) { // For each scanline...
// Seek to start of scan line. It might seem labor-
// intensive to be doing this on every line, but this
// method covers a lot of gritty details like cropping
// and scanline padding. Also, the seek only takes
// place if the file position actually needs to change
// (avoids a lot of cluster math in SD library).
if(flip) // Bitmap is stored bottom-to-top order (normal BMP)
pos = bmpImageoffset + (bmpHeight - 1 - row) * rowSize;
else // Bitmap is stored top-to-bottom
pos = bmpImageoffset + row * rowSize;
if(bmpFile.position() != pos) { // Need seek?
bmpFile.seek(pos);
buffidx = sizeof(sdbuffer); // Force buffer reload
}
for (col=0; col<w; col++) { // For each pixel...
// Time to read more pixel data?
if (buffidx >= sizeof(sdbuffer)) { // Indeed
bmpFile.read(sdbuffer, sizeof(sdbuffer));
buffidx = 0; // Set index to beginning
}
// Convert pixel from BMP to TFT format, push to display
b = sdbuffer[buffidx++];
g = sdbuffer[buffidx++];
r = sdbuffer[buffidx++];
tft.pushColor(tft.Color565(r,g,b));
} // end pixel
} // end scanline
Serial.print(F("Loaded in "));
Serial.print(millis() - startTime);
Serial.println(F(" ms"));
} // end goodBmp
}
}
bmpFile.close();
if(!goodBmp) Serial.println(F("BMP format not recognized."));
}
// These read 16- and 32-bit types from the SD card file.
// BMP data is stored little-endian, Arduino is little-endian too.
// May need to reverse subscript order if porting elsewhere.
uint16_t read16(File f) {
uint16_t result;
((uint8_t *)&result)[0] = f.read(); // LSB
((uint8_t *)&result)[1] = f.read(); // MSB
return result;
}
uint32_t read32(File f) {
uint32_t result;
((uint8_t *)&result)[0] = f.read(); // LSB
((uint8_t *)&result)[1] = f.read();
((uint8_t *)&result)[2] = f.read();
((uint8_t *)&result)[3] = f.read(); // MSB
return result;
}
void printtime () {
DateTime now = rtc.now();
// tft.fillScreen(ILI9340_BLACK);
tft.setTextColor (ILI9340_RED,ILI9340_BLACK);
tft.setTextSize (4);
tft.setCursor(0,00);
tft.print(now.year(), DEC);
tft.print(F("/"));
if (now.month() < 10)
tft.print("0");
tft.print(now.month(), DEC);
tft.print(F("/"));
if (now.day() < 10)
tft.print(F("0"));
tft.print(now.day(), DEC);
tft.println(F(""));
tft.setCursor(0,280);
tft.setTextColor (ILI9340_GREEN,ILI9340_BLUE);
tft.setTextSize (5);
if (now.hour() < 10)
tft.print(F("0"));
tft.print(now.hour(), DEC);
tft.print(F(":"));
if (now.minute() < 10)
tft.print(F("0"));
tft.print(now.minute(), DEC);
tft.print(F(":"));
if (now.second() < 10)
tft.print(F("0"));
tft.print(now.second(), DEC);
tft.println();
delay(5000);
}
void CheckCmd() {
if (Serial.available()) { // Look for char in serial que and process if found
command = Serial.read();
if (command == 84 || command == 116) { //If command = "Tt" Set Date
setDateDs1307();
}
Serial.println(command); // Echo command CHAR in ascii that was sent
}
command = 0; // reset command
delay(100);
}
void setDateDs1307()
{
second = (byte) ((Serial.read() - 48) * 10 + (Serial.read() - 48)); // Use of (byte) type casting and ascii math to achieve result.
minute = (byte) ((Serial.read() - 48) *10 + (Serial.read() - 48));
hour = (byte) ((Serial.read() - 48) *10 + (Serial.read() - 48));
dayOfWeek = (byte) (Serial.read() - 48);
dayOfMonth = (byte) ((Serial.read() - 48) *10 + (Serial.read() - 48));
month = (byte) ((Serial.read() - 48) *10 + (Serial.read() - 48));
year= (byte) ((Serial.read() - 48) *10 + (Serial.read() - 48));
Wire.beginTransmission(DS1307_I2C_ADDRESS);
I2C_WRITE(zero);
I2C_WRITE(decToBcd(second) & 0x7f); // 0 to bit 7 starts the clock
I2C_WRITE(decToBcd(minute));
I2C_WRITE(decToBcd(hour)); // If you want 12 hour am/pm you need to set
// bit 6 (also need to change readDateDs1307)
I2C_WRITE(decToBcd(dayOfWeek));
I2C_WRITE(decToBcd(dayOfMonth));
I2C_WRITE(decToBcd(month));
I2C_WRITE(decToBcd(year));
Wire.endTransmission();
}
// Gets the date and time from the ds1307 and prints result
void getDateDs1307()
{
// Reset the register pointer
Wire.beginTransmission(DS1307_I2C_ADDRESS);
I2C_WRITE(zero);
Wire.endTransmission();
Wire.requestFrom(DS1307_I2C_ADDRESS, 7);
// A few of these need masks because certain bits are control bits
second = bcdToDec(I2C_READ() & 0x7f);
minute = bcdToDec(I2C_READ());
hour = bcdToDec(I2C_READ() & 0x3f); // Need to change this if 12 hour am/pm
dayOfWeek = bcdToDec(I2C_READ());
dayOfMonth = bcdToDec(I2C_READ());
month = bcdToDec(I2C_READ());
year = bcdToDec(I2C_READ());
}
// Convert normal decimal numbers to binary coded decimal
byte decToBcd(byte val)
{
return ( (val/10*16) + (val%10) );
}
// Convert binary coded decimal to normal decimal numbers
byte bcdToDec(byte val)
{
return ( (val/16*10) + (val%16) );
}