mameng 发表于 2021-12-1 20:03

[复旦微FM33LG0系列开发板测评] 驱动SPI TFT显示

<p>&nbsp; &nbsp;看到淘宝有个9.9元的LCD SPI屏,拍下。买来发现是ST7735芯片控制的,一般淘宝里卖的比较多的基本是12864或者是由ILI93XX驱动的,用ST7735的比较少,所以我想写一篇关于ST7735的博文。在驱动屏幕之前我们需要看看它的产品手册。st7735有两种驱动方式,其中一种SPI通讯,另外一个是总线驱动。由于我买的液晶屏是SPI通讯的,所以我只讨论spi驱动。手册上有两个SPI通讯的时序图,分别是SPI三线和SPI四线。其实本质都是一样,只是三线SPI比四线SPI少了一个数据命令切换的控制。</p>

<p>&nbsp;</p>

<p>&nbsp;</p>

<p></p>

<p>SPI7735SPI三线时序图</p>

<p>ST7735SPI四线时序图:</p>

<p></p>

<p>&nbsp;</p>

<p>&nbsp; &nbsp;做驱动程序。移植一下午。搞定。</p>

<p>&nbsp;</p>

<p>&nbsp;</p>

<p>驱动函数:</p>

<pre>
<code>#include "lcd_init.h"
//#include "delay.h"

void LCD_GPIO_Init(void)
{
//        GPIO_InitTypeDefGPIO_InitStructure;
//         RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);       //使能A端口时钟
//        GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0|GPIO_Pin_1|GPIO_Pin_2|GPIO_Pin_3|GPIO_Pin_4|GPIO_Pin_5;       
//         GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;                //推挽输出
//        GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;//速度50MHz
//         GPIO_Init(GPIOA, &amp;GPIO_InitStructure);          //初始化GPIOA
//         GPIO_SetBits(GPIOA,GPIO_Pin_0|GPIO_Pin_1|GPIO_Pin_2|GPIO_Pin_3|GPIO_Pin_4|GPIO_Pin_5);
       
       
        FL_GPIO_InitTypeDef GPIO_InitStruct = {0};
   
    FL_GPIO_ResetOutputPin(GPIOA, FL_GPIO_PIN_0|FL_GPIO_PIN_1|FL_GPIO_PIN_2|FL_GPIO_PIN_3|FL_GPIO_PIN_4|FL_GPIO_PIN_5);
   
    GPIO_InitStruct.pin = FL_GPIO_PIN_0|FL_GPIO_PIN_1|FL_GPIO_PIN_2|FL_GPIO_PIN_3|FL_GPIO_PIN_4|FL_GPIO_PIN_5;
    GPIO_InitStruct.mode = FL_GPIO_MODE_OUTPUT;
    GPIO_InitStruct.outputType = FL_GPIO_OUTPUT_PUSHPULL;
    GPIO_InitStruct.pull = FL_DISABLE;
    FL_GPIO_Init(GPIOA, &amp;GPIO_InitStruct);
}


/******************************************************************************
      函数说明:LCD串行数据写入函数
      入口数据:dat要写入的串行数据
      返回值:无
******************************************************************************/
void LCD_Writ_Bus(unsigned char dat)
{       
        unsigned char i;
        LCD_CS_Clr();
        for(i=0;i&lt;8;i++)
        {                          
                LCD_SCLK_Clr();
                if(dat&amp;0x80)
                {
                   LCD_MOSI_Set();
                }
                else
                {
                   LCD_MOSI_Clr();
                }
                LCD_SCLK_Set();
                dat&lt;&lt;=1;
        }       
LCD_CS_Set();       
}


/******************************************************************************
      函数说明:LCD写入数据
      入口数据:dat 写入的数据
      返回值:无
******************************************************************************/
void LCD_WR_DATA8(unsigned char dat)
{
        LCD_Writ_Bus(dat);
}


/******************************************************************************
      函数说明:LCD写入数据
      入口数据:dat 写入的数据
      返回值:无
******************************************************************************/
void LCD_WR_DATA(unsigned short dat)
{
        LCD_Writ_Bus(dat&gt;&gt;8);
        LCD_Writ_Bus(dat);
}


/******************************************************************************
      函数说明:LCD写入命令
      入口数据:dat 写入的命令
      返回值:无
******************************************************************************/
void LCD_WR_REG(unsigned char dat)
{
        LCD_DC_Clr();//写命令
        LCD_Writ_Bus(dat);
        LCD_DC_Set();//写数据
}


/******************************************************************************
      函数说明:设置起始和结束地址
      入口数据:x1,x2 设置列的起始和结束地址
                y1,y2 设置行的起始和结束地址
      返回值:无
******************************************************************************/
void LCD_Address_Set(unsigned short x1,unsigned short y1,unsigned short x2,unsigned short y2)
{
        if(USE_HORIZONTAL==0)
        {
                LCD_WR_REG(0x2a);//列地址设置
                LCD_WR_DATA(x1+2);
                LCD_WR_DATA(x2+2);
                LCD_WR_REG(0x2b);//行地址设置
                LCD_WR_DATA(y1+1);
                LCD_WR_DATA(y2+1);
                LCD_WR_REG(0x2c);//储存器写
        }
        else if(USE_HORIZONTAL==1)
        {
                LCD_WR_REG(0x2a);//列地址设置
                LCD_WR_DATA(x1+2);
                LCD_WR_DATA(x2+2);
                LCD_WR_REG(0x2b);//行地址设置
                LCD_WR_DATA(y1+1);
                LCD_WR_DATA(y2+1);
                LCD_WR_REG(0x2c);//储存器写
        }
        else if(USE_HORIZONTAL==2)
        {
                LCD_WR_REG(0x2a);//列地址设置
                LCD_WR_DATA(x1+1);
                LCD_WR_DATA(x2+1);
                LCD_WR_REG(0x2b);//行地址设置
                LCD_WR_DATA(y1+2);
                LCD_WR_DATA(y2+2);
                LCD_WR_REG(0x2c);//储存器写
        }
        else
        {
                LCD_WR_REG(0x2a);//列地址设置
                LCD_WR_DATA(x1+1);
                LCD_WR_DATA(x2+1);
                LCD_WR_REG(0x2b);//行地址设置
                LCD_WR_DATA(y1+2);
                LCD_WR_DATA(y2+2);
                LCD_WR_REG(0x2c);//储存器写
        }
}

void LCD_Init(void)
{
        LCD_GPIO_Init();//初始化GPIO
       
        LCD_RES_Clr();//复位
        FL_DelayMs(100);
        LCD_RES_Set();
        FL_DelayMs(100);
       
        LCD_BLK_Set();//打开背光
FL_DelayMs(100);
       
        //************* Start Initial Sequence **********//
        LCD_WR_REG(0x11); //Sleep out
        FL_DelayMs(120);            //Delay 120ms
        //------------------------------------ST7735S Frame Rate-----------------------------------------//
        LCD_WR_REG(0xB1);
        LCD_WR_DATA8(0x05);
        LCD_WR_DATA8(0x3C);
        LCD_WR_DATA8(0x3C);
        LCD_WR_REG(0xB2);
        LCD_WR_DATA8(0x05);
        LCD_WR_DATA8(0x3C);
        LCD_WR_DATA8(0x3C);
        LCD_WR_REG(0xB3);
        LCD_WR_DATA8(0x05);
        LCD_WR_DATA8(0x3C);
        LCD_WR_DATA8(0x3C);
        LCD_WR_DATA8(0x05);
        LCD_WR_DATA8(0x3C);
        LCD_WR_DATA8(0x3C);
        //------------------------------------End ST7735S Frame Rate---------------------------------//
        LCD_WR_REG(0xB4); //Dot inversion
        LCD_WR_DATA8(0x03);
        //------------------------------------ST7735S Power Sequence---------------------------------//
        LCD_WR_REG(0xC0);
        LCD_WR_DATA8(0x28);
        LCD_WR_DATA8(0x08);
        LCD_WR_DATA8(0x04);
        LCD_WR_REG(0xC1);
        LCD_WR_DATA8(0XC0);
        LCD_WR_REG(0xC2);
        LCD_WR_DATA8(0x0D);
        LCD_WR_DATA8(0x00);
        LCD_WR_REG(0xC3);
        LCD_WR_DATA8(0x8D);
        LCD_WR_DATA8(0x2A);
        LCD_WR_REG(0xC4);
        LCD_WR_DATA8(0x8D);
        LCD_WR_DATA8(0xEE);
        //---------------------------------End ST7735S Power Sequence-------------------------------------//
        LCD_WR_REG(0xC5); //VCOM
        LCD_WR_DATA8(0x1A);
        LCD_WR_REG(0x36); //MX, MY, RGB mode
        if(USE_HORIZONTAL==0)LCD_WR_DATA8(0x00);
        else if(USE_HORIZONTAL==1)LCD_WR_DATA8(0xC0);
        else if(USE_HORIZONTAL==2)LCD_WR_DATA8(0x70);
        else LCD_WR_DATA8(0xA0);
        //------------------------------------ST7735S Gamma Sequence---------------------------------//
        LCD_WR_REG(0xE0);
        LCD_WR_DATA8(0x04);
        LCD_WR_DATA8(0x22);
        LCD_WR_DATA8(0x07);
        LCD_WR_DATA8(0x0A);
        LCD_WR_DATA8(0x2E);
        LCD_WR_DATA8(0x30);
        LCD_WR_DATA8(0x25);
        LCD_WR_DATA8(0x2A);
        LCD_WR_DATA8(0x28);
        LCD_WR_DATA8(0x26);
        LCD_WR_DATA8(0x2E);
        LCD_WR_DATA8(0x3A);
        LCD_WR_DATA8(0x00);
        LCD_WR_DATA8(0x01);
        LCD_WR_DATA8(0x03);
        LCD_WR_DATA8(0x13);
        LCD_WR_REG(0xE1);
        LCD_WR_DATA8(0x04);
        LCD_WR_DATA8(0x16);
        LCD_WR_DATA8(0x06);
        LCD_WR_DATA8(0x0D);
        LCD_WR_DATA8(0x2D);
        LCD_WR_DATA8(0x26);
        LCD_WR_DATA8(0x23);
        LCD_WR_DATA8(0x27);
        LCD_WR_DATA8(0x27);
        LCD_WR_DATA8(0x25);
        LCD_WR_DATA8(0x2D);
        LCD_WR_DATA8(0x3B);
        LCD_WR_DATA8(0x00);
        LCD_WR_DATA8(0x01);
        LCD_WR_DATA8(0x04);
        LCD_WR_DATA8(0x13);
        //------------------------------------End ST7735S Gamma Sequence-----------------------------//
        LCD_WR_REG(0x3A); //65k mode
        LCD_WR_DATA8(0x05);
        LCD_WR_REG(0x29); //Display on
}







</code></pre>

<p>main</p>

<pre>
<code>#include "main.h"
#include "user_init.h"
#include "lcd_init.h"
#include "lcd.h"


int main(void)
{
    /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
    /* SHOULD BE KEPT!!! */
    MF_Clock_Init();

    /* Configure the system clock */
    /* SHOULD BE KEPT!!! */
    MF_SystemClock_Config();

    /* Initialize FL Driver Library */
    /* SHOULD BE KEPT!!! */
    FL_Init();

    /* Initialize all configured peripherals */
    /* SHOULD BE KEPT!!! */
    MF_Config_Init();

    UserInit();


                LCD_Init();//LCD初始化
                LCD_Fill(0,0,LCD_W,LCD_H,BLUE);
                FL_DelayMs(100);
                LCD_ShowString(18,30,"Fudan",WHITE,BLUE,32,0);
                LCD_ShowString(5,90,"FM33LG0",WHITE,BLUE,32,0);
                FL_DelayMs(10);
        while(1)
    {
      LED0_TOG();
//                        printf("祝福复旦微电子越办越好!\r\n");
      FL_DelayMs(1000);
    }
}</code></pre>

<p></p>

<p></p>

<p>&nbsp;</p>

littleshrimp 发表于 2021-12-2 20:10

<p>有显示屏玩起来就是方便,看完你的帖子我也买了几个彩屏。</p>
页: [1]
查看完整版本: [复旦微FM33LG0系列开发板测评] 驱动SPI TFT显示