STM32F103以SPI 驱动128*128的TFT彩屏,LCD驱动为ST7735s,程序使用CubeMX的HAL库开发方式,另外也做了标准库的程序移植

0.  关于本文:

        其实我一直都比较懒,不喜欢写博客。但网上关于详细讲解SPI驱动LCD的文章比较少,虽然也能下载到一些案例程序,但对于初学者来说,如果不懂LCD驱动的原理,不懂如何对文字和图片取模,即便拿到了别人的代码,也是一脸懵很难移植。所以写下本文,大家有不明白的,欢迎留言区一起交流,谢谢!

1.  实验任务:

        本实验使用 STM32F103R6 芯片,通过软件SPI的方式,控制128*128分辨率的LCD,实现在液晶屏上显示汉字,英文,数字,图片等内容。

2. 实验效果展示:

   

 3.  硬件设计

STM32F103 MCU

ST7735 显示屏

PA6

背光控制

PB13

SCK

PB15

MOSI

PB14

数据/命令 切换

PC9

显示屏复位控制

PB12

从机选择

 

 4. 硬件SPI和软件SPI的比较

       本实验用的是软件SPI的方式来控制LCD。好处是可以使用任意的单片机引脚连接LCD,缺点是发送速度没有硬件SPI快,而且占用CPU资源。硬件SPI就是使用单片机特定的SPI引脚来进行通信。

软件SPI

硬件SPI

速度

较慢

较快

CPU资源

需占用CPU资源

不占用CPU资源

引脚灵活性

较灵活,任意GPIO都可使用

只能使用指定的GPIO

对芯片要求

无需芯片集成硬件SPI功能

需芯片集成硬件SPI功能

5. 新建工程

        选择左侧GPIO,参考硬件设计里面的引脚,将控制液晶屏的6个引脚全部设置为推挽输出低电平,不上拉不下拉,IO口的速度选择高速。如果需要串口调试的话,需要把串口也打开。 

 6. 文字取模

        想在液晶屏上显示任意的文字,需要将文字在128*128的像素上描点,1表示该像素点是点亮的,0表示该像素点不亮。这样多个像素组合在一起,就显示出了一个文字。我们需要做的就是在软件里面输入文字,然后生成16进制的数组,在液晶屏上进行描点,将1的地方点亮,0的地方不点亮,将数组里面的内容全部描点后就变成了一个文字。

       我们打开软件:PCtoLCD2002.exe,字模选项设置如下,然后输入文字,点击生成字模数组,将数组复制到程序里面,就可以显示文字了。

        这里要说明一下,关于字体的大小,常用的有6*8,8*16,16*16,32*32。本实验所用汉字采用的是32*32像素大小,所以一个汉字,它的行和列都是32个像素点。在程序里面我们先将第一行,进行32次描点。然后对第二行进行32次描点,以此类推,直到32行全部描点。这样就形成了一个32行,32列的像素点,就组成了一个汉字。

 7. 图片取模

        如果我们想在液晶屏里面显示图片,需要先将图片用PS或者画图软件,转换成128*128的像素大小,因为我们液晶屏的像素就是128*128。下面以画图软件举例,将设置好的图片进行保存。

         打开图片转换软件:Img2Lcd.exe,导入刚才设置好的图片,选择16位真彩色,然后点击保存,把图片生成的数组复制到程序里面。

 8. 驱动芯片ST7735S的认知

        我们知道在自然界中,红、绿、蓝是光学三原色(RGB),自然界中的任何颜色都可以由红、绿、蓝三原色来叠加组成。 

        举例:红色与绿色1:1叠加就组成了黄色,红色与绿色与蓝色1:1:1叠加就组成了白色。

        红色是(R:255,G:0,B:0),也就是0xFF0000。绿色(R:0,G:255,B:0),也就是0x00FF00。蓝色就是(R:0,G:0,B:255),也就是0x0000FF。不同颜色的RGB值见下表:

        虽然采用三个字节来表示RGB的颜色,能表示的颜色非常丰富,数据也非常的整齐 。但是嵌入式系统常常资源有限,使用三个字节表示一个像素过于消耗内存,所以在小型嵌入式系统中,常常使用两个字节(16Bit)来表示一个像素的颜色。

        我们的液晶屏用的驱动芯片是ST7735S,它也是用两个字节(16Bit)来表示一个像素的颜色。在(16Bit)的颜色系统中,常用的是5-6-5的组合形式,即红色占用5Bit,绿色占用6Bit,蓝色占用5Bit。如下图所示:

        用两个字节表示红色为(R:32,G:0,B:0),也就是0xF800,二进制为11111000 00000000.

        上面的图片转换软件,输出的时候选择16位真彩色也是这个原因。但是输出的数组,每一个是8位,而每个像素点需要16位的RGB值表示颜色。所以我们在程序里面,针对每个像素点,需要写入两次,每个数据8位,从而组成16位的RGB值。

        液晶屏有128*128个像素点,每个像素点需要写入两次,一共需要128*128*2个数据,也就是32768个数据。这也是为什么输出的图片数组有32768个的原因。

        驱动芯片将某种颜色,以16进制的方式,写入到液晶屏的每一个像素点,然后所有128*128个像素点就组成了完整的图像。

9. 程序编写

        以下程序是用HAL库编写,首先是对液晶屏进行初始化,打开背光灯。然后全屏显示红色、绿色、蓝色、黑色、白色。

       再从左上角的第一个像素点X:Y(0:0)开始,垂直向下点亮8个像素点,这8个点就组成了一条直线。

       再从坐标轴X:Y(0:0)开始,调用文字的数组,打印出8个汉字,“重庆工程,文字测试”。

       再从坐标轴X:Y(10:80)开始,调用准备好的英文字体库,打印一串英文和数字。

       最后再调用图片的数组,打印出一张图片。在while (1)里面不做任何操作。

        驱动程序因为代码行太长了,这里不贴出。

int main(void)
{
  /* USER CODE BEGIN 1 */

  /* USER CODE END 1 */

  /* MCU Configuration--------------------------------------------------------*/

  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
  HAL_Init();

  /* USER CODE BEGIN Init */

  /* USER CODE END Init */

  /* Configure the system clock */
  SystemClock_Config();

  /* USER CODE BEGIN SysInit */

  /* USER CODE END SysInit */

  /* Initialize all configured peripherals */
  MX_GPIO_Init();
  MX_USART1_UART_Init();
  /* USER CODE BEGIN 2 */

    unsigned char i=0;
    LCD_Init();  //液晶屏初始化
    LCD_BL_ON; //打开LCD显示屏的背光

    printf("LCD测试实验\n\r");    
    Full_Display_Color(RED);//全屏显示红色
    HAL_Delay(500);
    Full_Display_Color(GREEN);//全屏显示绿色
    HAL_Delay(500);
    Full_Display_Color(BLUE);//全屏显示蓝色
    HAL_Delay(500);
    Full_Display_Color(BLACK);//全屏显示黑色
    HAL_Delay(500);
    Full_Display_Color(WHITE);//全屏显示白色
    HAL_Delay(500);

//    从X和Y的坐标轴(0,0)开始,向下画一条直线 
    for(i=0; i<8; i++ )    Draw_Point(0, i, RED);
    HAL_Delay(1000);

//    在坐标X和Y,以字体为红色,背景为灰色,将数组Font_Image_test里面的第i个汉字打印出来
    for(i=0; i<4; i++ ) Display_Font(32*i,0,RED,GRAY0,Font_Image_test,i);
    for(i=0; i<4; i++ ) Display_Font(32*i,32,BLUE,GRAY0,Font_Image_test,4+i);

//    在坐标X和Y,以字体为红色,背景为灰色,显示英文字体
    Display_String(10,80,BLACK,RED,"STM32F103R6HAL");
    Display_String(10,100,BLACK,RED,"demo test!");
    HAL_Delay(1000);

    Display_Picture(Image_test);//全屏显示图片
    HAL_Delay(500);

  /* USER CODE END 2 */
  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
  }
  /* USER CODE END 3 */
}

         以下程序是用标准库编写,液晶屏显示内容和HAL库编写的一样。驱动程序因为代码行太长了,这里不贴出。

int main(void)
{    
    unsigned char i=0;
    delay_init(72);    
    delay_ms(200);
    LCD_Init();  //显示屏初始化
    GPIO_SetBits(GPIOA,GPIO_Pin_6); //打开LCD显示屏的背光

    DispColor(BLACK);//全屏显示黑色
    delay_ms(1000);
    DispColor(RED);//全屏显示红色
    delay_ms(1000);
    DispColor(GREEN);//全屏显示绿色
    delay_ms(1000);
    DispColor(BLUE);//全屏显示蓝色
    delay_ms(1000);
    DispColor(WHITE);//全屏显示白色
    delay_ms(1000);

    DrawPoint(0, 0, BLACK);//从X和Y的坐标轴(0,0)开始,向下画一条直线。
    DrawPoint(0, 1, BLACK);
    DrawPoint(0, 2, BLACK);
    DrawPoint(0, 3, BLACK);
    DrawPoint(0, 4, BLACK);
    DrawPoint(0, 5, BLACK);
    delay_ms(2000);

    for(i=0; i<4; i++ ) Gui_DrawFont_Num32(32*i,0,RED,GRAY0,Num[i]); //打印出汉字:重庆工程,文字测试  
    for(i=0; i<4; i++ ) Gui_DrawFont_Num32(32*i,32,RED,GREEN,Num[4+i]);

    Gui_DrawFont_GBK16(10,64,BLACK,GRAY0,"STM32F103_HAL");//打印出英文
    Gui_DrawFont_GBK16(10,80,RED,GRAY2,"demo test!");

//    Gui_DrawFont_Num32_123(95,95,RED,GRAY0,Num[5]);//打印出5,4,3,2,1,0的倒计时
//    delay_ms(5000);
//    Gui_DrawFont_Num32_123(95,95,RED,GRAY0,Num[4]);
//    delay_ms(5000);
    Gui_DrawFont_Num32_123(95,95,RED,GRAY0,Num[3]);
    delay_ms(5000);
    Gui_DrawFont_Num32_123(95,95,RED,GRAY0,Num[2]);
    delay_ms(5000);
    Gui_DrawFont_Num32_123(95,95,RED,GRAY0,Num[1]);
    delay_ms(5000);
    Gui_DrawFont_Num32_123(95,95,RED,GRAY0,Num[0]);    
    delay_ms(9000);

    DispPic(gImage_zhang123);//DispPic(gImage_zhang); 全屏显示一张图片
    delay_ms(5000);
    while(1) 
    {     }      
 }

 10. 运行效果

 11. 完整代码下载

        HAL库程序代码,含文字和图片取模软件:

STM32F103驱动128*128的TFT彩屏,LCD驱动为ST7735s,程序使用了CubeMX的HAL库开发方式-C/C++文档类资源-CSDN文库

        标准库程序代码,含文字和图片取模软件:

STM32F103驱动128*128的TFT彩屏,LCD驱动为ST7735s,程序使用标准库开发。含文字和图片取模软件-C/C++文档类资源-CSDN文库

版权声明:本文为CSDN博主「祝老师」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/u010173859/article/details/120972201

生成海报
点赞 0

祝老师

我还没有学会写个人说明!

暂无评论

发表评论

相关推荐

STM32F2————配置时钟延迟不准的问题

STM32F2配置时钟问题 笔者在本科毕业设计使用STM32F207芯片,但是在配置时钟时出现了问题。 问题 我按照F1写代码的延时函数放在F2竟然不准了 换个办法 使用Systick时钟也是不准,原因是笔者代

为什么重写printf函数没有用?

以前在网上找了无数方法去重写printf函数,但发现都没效果,今天偶然发现重写printf函数可以了,原因是以前没有勾选微库(Use MicroLlB)! 这里