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
暂无评论