系列内容章节如下:
STM32并口屏应用实例:点亮你的显示世界之原理篇
STM32并口屏应用实例:点亮你的显示世界之程序篇
STM32并口屏应用实例:点亮你的显示世界之应用篇
STM32并口屏应用实例:点亮你的显示世界之原理篇
在嵌入式系统开发中,显示设备是与用户交互的重要界面之一。STM32作为一款功能强大的微控制器,支持多种外设接口,其中并口屏的驱动应用非常广泛,其抗干扰性比其他接口更为出色。本文将通过一个实际案例,介绍如何使用STM32驱动并口屏,并展示其原理和实现过程。
一、并口屏简介
并口屏是一种通过并行数据线与控制器连接的显示屏,常见的有TFT-LCD屏。与串行接口相比,并口屏的数据传输速度快,适合高分辨率和高刷新率的应用场景。例如,8位并口屏通过8根数据线同时传输数据,大大提高了通信效率。
二、硬件连接
以STM32F103VET6为例,我们使用其GPIO端口连接一个8位并口的液晶显示屏(如ST75256/JLX25664,256*64像素点)。以下是硬件连接的要点:
-
数据线连接将TFT屏的8位数据线(D0-D7)分别连接到STM32的GPIO端口(如PD9-PD15、PC6)。
-
控制信号连接
• CS(片选信号):连接到STM32的一个GPIO引脚(如PB12)。
• RS(寄存器选择信号):连接到另一个GPIO引脚(如PD8)。
• WR(写信号):连接到GPIO引脚(如PB15)。
• RD(读信号):连接到GPIO引脚(如PB14),本例中暂不使用。
• RST(复位信号):连接到GPIO引脚(如PB13)。
• BLK(背光控制):连接到GPIO引脚(如PB9),可通过PWM控制背光亮度,本例中暂不使用。 -
电源连接
确保TFT屏的电源供电稳定,通常需要3.3V或5V电源。
三、参考程序
3.1 IO驱动代码
通过IO控制宏来实现对LCD的控制端口电平的控制。其中,并口数据写入8位数据,每个bit位对应D0-D7。
/********************************************************************************************************
函数名称: Drv_LCD_CS
功能描述:
输 入: 无
输 出: 无
*********************************************************************************************************/
void Drv_LCD_CS(uint8_t cmd)
{
if(LCD_ENABLE == cmd)
{
BSP_LCD_CS_ON_ENABLE;
}
else if(LCD_DISENABLE == cmd)
{
BSP_LCD_CS_OFF_ENABLE;
}
}
/*********************************************************************************************************
函数名称: Drv_LCD_Reset
功能描述:
输 入: 无
输 出: 无
*********************************************************************************************************/
void Drv_LCD_Reset(uint8_t cmd)
{
if(LCD_ENABLE == cmd)
{
BSP_LCD_RESET_ON_ENABLE;
}
else if(LCD_DISENABLE == cmd)
{
BSP_LCD_RESET_OFF_ENABLE;
}
}
/*****************************************************************************************************
函数名称: Drv_LCD_RD
功能描述:
输 入: 无
输 出: 无
*****************************************************************************************************/
void Drv_LCD_RD(uint8_t cmd)
{
if(LCD_ENABLE == cmd)
{
BSP_LCD_RD_ON_ENABLE;
}
else if(LCD_DISENABLE == cmd)
{
BSP_LCD_RD_OFF_ENABLE;
}
}
/********************************************************************************************************
函数名称: Drv_LCD_WR
功能描述:
输 入: 无
输 出: 无
******************************************************************************************************/
void Drv_LCD_WR(uint8_t cmd)
{
if(LCD_ENABLE == cmd)
{
BSP_LCD_WR_ON_ENABLE;
}
else if(LCD_DISENABLE == cmd)
{
BSP_LCD_WR_OFF_ENABLE;
}
}
/*******************************************************************************************************
函数名称: Drv_LCD_RS
功能描述:
输 入: 无
输 出: 无
****************************************************************************************************/
void Drv_LCD_RS(uint8_t cmd)
{
if(LCD_ENABLE == cmd)
{
BSP_LCD_RS_ON_ENABLE;
}
else if(LCD_DISENABLE == cmd)
{
BSP_LCD_RS_OFF_ENABLE;
}
}
/*********************************************************************************************************
函数名称: Drv_LCD_TX
功能描述:
输 入: 无
输 出: 无
********************************************************************************************************/
void Drv_LCD_TX(uint8_t data)
{
BSP_LCD_D0((GPIO_PinState)((data)&0x01));
BSP_LCD_D1((GPIO_PinState)((data>>1)&0x01));
BSP_LCD_D2((GPIO_PinState)((data>>2)&0x01));
BSP_LCD_D3((GPIO_PinState)((data>>3)&0x01));
BSP_LCD_D4((GPIO_PinState)((data>>4)&0x01));
BSP_LCD_D5((GPIO_PinState)((data>>5)&0x01));
BSP_LCD_D6((GPIO_PinState)((data>>6)&0x01));
BSP_LCD_D7((GPIO_PinState)((data>>7)&0x01));
}
3.2 LCD初始化程序和命令/数据写入接口
命令写入
static void Api_transfer_cmd_lcd(uint8_t cmd)
{
Drv_LCD_CS(LCD_DISENABLE);
Drv_LCD_RS(LCD_DISENABLE);
Drv_LCD_RD(LCD_DISENABLE);
Drv_LCD_WR(LCD_DISENABLE);
Drv_LCD_TX(cmd);
Drv_LCD_RD(LCD_ENABLE);
Drv_LCD_CS(LCD_ENABLE);
Drv_LCD_RD(LCD_DISENABLE);
Drv_LCD_TX(0x00);
}
数据写入
static void Api_transfer_data_lcd(uint8_t data)
{
Drv_LCD_CS(LCD_DISENABLE);
Drv_LCD_RS(LCD_ENABLE);
Drv_LCD_RD(LCD_DISENABLE);
Drv_LCD_WR(LCD_DISENABLE);
Drv_LCD_TX(data);
Drv_LCD_RD(LCD_ENABLE);
Drv_LCD_CS(LCD_ENABLE);
Drv_LCD_RD(LCD_DISENABLE);
Drv_LCD_TX(0x00);
}
LCD初始化
void Api_init_lcd(void)
{
Drv_LCD_Reset(LCD_DISENABLE);
osDelay(100);
Drv_LCD_Reset(LCD_ENABLE);
osDelay(100);
Api_transfer_cmd_lcd(0x30);
Api_transfer_cmd_lcd(0x94);
Api_transfer_cmd_lcd(0x31);
Api_transfer_cmd_lcd(0xD7);
Api_transfer_data_lcd(0x9F);
Api_transfer_cmd_lcd(0x32);
Api_transfer_data_lcd(0x00);
Api_transfer_data_lcd(0x01);
Api_transfer_data_lcd(0x05);
Api_transfer_cmd_lcd(0x20);
Api_transfer_data_lcd(0x01);
Api_transfer_data_lcd(0x03);
Api_transfer_data_lcd(0x05);
Api_transfer_data_lcd(0x07);
Api_transfer_data_lcd(0x09);
Api_transfer_data_lcd(0x0B);
Api_transfer_data_lcd(0x0D);
Api_transfer_data_lcd(0x10);
Api_transfer_data_lcd(0x11);
Api_transfer_data_lcd(0x13);
Api_transfer_data_lcd(0x15);
Api_transfer_data_lcd(0x17);
Api_transfer_data_lcd(0x19);
Api_transfer_data_lcd(0x1B);
Api_transfer_data_lcd(0x1D);
Api_transfer_data_lcd(0x1F);
Api_transfer_cmd_lcd(0x30);
Api_transfer_cmd_lcd(0x75);
Api_transfer_data_lcd(0x00);
Api_transfer_data_lcd(0xFF);
Api_transfer_cmd_lcd(0x15);
Api_transfer_data_lcd(0x00);
Api_transfer_data_lcd(0xFF);
Api_transfer_cmd_lcd(0xBC);
Api_transfer_data_lcd(0x00);
Api_transfer_data_lcd(0xA6);
Api_transfer_data_lcd(0x0C);
Api_transfer_cmd_lcd(0xCA);
Api_transfer_data_lcd(0x00);
Api_transfer_data_lcd(0x3F);
Api_transfer_data_lcd(0x20);
Api_transfer_cmd_lcd(0xF0);
Api_transfer_data_lcd(0x10);
Api_transfer_cmd_lcd(0x81);
Api_transfer_data_lcd(0x12);
Api_transfer_data_lcd(0x02);
Api_transfer_cmd_lcd(0x20);
Api_transfer_data_lcd(0x0B);
osDelay(1);
Api_transfer_cmd_lcd(0xAF);
}
其中的命令和命令数据请参照对应的LCD规格书。一般初始化程序会有参考代码,只不过应用的芯片不一样,需要根据我们自己使用的芯片去实现命令写入和数据写入的代码,达到我们需要的控制需求。
3.3 显示程序设计
因为显示内容包含中文、英文、特殊字符;显示内容还有字号大小的区分,根据我们的具体显示需求通过设计对应的显示接口(PS:项目开需求/时间发导向性: 一般的网上会有一些通用的接口,显示的时候通过传入字号大小去匹配显示对应字符字库,如果时间和MCU空间能够满足,也可以去这么做。但是一般的项目中对字体调节的需求不大,而且调试通用函数费时费力,有兴趣的可以自己开发玩一玩)。
3.3.1 显示原理
请留意页的定义:PAGE,与平时所讲的“页”并不是一个意思,在此表示 8 个行就是一个“页”,
一个个 256*64 点阵的屏分为 8 个“页”,从第 0“页”到第 7“页”。
DB7–DB0 的排列方向:数据是从下向上排列的。最低位 D0 是在最上面,最高位 D7 是在最下面。
每一位(bit)数据对应一个点阵,通常“1”代表点亮该点阵,“0”代表关掉该点阵.如下图所示:
整个LCD显示屏就是由这些页(像素点阵)组成。
所以,显示原理就是通过工具降我们要显示的字符转换成点阵数据,然后通过显示接口将显示内容写入到对应的页和列。
3.3.2 显示示例
进一步的,通过在LCD的页,列坐标上写入定义好的数据,将会显示出我们需要的内容。程序设计将在下一章STM32并口屏应用实例:点亮你的显示世界之程序篇内容中作详细讲解分析。
char cmd_str[20];
Api_display_string_8x16(type, 20, 1, (uchar *)"4.");
Api_display_label_16x16(type, 36, 1, AlarmInfo16x16, sizeof(AlarmInfo16x16)/32);
Api_display_string_8x16(type, 100, 1, (uchar *)":");
Api_display_label_16x16(type, 134, 1, AlarmNONE16x16, sizeof(AlarmNONE16x16)/32);
Api_display_string_8x16(type, 20, 3, (uchar *)"5.ModSta1 :");
memset(cmd_str, 0, 20);
snprintf(cmd_str, 20, "0x%08X", pSt_DisPara.pU32_DCstatus1);
Api_display_string_8x16(type, 118, 3, (uchar *)cmd_str);
Api_display_string_8x16(type, 20, 5, (uchar *)"6.ModSta2 :");
memset(cmd_str, 0, 20);
snprintf(cmd_str, 20, "0x%08X", pSt_DisPara.pU32_DCstatus2)
四、效果展示
通过上述代码,我们成功驱动了8位并口的液晶屏,实现了参数的显示。如下:
特殊符号显示
中英文字符串显示
十六进制数据显示
十进制数据显示
五、总结
本文通过一个实际案例,展示了如何使用STM32驱动8位并口屏。通过硬件连接和软件编程,我们实现了屏幕的初始化、数据传输和显示功能。并口屏以其快速的数据传输能力,在嵌入式显示领域具有广泛的应用前景。希望本文能为你的项目提供参考和启发。
一般LCD都会设计多种通信接口,例如,在我们示例中所应用的JLX25664有设计IIC接口、4线SPI接口,并口包括6800和8080系列的并口,区别只是在通信调用接口不同,寄存器地址和寄存器数据控制写入的逻辑大差不差,需要的可进一步阅读LCD规格书。如果自己找不到的话需要的可以联系交流。