· 2022年08月28日 · 江苏

【MM32F5270开发板试用】用fsmc模拟8080协议来驱动ILI9341显示屏幕

用fsmc模拟8080协议来驱动ILI9341的显示

8080协议

8080 时序也叫因特尔总线,一般mcu(mpu)模式的lcd上。

Inter总线控制线有四根:

RD:写使能
WR:读使能
DC(RS):数据/命令
CS:片选
LCD控制及传输数据所需要的管脚:

管脚名称功能描述
CS片选信号
DC(RS)数据或者命令管脚(1:数据读写,0:命令读写)
WRMCU(MPU)向LCD写入数据控制线,上升沿有效,写数据时 RD拉高
RDMCU (MPU) 从LCD读数据控制线,上升沿有效,读数据时,WR拉高
DB[x:0]8/9/16/18bit 双向数据总线,一般8位MCU接口用的比较多
RST硬件复位 LCD 信号
BLLCD背光信号
IM2/IM1/IM0接口控制. IM2=0 串行,IM2 =1,IM1=0,IM0=0,6800/8080 8bit 并行接口;IM1=0,IM0=1,6800/8080 16bit 并行接口;IM1=1,IM0=0,6800/8080 9bit 并行接口;IM1=1,IM0=1,6800/8080 18bit 并行接口;
P686800/8080 选择。0 表示8080,1 表示6800

以下是8080时序图
image.png

Fsmc

由于 FSMC 外设可以用于控制扩展的外部存储器,而 MCU 对液晶屏的操作实际上就是把显示数据写入到显存中,与控制SRAM 存储器非常类似,且 8080 接口的通讯时序完全可以使用 FSMC 外设产生,因而非常适合使用 FSMC控制液晶屏。
image.png

获取官方的sdk

image.png
官方在mindsdk中提供了一系列的参考的例程给我们参考,我们通过下载可以获取到这个sdk,打开其中的lcd.c和lcd.h文件查看其中的代码,可以发现其中的代码提供的是官方支持的显示屏其驱动芯片为st7796s,但是手头只有一块ILI9341的显示屏.查看fsmc的驱动代码,能发现其中提供了现成的发送命令、发送数据、读取命令、读取数据.那么只要发送相应的命令即可实现驱动.然后就是查询ILI9341的芯片手册,获取到主要命令.完成初始化,设置窗口,填充色块的代码.然后就完成了最初的代码,其中利用到了delay_us和delay_ms函数主要是参考之前论坛中两位大佬写的systicks系统定时器编写延时器来编写的.这里这里.
然后就实现了ILI9341芯片显示屏的驱动.
相关代码如下

void LCD_Init(LCD_Init_Type * init)
{
    LCD_InitHardware();

    GPIO_SetBits(BOARD_LCD_RST_GPIO_PORT, BOARD_LCD_RST_GPIO_PIN);
    GPIO_ClearBits(BOARD_LCD_RST_GPIO_PORT, BOARD_LCD_RST_GPIO_PIN);
    GPIO_SetBits(BOARD_LCD_RST_GPIO_PORT, BOARD_LCD_RST_GPIO_PIN);
    delay_ms(50);
    LCD_WriteCmd(0xCF);  
        LCD_WriteData(0x00); 
        LCD_WriteData(0xC1); 
        LCD_WriteData(0X30); 
        LCD_WriteCmd(0xED);  
        LCD_WriteData(0x64); 
        LCD_WriteData(0x03); 
        LCD_WriteData(0X12); 
        LCD_WriteData(0X81); 
        LCD_WriteCmd(0xE8);  
        LCD_WriteData(0x85); 
        LCD_WriteData(0x10); 
        LCD_WriteData(0x7A); 
        LCD_WriteCmd(0xCB);  
        LCD_WriteData(0x39); 
        LCD_WriteData(0x2C); 
        LCD_WriteData(0x00); 
        LCD_WriteData(0x34); 
        LCD_WriteData(0x02); 
        LCD_WriteCmd(0xF7);  
        LCD_WriteData(0x20); 
        LCD_WriteCmd(0xEA);  
        LCD_WriteData(0x00); 
        LCD_WriteData(0x00); 
        LCD_WriteCmd(0xC0);    //Power control 
        LCD_WriteData(0x1B);   //VRH[5:0] 
        LCD_WriteCmd(0xC1);    //Power control 
        LCD_WriteData(0x01);   //SAP[2:0];BT[3:0] 
        LCD_WriteCmd(0xC5);    //VCM control 
        LCD_WriteData(0x30);      //3F
        LCD_WriteData(0x30);      //3C
        LCD_WriteCmd(0xC7);    //VCM control2 
        LCD_WriteData(0XB7); 
        LCD_WriteCmd(0x36);    // Memory Access Control 
        LCD_WriteData(0x48); 
        LCD_WriteCmd(0x3A);   
        LCD_WriteData(0x55); 
        LCD_WriteCmd(0xB1);   
        LCD_WriteData(0x00);   
        LCD_WriteData(0x1A); 
        LCD_WriteCmd(0xB6);    // Display Function Control 
        LCD_WriteData(0x0A); 
        LCD_WriteData(0xA2); 
        LCD_WriteCmd(0xF2);    // 3Gamma Function Disable 
        LCD_WriteData(0x00); 
        LCD_WriteCmd(0x26);    //Gamma curve selected 
        LCD_WriteData(0x01); 
        LCD_WriteCmd(0xE0);    //Set Gamma 
        LCD_WriteData(0x0F); 
        LCD_WriteData(0x2A); 
        LCD_WriteData(0x28); 
        LCD_WriteData(0x08); 
        LCD_WriteData(0x0E); 
        LCD_WriteData(0x08); 
        LCD_WriteData(0x54); 
        LCD_WriteData(0XA9); 
        LCD_WriteData(0x43); 
        LCD_WriteData(0x0A); 
        LCD_WriteData(0x0F); 
        LCD_WriteData(0x00); 
        LCD_WriteData(0x00); 
        LCD_WriteData(0x00); 
        LCD_WriteData(0x00);          
        LCD_WriteCmd(0XE1);    //Set Gamma 
        LCD_WriteData(0x00); 
        LCD_WriteData(0x15); 
        LCD_WriteData(0x17); 
        LCD_WriteData(0x07); 
        LCD_WriteData(0x11); 
        LCD_WriteData(0x06); 
        LCD_WriteData(0x2B); 
        LCD_WriteData(0x56); 
        LCD_WriteData(0x3C); 
        LCD_WriteData(0x05); 
        LCD_WriteData(0x10); 
        LCD_WriteData(0x0F); 
        LCD_WriteData(0x3F); 
        LCD_WriteData(0x3F); 
        LCD_WriteData(0x0F); 
        LCD_WriteCmd(0x2B); 
        LCD_WriteData(0x00);
        LCD_WriteData(0x00);
        LCD_WriteData(0x01);
        LCD_WriteData(0x3f);
        LCD_WriteCmd(0x2A); 
        LCD_WriteData(0x00);
        LCD_WriteData(0x00);
        LCD_WriteData(0x00);
        LCD_WriteData(0xef);     
        LCD_WriteCmd(0x11); //Exit Sleep
    delay_ms(120);
        LCD_WriteCmd(0x29); //display on    
              LCD_Display_Dir(2);    //选择--屏幕显示方式
      LCD_ClearWindow(0,0,240,320,WHITE);
      void LCD_SetWindow(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1)
{   
    uint16_t x2,y2;
    x2=x0+x1-1;
    y2=y0+y1-1;
    LCD_WriteCmd(0x2a);
    LCD_WriteData(x0 >> 8);
    LCD_WriteData(x0 & 0xff);
    LCD_WriteData(x2 >> 8);
    LCD_WriteData(x2 & 0xff);
    LCD_WriteCmd(0x2b);
    LCD_WriteData(y0 >> 8);
    LCD_WriteData(y0 & 0xff);
    LCD_WriteData(y2 >> 8);
    LCD_WriteData(y2 & 0xff);
}
void LCD_FillWindow(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1, uint16_t * color)
{
    LCD_SetWindow(x0, y0, x1, y1);
    LCD_WriteCmd(0x2c);
    for(uint32_t i = 0; i <= x1 - x0; i++)
    {
        for(uint32_t j = 0; j <= y1 - y0; j++)
        {
            LCD_WriteData((* color++));
        }
    }
}

 title=!
7a7f8bc3a3fd80c5be349fd26499998.jpg
在后来我还用lvgl的demo跑了一下,但是因为非官方屏幕,所以尺寸适配的不是很友好.
ef7a0aeaf7ed270580f68b6a23b9462.jpg

总结

mindsdk中提供的示例很好,代码写的很好,但是就是在函数中的注释太少,不便于理解,但是在参数的描述很到位.

推荐阅读
关注数
6144
内容数
276
灵动MM32 MCU相关技术知识,欢迎关注~
目录
极术微信服务号
关注极术微信号
实时接收点赞提醒和评论通知
安谋科技学堂公众号
关注安谋科技学堂
实时获取安谋科技及 Arm 教学资源
安谋科技招聘公众号
关注安谋科技招聘
实时获取安谋科技中国职位信息