Developing the theme of adaptation to the library Adafruit stm32. The library for the 16 bit bus using FSMC. It is easy to do the work for 8-bit bus.
/*******************************************************************/
#include "stm32f10x_gpio.h"
#include "stm32f10x_fsmc.h"
#include "stm32f10x_rcc.h"
#include "stm32f10x.h"
#include "reg_9341.h"
#define DELAY_TIME 1
#define TFTWIDTH 240
#define TFTHEIGHT 320
uint8_t rotation;
const uint16_t
WIDTH, HEIGHT;
uint16_t _width, _height;
/*******************************************************************/
// Определяем адреса, по которым будем записывать данные
// Для записи данных
#define LCD_DATA ((uint32_t)0x60020000)
// Для записи команд
#define LCD_REG ((uint32_t)0x60000000)
/*******************************************************************/
// Простенькая функция задержки
void delay(uint32_t delayTime)
{
uint32_t i;
for(i = 0; i < delayTime; i++);
}
/*******************************************************************/
// Так мы будем писать команды в регистры LCD
/*void writeLCDCommand(unsigned int reg,unsigned int value)
{
*(uint16_t *) (LCD_REG) = reg;
*(uint16_t *) (LCD_DATA) = value;
}*/
/*******************************************************************/// Так мы будем писать команды в регистры LCD
void LCD_Write_COM(unsigned int reg)
{
*(uint16_t *) (LCD_REG) = reg;
//*(uint16_t *) (LCD_DATA) = value;
}
/*******************************************************************/
// А так данные..
//void writeLCDData(unsigned int data)
void LCD_Write_DATA(unsigned int data)
{
*(uint16_t *) (LCD_DATA)= data;
}
/*******************************************************************/
void Lcd_data_start(void)
{
LCD_Write_COM(0x2c);
}
/*******************************************************************/
void Global_reset(void)
{
GPIO_ResetBits(GPIOE, GPIO_Pin_1);
delay(0x0FFFFF);
GPIO_SetBits(GPIOE, GPIO_Pin_1 );
delay(0x0FFFFF);
}
/*******************************************************************/
void initAll()
{
FSMC_NORSRAMInitTypeDef fsmc;
FSMC_NORSRAMTimingInitTypeDef fsmcTiming;
GPIO_InitTypeDef gpio;
// Включаем тактирование портов
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOB |RCC_APB2Periph_GPIOC | RCC_APB2Periph_GPIOD | RCC_APB2Periph_GPIOE , ENABLE);
// И тактирование FSMC
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_FSMC, ENABLE);
// Инициализация пинов, задейстованных в общении по FSMC
gpio.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_4 | GPIO_Pin_5 | GPIO_Pin_8 | GPIO_Pin_9 | GPIO_Pin_10 | GPIO_Pin_14 | GPIO_Pin_15;
gpio.GPIO_Mode = GPIO_Mode_AF_PP;
gpio.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOD, &gpio);
gpio.GPIO_Pin = GPIO_Pin_7 | GPIO_Pin_8 | GPIO_Pin_9 | GPIO_Pin_10 | GPIO_Pin_11 | GPIO_Pin_12 | GPIO_Pin_13 | GPIO_Pin_14 | GPIO_Pin_15;
gpio.GPIO_Mode = GPIO_Mode_AF_PP;
gpio.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOE, &gpio);
gpio.GPIO_Mode = GPIO_Mode_Out_PP;
gpio.GPIO_Pin = GPIO_Pin_6;
GPIO_Init(GPIOD, &gpio);
// Здесь у нас Reset
gpio.GPIO_Pin = GPIO_Pin_1 ;
GPIO_Init(GPIOE, &gpio);
// CS
gpio.GPIO_Mode = GPIO_Mode_AF_PP;
gpio.GPIO_Pin = GPIO_Pin_7;
GPIO_Init(GPIOD, &gpio);
// RS
gpio.GPIO_Pin = GPIO_Pin_11 ;
GPIO_Init(GPIOD, &gpio);
// CS -> 1
// Reset -> 0
// RD -> 1
// RW -> 1
GPIO_SetBits(GPIOD, GPIO_Pin_7);
GPIO_ResetBits(GPIOE, GPIO_Pin_1);
GPIO_SetBits(GPIOD, GPIO_Pin_4);
GPIO_SetBits(GPIOD, GPIO_Pin_5);
// Настройка FSMC
fsmcTiming.FSMC_AddressSetupTime = 0x02;
fsmcTiming.FSMC_AddressHoldTime = 0x00;
fsmcTiming.FSMC_DataSetupTime = 0x04;//0x05
fsmcTiming.FSMC_BusTurnAroundDuration = 0x00;
fsmcTiming.FSMC_CLKDivision = 0x00;
fsmcTiming.FSMC_DataLatency = 0x00;
fsmcTiming.FSMC_AccessMode = FSMC_AccessMode_B;
fsmc.FSMC_Bank = FSMC_Bank1_NORSRAM1;
fsmc.FSMC_DataAddressMux = FSMC_DataAddressMux_Disable;
fsmc.FSMC_MemoryType = FSMC_MemoryType_NOR;
fsmc.FSMC_MemoryDataWidth = FSMC_MemoryDataWidth_16b;
fsmc.FSMC_BurstAccessMode = FSMC_BurstAccessMode_Disable;
fsmc.FSMC_WaitSignalPolarity = FSMC_WaitSignalPolarity_Low;
fsmc.FSMC_WrapMode = FSMC_WrapMode_Disable;
fsmc.FSMC_WaitSignalActive = FSMC_WaitSignalActive_BeforeWaitState;
fsmc.FSMC_WriteOperation = FSMC_WriteOperation_Enable;
fsmc.FSMC_WaitSignal = FSMC_WaitSignal_Disable;
fsmc.FSMC_ExtendedMode = FSMC_ExtendedMode_Disable;
fsmc.FSMC_WriteBurst = FSMC_WriteBurst_Disable;
fsmc.FSMC_ReadWriteTimingStruct = &fsmcTiming;
fsmc.FSMC_WriteTimingStruct = &fsmcTiming;
fsmc.FSMC_AsynchronousWait = FSMC_AsynchronousWait_Disable;
FSMC_NORSRAMInit(&fsmc);
FSMC_NORSRAMCmd(FSMC_Bank1_NORSRAM1, ENABLE);
rotation = 1;
_width = TFTWIDTH;
_height = TFTHEIGHT;
}
/*******************************************************************/
void initLCD()
{
// Глобальный Reset дисплея
Global_reset();
// Пляски с бубном от китайских товарищей
LCD_Write_COM(0x01); //reset
delay(15);
LCD_Write_COM(0x11);//sleep out
delay(20);
LCD_Write_COM(0x28); //display off
delay(5);
LCD_Write_COM(0xCF); //power control b
LCD_Write_DATA(0x00);
LCD_Write_DATA(0xC1); //83 81 AA
LCD_Write_DATA(0x30);
LCD_Write_COM(0xED); //power on seq control
LCD_Write_DATA(0x64); //64 67
LCD_Write_DATA(0x03);
LCD_Write_DATA(0x12);
LCD_Write_DATA(0x81);
LCD_Write_COM(0xE8); //timing control a
LCD_Write_DATA(0x85);
LCD_Write_DATA(0x00); // 01
LCD_Write_DATA(0x78); //79 78
LCD_Write_COM(0xCB); //power control a
LCD_Write_DATA(0x39);
LCD_Write_DATA(0X2C);
LCD_Write_DATA(0x00);
LCD_Write_DATA(0x34);
LCD_Write_DATA(0x02);
LCD_Write_COM(0xF7); //pump ratio control
LCD_Write_DATA(0x20);
LCD_Write_COM(0xEA); //timing control b
LCD_Write_DATA(0x00);
LCD_Write_DATA(0x00);
LCD_Write_COM(0xC0); //power control 2
LCD_Write_DATA(0x23); //26 25
LCD_Write_COM(0xC1); //power control 2
LCD_Write_DATA(0x10);// 11
LCD_Write_COM(0xC5); //vcom control 1
LCD_Write_DATA(0x3E);// 35
LCD_Write_DATA(0x28);// 3E
LCD_Write_COM(0xC7); //vcom control 2
LCD_Write_DATA(0x86); //BE 94
LCD_Write_COM(0xB1); //frame control
LCD_Write_DATA(0x00);
LCD_Write_DATA(0x18); //1B 70
LCD_Write_COM(0xB6); //display control
LCD_Write_DATA(0x08);// 0A
LCD_Write_DATA(0x82);
LCD_Write_DATA(0x27);
LCD_Write_DATA(0x00);
LCD_Write_COM(0xB7); //emtry mode
LCD_Write_DATA(0x07);
LCD_Write_COM(0x3A); //pixel format
LCD_Write_DATA(0x55); //16bit
LCD_Write_COM(0xE0);
LCD_Write_DATA(0x0F);
LCD_Write_DATA(0x31);
LCD_Write_DATA(0x2B);
LCD_Write_DATA(0x0C);
LCD_Write_DATA(0x0E);
LCD_Write_DATA(0x08);
LCD_Write_DATA(0x4E);
LCD_Write_DATA(0xF1);
LCD_Write_DATA(0x37);
LCD_Write_DATA(0x07);
LCD_Write_DATA(0x10);
LCD_Write_DATA(0x03);
LCD_Write_DATA(0x0E);
LCD_Write_DATA(0x09);
LCD_Write_DATA(0x00);
LCD_Write_COM(0x36); //mem access
LCD_Write_DATA((1<<3)|(1<<6));
//LCD_Write_DATA((1<<3)|(1<<7)); //rotate 180
LCD_Write_COM(0x29); //display on
LCD_Write_COM(0x2C);
delay(5);
/*writeLCDCommand(0x0015,0x0030);
writeLCDCommand(0x0011,0x0040);
writeLCDCommand(0x0010,0x1628);
writeLCDCommand(0x0012,0x0000);
writeLCDCommand(0x0013,0x104d);
delay(10);
writeLCDCommand(0x0012,0x0010);
delay(10);
writeLCDCommand(0x0010,0x2620);
writeLCDCommand(0x0013,0x344d);
delay(10);
writeLCDCommand(0x0001,0x0100);
writeLCDCommand(0x0002,0x0300);
writeLCDCommand(0x0003,0x1030);
writeLCDCommand(0x0008,0x0604);
writeLCDCommand(0x0009,0x0000);
writeLCDCommand(0x000A,0x0008);
writeLCDCommand(0x0041,0x0002);
writeLCDCommand(0x0060,0x2700);
writeLCDCommand(0x0061,0x0001);
writeLCDCommand(0x0090,0x0182);
writeLCDCommand(0x0093,0x0001);
writeLCDCommand(0x00a3,0x0010);
delay(10);
// Настройки гаммы
writeLCDCommand(0x30,0x0000);
writeLCDCommand(0x31,0x0502);
writeLCDCommand(0x32,0x0307);
writeLCDCommand(0x33,0x0305);
writeLCDCommand(0x34,0x0004);
writeLCDCommand(0x35,0x0402);
writeLCDCommand(0x36,0x0707);
writeLCDCommand(0x37,0x0503);
writeLCDCommand(0x38,0x1505);
writeLCDCommand(0x39,0x1505);
delay(10);
// Включение дисплея
writeLCDCommand(0x0007,0x0001);
delay(10);
writeLCDCommand(0x0007,0x0021);
writeLCDCommand(0x0007,0x0023);
delay(10);
writeLCDCommand(0x0007,0x0033);
delay(10);
writeLCDCommand(0x0007,0x0133);*/
}
/*******************************************************************/
int main()
{
initAll();
delay(100);
initLCD();
//setRotation(0);
while(1)
{
int i;
// Начальный и конечный адреса по горизонтали
/*writeLCDCommand(0x0050, 0);
writeLCDCommand(0x0051, 239);
// Начальный и конечный адреса по вертикали
writeLCDCommand(0x0052, 0);
writeLCDCommand(0x0053, 319);
writeLCDCommand(32, 0);
writeLCDCommand(33, 0);*/
//drawPixel(30, 40, 0xFFFF);
//LCD_Write_COM(0x51);
//LCD_Write_DATA(0x00);
//*(uint16_t *) (LCD_REG) = 0x2C;
// Красный
//fillScreen(0xF800);
/*for (i = 0; i < 76800; i++)
{
LCD_Write_DATA(0xF800);
//drawPixel(30, 40, 0x0000);
}*/
//drawPixel(30, 40, 0x0000);
//delay(0xFFFFFF);
// Зеленый
//fillScreen(0x07E0);
/*for (i = 0; i < 76800; i++)
{
LCD_Write_DATA(0x07E0);
}*/
//delay(0xFFFFFF);
//Синий
//fillScreen(0x001F);
/*for (i = 0; i < 76800; i++)
{
LCD_Write_DATA(0x001F);
//drawPixel(30, 40, 0x0000);
}*/
//delay(0xFFFFFF);
//Серый
//fillScreen(0x03EF);
/*for (i = 0; i < 76800; i++)
{
LCD_Write_DATA(0x03EF);
//drawPixel(30, 40, 0x0000);
}*/
//delay(0xFFFFFF);
//fillScreen(0xFFE0);
/*for (i = 0; i < 76800; i++)
{
LCD_Write_DATA(0xFFE0);
//drawPixel(30, 40, 0x0000);
}*/
//delay(0xFFFFFF);
//fillScreen(0x0000);
/*for (i = 0; i < 76800; i++)
{
LCD_Write_DATA(0x0000);
//drawPixel(30, 40, 0x0000);
}*/
//delay(0xFFFFFF);
for(i = 0; i < 4; i++)
{
setRotation(i);
fillScreen(0x03EF);
fillRect(20, 30, 50, 70, 0xF800);
delay(0x0FFFFF);
}
}
}
/*void Adafruit_GFX(int16_t w, int16_t h)
{
WIDTH(w), HEIGHT(h);
}*/
void Rotation(uint8_t x) {
rotation = (x & 3);
switch(rotation) {
case 0:
case 2:
_width = TFTWIDTH;
_height = TFTHEIGHT;
break;
case 1:
case 3:
_width = TFTHEIGHT;
_height = TFTWIDTH;
break;
}
}
void setRotation(uint8_t x)
{
Rotation(x);
uint16_t t;
switch (rotation) {
case 2:
//Rotation(x);
t = ILI9341_MADCTL_MX | ILI9341_MADCTL_BGR;
break;
case 3:
//Rotation(x);
t = ILI9341_MADCTL_MV | ILI9341_MADCTL_BGR;
break;
case 0:
//Rotation(x);
t = ILI9341_MADCTL_MY | ILI9341_MADCTL_BGR;
break;
case 1:
//Rotation(x);
t = ILI9341_MADCTL_MX | ILI9341_MADCTL_MY | ILI9341_MADCTL_MV | ILI9341_MADCTL_BGR;
break;
}
LCD_Write_COM(ILI9341_MADCTL); // MADCTL
LCD_Write_DATA(t);
// For 9341, init default full-screen address window:
setAddrWindow(0, 0, _width - 1, _height - 1);
}
void setAddrWindow(int x1, int y1, int x2, int y2)
{
uint32_t t;
t = x1;
t <<= 16;
t |= x2;
writeRegister32(ILI9341_COLADDRSET, t); // HX8357D uses same registers!
t = y1;
t <<= 16;
t |= y2;
writeRegister32(ILI9341_PAGEADDRSET, t); // HX8357D uses same registers!
}
void fillRect(int16_t x1, int16_t y1, int16_t w, int16_t h, uint16_t fillcolor)
{
int16_t x2, y2;
// Initial off-screen clipping
if( (w <= 0 ) || (h <= 0 ) ||
(x1 >= _width) || (y1 >= _height) ||
((x2 = x1+w-1) < 0 ) || ((y2 = y1+h-1) < 0 )) return;
if(x1 < 0) { // Clip left
w += x1;
x1 = 0;
}
if(y1 < 0) { // Clip top
h += y1;
y1 = 0;
}
if(x2 >= _width) { // Clip right
x2 = _width - 1;
w = x2 - x1 + 1;
}
if(y2 >= _height) { // Clip bottom
y2 = _height - 1;
h = y2 - y1 + 1;
}
setAddrWindow(x1, y1, x2, y2);
flood(fillcolor, (uint32_t)w * (uint32_t)h);
}
void fillScreen(uint16_t color)
{
setAddrWindow(0, 0, _width - 1, _height - 1);
flood(color, (long)TFTWIDTH * (long)TFTHEIGHT);
}
void flood(uint16_t color, uint32_t len)
{
uint16_t blocks;
int i;
LCD_Write_COM(0x2c);
LCD_Write_DATA(color);
len--;
blocks = (uint16_t)(len / 64); // 64 pixels/block
while(blocks--) {
i = 16; // 64 pixels/block / 4 pixels/pass
do {
LCD_Write_DATA(color); LCD_Write_DATA(color);
LCD_Write_DATA(color); LCD_Write_DATA(color);
} while(--i);
}
for(i = (uint8_t)len & 63; i--; ) {
LCD_Write_DATA(color);
}
}
void drawPixel(int16_t x, int16_t y, uint16_t color)
{
setAddrWindow(x, y, _width-1, _height-1);
*(uint16_t *) (LCD_REG) = 0x2C;
LCD_Write_DATA(color);
}
void writeRegister32(uint16_t r, uint32_t d)
{
//CS_ACTIVE;
//CD_COMMAND;
LCD_Write_COM(r);
//write8(r);
//CD_DATA;
delay(DELAY_TIME);
LCD_Write_DATA(d>>24);
//write8(d >> 24);
delay(DELAY_TIME);
LCD_Write_DATA(d>>16);
//write8(d >> 16);
delay(DELAY_TIME);
LCD_Write_DATA(d>>8);
//write8(d >> 8);
delay(DELAY_TIME);
LCD_Write_DATA(d);
//CS_IDLE;
}
/*******************************************************************/