由于项目需要用到5.0寸触屏,选了一款RGB565接口的电容触摸屏,决定采用STM32F407+SSD1963的驱动方案,整个过程基本顺利,但中间也遇到了一些问题,折腾了两天,在网上看到很多网友也有遇到类似问题,好像都没有解决,决定把它分享出来,以免浪费不必要的时间。
当第一次做板回来,顺利点亮屏,研究了半天SSD1963手册,终于显示了红绿蓝三原色后,心里挺开心,觉得已经搞得差不多了。接着开始根据UI设计实现界面,这时奇怪的问题出来了,字体显示边缘总是不干净,有点模糊又有一点杂色,图标显示颜色都跟设计有差异,而且细节处也显得不清楚,最后发现只要不是单色,颜色都不能正常显示。由于红绿蓝三原色正常,一直认为硬件没问题,可能是软件初始化配置问题。SSD1963的手册不是太好,不太考虑普通人的智商,有些不好理解,SSD1963没有16位的模式,用18位模式来代替,但是手册里并没有提示18位数据哪两位不用,实际测试必须是LDATA0和LDATA12不用,不要与下图的MCU数据接口混淆,这个是指不同宽度MCU数据接口写入SSD1963显存时对应的RGB关系。
所以硬件连接必须如下:
部分初始化代码如下:
UINT32 HDP = 479; // HS_Display_Area
UINT32 HT = 510; // (HS_Display_Area + HS_pulse_width + HS_Blanking + HS_Front_Porch)
UINT32 HPS = 20; // (HS_pulse_width + HS_Blanking)
UINT32 HPW = 2; // HS_pulse_width
UINT32 LPS = 8; // Horizontal Display Period Start Position
UINT32 VDP = 853; // VS_Display_Area
UINT32 VT = 920; // (VS_Display_Area + VS_pulse_width + VS_Blanking + VS_Front_Porch)
UINT32 VPS = 20; // (VS_pulse_width + VS_Blanking)
UINT32 VPW = 8; // VS_pulse_width
UINT32 FPS = 2; // Vertical Display Period Start Positio
SSD1963_RST_LOW; //复位SSD1963
delay_us(100);
SSD1963_RST_HIGH;
LCD_WR_REG(0xE2); //Set PLL with CLK = 10MHz (MCU OUTPUT),
//Multiplier M = 29, 250MHz < VCO < 800MHz = CLK*(M+1), VCO = 300MHz
LCD_WR_DATA(0x1D); //CLK = 10MHz (MCU OUTPUT),///参数1
LCD_WR_DATA(0x02); //参数2 Divider N = 2, PLL = 300/(N+1) = 100MHz
LCD_WR_DATA(0x04); //参数3 Validate M and N values
LCD_WR_REG(0xE0); // Start PLL command
LCD_WR_DATA(0x01); // enable PLL
delay_ms(100); // Wait 100ms to let the PLL stable
LCD_WR_REG(0xE0); // Start PLL command again
LCD_WR_DATA(0x03); // now, use PLL output as system clock
//delay_ms(5);
LCD_WR_REG(0x01); //软复位
delay_ms(5);
//Set LSHIFT freq, i.e. the DOTCLK with PLL freq 100MHz set previously
//Typical DOTCLK for KD050FM-1 is 35MHz MAX(datasheet), experiment shows 30MHz gives a stable result
//30MHz = 100MHz*(LCDC_FPR+1)/2^20
//LCDC_FPR = 314571 (0x4CCC8)
LCD_WR_REG(0xE6);
LCD_WR_DATA(0x04);//0x03
LCD_WR_DATA(0xCC);
LCD_WR_DATA(0xC8);
//Set LCD mode, varies from individual manufacturer
LCD_WR_REG(0xB0);
LCD_WR_DATA(0x10); // set 18-bit for 5" panel
LCD_WR_DATA(0x00); // set TTL mode
LCD_WR_DATA((HDP >> 8) & 0x00FF); // Set LCD horizontal panel size H
LCD_WR_DATA(HDP & 0x00FF); // Set LCD horizontal panel size L
LCD_WR_DATA((VDP >> 8) & 0x00FF); // Set LCD vertical panel size H
LCD_WR_DATA(VDP & 0x00FF); // Set LCD vertical panel size L
LCD_WR_DATA(0x00); // RGB sequence
//Set horizontal period
LCD_WR_REG(0xB4);
LCD_WR_DATA((HT >> 8) & 0x00FF); //Set HT
LCD_WR_DATA(HT & 0x00FF);
LCD_WR_DATA((HPS >> 8) & 0X00FF); //Set HPS
LCD_WR_DATA(HPS & 0x00FF);
LCD_WR_DATA(HPW); //Set HPW
LCD_WR_DATA((LPS >> 8) & 0x00FF); //Set HPS
LCD_WR_DATA(LPS & 0x00FF);
LCD_WR_DATA(0x0000);
//Set vertical period
LCD_WR_REG(0xB6);
LCD_WR_DATA((VT >> 8) & 0x00FF); //Set VT
LCD_WR_DATA(VT & 0x00FF);
LCD_WR_DATA((VPS >> 8) & 0x00FF); //Set VPS
LCD_WR_DATA(VPS & 0x00FF);
LCD_WR_DATA(VPW); //Set VPW
LCD_WR_DATA((FPS >> 8) & 0x00FF); //Set FPS
LCD_WR_DATA(FPS & 0x00FF);
//设置GPIO配置
LCD_WR_REG(0xB8);
LCD_WR_DATA(0x0F); //GPIO3=output, GPIO[2:0]=output//GPIO is controlled by host; 4个IO设置成输出
LCD_WR_DATA(0x01); //GPIO0 使用正常的IO功能
LCD_WR_REG(0xBA); //设置GPIO配置
LCD_WR_DATA(0x000F); //GPIO[3:0] out 1
LCD_WR_REG(0x0036); //rotation
LCD_WR_DATA(0x0000);
LCD_WR_REG(0xF0); //设置SSD1963同CPU接口为16bit Set pixel data interface
LCD_WR_DATA(0x03); //16-bit(565 format) data