1.3寸SPI通讯TFT LCD显示屏(驱动笔记) | 您所在的位置:网站首页 › 彩色显示屏的接线图片 › 1.3寸SPI通讯TFT LCD显示屏(驱动笔记) |
LCD的驱动为ST7789V,采用SPI协议单工进行通讯。正常SPI通讯拥有四根线片选先线、时钟线、输入线、输出线四根线配合进行输出,而LCD屏只需要写入数据显示即可,因此该显示屏引脚只有SPI通讯的时钟线和输入线。 一、硬件介绍 1.1 1.3寸SPI通讯TFT LCD显示屏拥有GND、VCC、SCL、SDA、RES、DC、BLK四个引脚,分别为负极、正极(3.3V)、SCL(时钟信号线)、SDA(数据线)、RES(复位线)、DC(寄存器\数据写入选择线)、BLK(背光开启)。 驱动为ST7789V,最多能够驱动240*320分辨率的显示屏,而实际显示屏的分辨率只有240*240的分辨率。 1.2 单片机为STM32F103C6T6单片机与LCD屏引脚的连接分别为: BLK -> PB5 DC -> PB6 RES -> PB7 SDA -> PB8 SCL -> PB9 引脚设置均为推挽输出、上拉电阻;PB8与PB9的初始电压设置为高,其余三个引脚初始电压设置为低。 二、程序编写 2.1 GPIO模拟SPI输出该模块时钟线和数据线初始状态均为高电平,时钟线由低电平变化为高电平的时刻,对信号线进行采样,传输时,高位在先,低位在后。 void LCD_Transport(char data) { uint8_t i; // pull down the clock time for(i = 0; i < 8; i++) { LCD_CLK_Low(); if(data&0x80) // OUTPUT Volt LCD_SDA_High(); else LCD_SDA_Low(); LCD_CLK_High(); //RESET data // pull down CS,choose this machine // DC -> high transport data LCD_DC_High(); LCD_Transport(data>>8); LCD_Transport(data); // SPI hasn't reply mechanism } void LCD_Write_REG(char REG) { // DC -> REG choose REG LCD_DC_Low(); LCD_Transport(REG); } 2.3初始化函数初始化函数为重启、开启背光、配置寄存器等一些列操作。其中该型号显示屏能够配置12位、16位、18位的RGB等,显示屏分辨率为240*240,也就是240*240个像素点,而每个像素点都可以由12个、16个、18个小灯组成,每个像素点通过不同的RGB搭配方式可以显示出不同的颜色。一般24位以上的RGB显示才能称为真彩显示,因此该显示屏的显示效果比不上现在的手机屏的显示效果。 void LCD_Init() { // reset at first LCD_RST_Low(); Delay_ms(20); LCD_RST_High(); Delay_ms(20); LCD_BLK_High(); // open background // set scan mode in screen memory and data form LCD_Write_REG(0x36); LCD_Write_Data8(0x00); // set RGB form color deep 16 bit R:5 G:6 B:5; RGB: 444 RGB: 666 LCD_Write_REG(0x3A); LCD_Write_Data8(0x05); // porch set LCD_Write_REG(0xB2); LCD_Write_Data8(0x0C); LCD_Write_Data8(0x0C); LCD_Write_Data8(0x00); LCD_Write_Data8(0x33); LCD_Write_Data8(0x33); // Gate volt control default setting VGL=-8.87 VGH=14.06 LCD_Write_REG(0xB7); LCD_Write_Data8(0x35); // Vcom volt 0.9v default setting LCD_Write_REG(0xBB); LCD_Write_Data8(0x19); // LCM control LCD_Write_REG(0xC0); LCD_Write_Data8(0x2C); // VDV and VRH Command Enable LCD_Write_REG(0xC2); LCD_Write_Data8(0x01); // VRH Set LCD_Write_REG(0xC3); LCD_Write_Data8(0x12); // VDV Set LCD_Write_REG(0xC4); LCD_Write_Data8(0x20); //Frame Rate Control in Normal Mode 60 Hz 00: 119Hz LCD_Write_REG(0xC6); LCD_Write_Data8(0x0F); // Power Control 1 default value LCD_Write_REG(0xD0); LCD_Write_Data8(0xA4); LCD_Write_Data8(0xA1); //Positive Voltage Gamma Control LCD_Write_REG(0xE0); LCD_Write_Data8(0xD0); LCD_Write_Data8(0x04); LCD_Write_Data8(0x0D); LCD_Write_Data8(0x11); LCD_Write_Data8(0x13); LCD_Write_Data8(0x2B); LCD_Write_Data8(0x3F); LCD_Write_Data8(0x54); LCD_Write_Data8(0x4C); LCD_Write_Data8(0x18); LCD_Write_Data8(0x0D); LCD_Write_Data8(0x0B); LCD_Write_Data8(0x1F); LCD_Write_Data8(0x23); //Negative Voltage Gamma Control LCD_Write_REG(0xE1); LCD_Write_Data8(0xD0); LCD_Write_Data8(0x04); LCD_Write_Data8(0x0C); LCD_Write_Data8(0x11); LCD_Write_Data8(0x13); LCD_Write_Data8(0x2C); LCD_Write_Data8(0x3F); LCD_Write_Data8(0x44); LCD_Write_Data8(0x51); LCD_Write_Data8(0x2F); LCD_Write_Data8(0x1F); LCD_Write_Data8(0x1F); LCD_Write_Data8(0x20); LCD_Write_Data8(0x23); // Display Inversion On LCD_Write_REG(0x21); // turn off Sleep mode LCD_Write_REG(0x11); Delay_ms(20); // Display On LCD_Write_REG(0x29); } 2.4 设置操作区域函数LCD屏的显示操作就是先指定需要填充颜色的像素区域或像素点,分别在0x0a、0x2b、0x2c中操作即可。 void address_set(uint16_t x1,uint16_t y1,uint16_t x2, uint16_t y2) { if(x2>wide-1|| y2>length-1)return; else { // choose x axle register LCD_Write_REG(0x2A); // write 16 bit LCD_Write_Data8(x1>>8); LCD_Write_Data8(x1); LCD_Write_Data8(x2>>8); LCD_Write_Data8(x2); // choose y axle register LCD_Write_REG(0x2B); LCD_Write_Data8(y1>>8); LCD_Write_Data8(y1); LCD_Write_Data8(y2>>8); LCD_Write_Data8(y2); // reset to start colum / page position LCD_Write_REG(0x2C); } } 2.5 像素点填充以清屏函数为例,先指定全屏区域作为填充区域,后在每个像素点中逐个填入颜色。 void LCD_SPI_Clear(uint16_t color) { int i,j; address_set(0,0, wide - 1, length - 1); // choose total screen for(i = 0; i < wide; i++) { for(j = 0; j < length; j++) { LCD_Write_Data(color); } } 2.4 字符和数字的显示每个字符占用的像素点为8*16个,因此需要配置8*16个像素点中的每个像素的颜色来显示字符串。字符在文件的存储形式为16个字节的数据,每个字节的8位代表8个像素点的像素值,0代表背景色,1代表显示颜色,这就比较简单,也就是通过二维数组来存储字符串,若要存储图片,那么就还需要存储每个像素点具体像素值,这就需要三维的数组,而数字显示则是将实际的数字进行加减乘除运算得到对应的字符串并显示。 void Draw_one_charater(uint8_t x, uint8_t y,char a, uint16_t color) { uint8_t temp; // the show table only have value after space a = a - ' '; address_set(x,y,x + 7,y + 15); for(uint8_t i = 0; i < 16; i++) { temp = asc2_1608[a*16 + i]; for(uint8_t j = 0; j < 8; j++) // write horizontal at first { if(temp&0x01) { LCD_Write_Data(color); } else { LCD_Write_Data(BLACK); } temp>>=1; } } } void Show_String(uint8_t x, uint8_t y, char *string,uint8_t String_long) { // character occupy 8*16 position 0 or 1 reprensent pixel show black or wihte if(y+16>length) { return; } else { if(x + 8 * String_long Draw_one_charater(x + i *8, y,string[i], WHITE); } } else { return; } } } void Show_number(uint8_t x, uint8_t y, uint32_t number,uint8_t number_bit_in_ten) { uint32_t temp; char Display_Number; // The MAX Display 10 bits in LCD uint32_t is 10 bit uint8_t memory_nuber[10]; // ASCII: 0 -> 48 9 -> 57 temp = number; if(x + number_bit_in_ten * 8 > wide)return; else { for(uint8_t i = 0; i < number_bit_in_ten; i++) { memory_nuber[i] = temp % 10; temp = temp / 10; } for(uint8_t i = 0; i < number_bit_in_ten; i++) { Display_Number = memory_nuber[number_bit_in_ten - i - 1] + 48; Draw_one_charater(x + i * 8, y,Display_Number, YELLOW); } } } 三、主函数和显示效果主函数只需要添加初始化和清屏函数即可。 LCD_Init(); LCD_SPI_Clear(BLACK); LCD_Draw_Horizontal_Line(16,8,220); LCD_Draw_Horizontal_Line(16,16,220); LCD_Draw_Horizontal_Line(16,24,220); LCD_Draw_Horizontal_Line(16,32,220); LCD_Draw_Vetical_Line(16,8,32); LCD_Draw_Vetical_Line(116,8,32); LCD_Draw_Vetical_Line(220,8,32); Show_String(72, 48, "char:",5); Show_number(112,48,sizeof(char),1); Show_String(72, 64, "short int:",10); Show_number(152,64,sizeof(short int),1); Show_String(72, 80, "int:",4); Show_number(104,80,sizeof(int),1); 显示效果: 之前一直错误的以为int在电脑中占用4字节,在单片机中只占用1个字节,现在事实证明,和电脑中的一样;char-> 1bit short int -> 2bit int -> 4bit |
今日新闻 |
推荐新闻 |
专题文章 |
CopyRight 2018-2019 实验室设备网 版权所有 |