本文在RT-Thread开发之路(8)— 通过TFTLCD液晶屏幕显示数据的原文上进行了局部的小修改,感谢原作者的文章,让自己学到了新的知识。
RT-Thread开发之路(1)— 通过TFTLCD液晶屏幕显示数据
一、硬件连接
BearPi上和正点原子的潘多拉开发板上一样,安装了一个1.3寸,分辨率240*240,色彩深度16bit 的SPI通信接口的TFTLCD液晶彩屏,其驱动芯片为ST7789V2,且连接方式都一样采用4线SPI,如下所示,左边是BearPi,右边是atk-pandora的连接图。
二、开启SPI设备
打开board.h
文件,找到SPI
的配置处,按照其提示配置:
首先,打开【RT-Thread Settings】,找到SPI设备驱动程序,将其选中,然后保存使之生效
通过查看原理图,可以知道,其连接到的引脚如下所示:(对应Pandora的SPI3)
将board.h的SPI3的注释打开,
接下来使用CubeMx生成HAL_SPI_MspInit()
函数,将SPI以及LCD需要的控制引脚设置为如图所示:
将HAL_SPI_MspInit()
复制到board.c
里
void HAL_SPI_MspInit(SPI_HandleTypeDef* hspi)
{
GPIO_InitTypeDef GPIO_InitStruct = {0};
if(hspi->Instance==SPI3)
{
/* USER CODE BEGIN SPI3_MspInit 0 */
/* USER CODE END SPI3_MspInit 0 */
/* Peripheral clock enable */
__HAL_RCC_SPI3_CLK_ENABLE();
__HAL_RCC_GPIOB_CLK_ENABLE();
/**SPI3 GPIO Configuration
PB3 (JTDO-TRACESWO) ------> SPI3_SCK
PB5 ------> SPI3_MOSI
*/
GPIO_InitStruct.Pin = GPIO_PIN_3|GPIO_PIN_5;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
GPIO_InitStruct.Alternate = GPIO_AF6_SPI3;
HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
/* USER CODE BEGIN SPI3_MspInit 1 */
/* USER CODE END SPI3_MspInit 1 */
}
}
然后打开stm32xxxx_hal_config.h
文件,将#define HAL_SPI_MODULE_ENABLED
的注释去掉:
然后编译下载运行,在msh下输入list_device
,可以看到,spi3已经注册上去了
三、移植LCD代码
在packages
文件夹下新建lcd_st7789v2
文件夹,并将并将潘多拉开发板IoT_Board
的drv_lcd.c
、drv_lcd.h
、drv_lcd_font.h
三个文件放入其中,获取方式为:从 Github 获取 或 从 Gitee 获取。也可以从正点原子官网下载Pandora的IOT_Board中获取
然后我们需要对drv_lcd.c
做一些修改,首先,去掉gpio.h
头文件:
然后修改LCD_PWR_PIN
,LCD_DC_PIN
,LCD_RES_PIN
引脚定义:
#define LCD_PWR_PIN GET_PIN(B, 7)
#define LCD_DC_PIN GET_PIN(B, 4)
#define LCD_RES_PIN GET_PIN(B, 6)
接下来,在rt_hw_lcd_config()
函数修改两行代码,添加一行代码:
spi_dev_lcd = (struct rt_spi_device *)rt_device_find("spi30"); //修改
cfg.mode = RT_SPI_MASTER | RT_SPI_MODE_0 | RT_SPI_MSB; //修改
spi_dev_lcd->bus->owner = spi_dev_lcd; //添加
然后,我们对rt_hw_lcd_init()
需要做比较大的修改,就直接贴上修改完成的代码:
static int rt_hw_lcd_init(void)
{
rt_hw_spi_device_attach("spi3", "spi30", GPIOD, GPIO_PIN_7);
lcd_gpio_init();
rt_thread_mdelay(50);
rt_pin_write(LCD_PWR_PIN, PIN_LOW);
rt_pin_write(LCD_RES_PIN, PIN_LOW);
rt_thread_mdelay(12);
rt_pin_write(LCD_RES_PIN, PIN_HIGH);
rt_pin_write(LCD_PWR_PIN, PIN_LOW);
rt_pin_write(LCD_RES_PIN, PIN_LOW);
rt_thread_mdelay(12);
rt_pin_write(LCD_RES_PIN, PIN_HIGH);
rt_thread_mdelay(12);
/* Sleep Out */
lcd_write_cmd(0x11);
/* wait for power stability */
rt_thread_mdelay(12);
/* Memory Data Access Control */
lcd_write_cmd(0x36);
lcd_write_data(0x00);
/* RGB 5-6-5-bit */
lcd_write_cmd(0x3A);
lcd_write_data(0x65);
/* Porch Setting */
lcd_write_cmd(0xB2);
lcd_write_data(0x0C);
lcd_write_data(0x0C);
lcd_write_data(0x00);
lcd_write_data(0x33);
lcd_write_data(0x33);
/* Gate Control */
lcd_write_cmd(0xB7);
lcd_write_data(0x72);
/* VCOM Setting */
lcd_write_cmd(0xBB);
lcd_write_data(0x3D);
/* LCM Control */
lcd_write_cmd(0xC0);
lcd_write_data(0x2C);
/* VDV and VRH Command Enable */
lcd_write_cmd(0xC2);
lcd_write_data(0x01);
/* VRH Set */
lcd_write_cmd(0xC3);
lcd_write_data(0x19);
/* VDV Set */
lcd_write_cmd(0xC4);
lcd_write_data(0x20);
/* Frame Rate Control in Normal Mode */
lcd_write_cmd(0xC6);
lcd_write_data(0x0F);
/* Power Control 1 */
lcd_write_cmd(0xD0);
lcd_write_data(0xA4);
lcd_write_data(0xA1);
/* Positive Voltage Gamma Control */
lcd_write_cmd(0xE0);
lcd_write_data(0xD0);
lcd_write_data(0x04);
lcd_write_data(0x0D);
lcd_write_data(0x11);
lcd_write_data(0x13);
lcd_write_data(0x2B);
lcd_write_data(0x3F);
lcd_write_data(0x54);
lcd_write_data(0x4C);
lcd_write_data(0x18);
lcd_write_data(0x0D);
lcd_write_data(0x0B);
lcd_write_data(0x1F);
lcd_write_data(0x23);
/* Negative Voltage Gamma Control */
lcd_write_cmd(0xE1);
lcd_write_data(0xD0);
lcd_write_data(0x04);
lcd_write_data(0x0C);
lcd_write_data(0x11);
lcd_write_data(0x13);
lcd_write_data(0x2C);
lcd_write_data(0x3F);
lcd_write_data(0x44);
lcd_write_data(0x51);
lcd_write_data(0x2F);
lcd_write_data(0x1F);
lcd_write_data(0x1F);
lcd_write_data(0x20);
lcd_write_data(0x23);
/* Display Inversion On */
lcd_write_cmd(0x21);
lcd_write_cmd(0x29);
lcd_address_set(0, 0, 240 - 1, 240 - 1);
lcd_clear(WHITE);
/* display on */
rt_pin_write(LCD_PWR_PIN, PIN_HIGH);
return RT_EOK;
}
INIT_COMPONENT_EXPORT(rt_hw_lcd_init);
接下来添加头文件,在工具设置配置页,点击GNU ARM Cross C Compiler
下的Includes
配置项即可打开头文件路径配置参数,点击Inlucde paths(-I)
配置栏的添加按钮即将lcd_st7789v2
目录添加进来,如下图所示:
四、编写代码,在LCD上显示
在main.c
里添加头文件,
#include "drv_lcd.h"
然后测试几个函数:
/* 设置背景色和前景色 */
lcd_set_color(WHITE, BLACK);
/* 在 LCD 上显示字符 */
lcd_show_string(10, 60, 32, "Hello!");
lcd_show_string(10, 100, 32, "RT-Thread");
/* 在 LCD 上画线 */
lcd_draw_line(0, 69+16+24+32, 240, 69+16+24+32);
/* 在 LCD 上画一个同心圆 */
lcd_draw_point(120, 194);
for (int i = 0; i < 46; i += 4)
{
lcd_draw_circle(120, 194, i);
}
编译下载运行,可以看到: