当前位置: 首页 > article >正文

LVGL+FreeRTOS实战项目:智能健康助手(lcd篇)

1.8寸彩色TFT显示屏简介

接线图

我们选用的是分辨率为128*160的彩色显示屏,采用的SPI接口,通过我们STM32的SPI外设,来和我们的屏幕进行通信,以显示我们需要显示的图片。

 

软件部分 

#include "lcd_driver.h"

//液晶IO初始化配置
void LCD_Driver_Init(void)
{

	SPI_InitTypeDef  SPI_InitStructure;
	GPIO_InitTypeDef GPIO_InitStructure;

	/* 使能 LCD_SPI 及GPIO 时钟 */
	/*!< SPI_LCD_SPI_CS_GPIO, SPI_LCD_SPI_MOSI_GPIO, 
	   SPI_LCD_SPI_MISO_GPIO,SPI_LCD_SPI_SCK_GPIO 时钟使能 */
	RCC_AHB1PeriphClockCmd (LCD_SPI_SCK_GPIO_CLK|LCD_SPI_MOSI_GPIO_CLK|LCD_CS_GPIO_CLK, ENABLE);

	/*!< SPI_LCD_SPI 时钟使能 */
	LCD_SPI_CLK_INIT(LCD_SPI_CLK, ENABLE);

	//设置引脚复用
	GPIO_PinAFConfig(LCD_SPI_SCK_GPIO_PORT,LCD_SPI_SCK_PINSOURCE,LCD_SPI_SCK_AF);  
	GPIO_PinAFConfig(LCD_SPI_MOSI_GPIO_PORT,LCD_SPI_MOSI_PINSOURCE,LCD_SPI_MOSI_AF); 
	GPIO_PinAFConfig(LCD_CS_GPIO_PORT,LCD_SPI_CS_PINSOURCE,LCD_SPI_CS_AF); 
	
	/*!< 配置 SPI_LCD_SPI 引脚: SCK */
	GPIO_InitStructure.GPIO_Pin = LCD_SPI_SCK_PIN;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
	GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
	GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;  

	GPIO_Init(LCD_SPI_SCK_GPIO_PORT, &GPIO_InitStructure);

	/*!< 配置 SPI_LCD_SPI 引脚: MOSI */
	GPIO_InitStructure.GPIO_Pin = LCD_SPI_MOSI_PIN;
	GPIO_Init(LCD_SPI_MOSI_GPIO_PORT, &GPIO_InitStructure);  

	/*!< 配置 SPI_LCD_SPI 引脚: CS */
	GPIO_InitStructure.GPIO_Pin = LCD_CS_PIN;
	GPIO_Init(LCD_CS_GPIO_PORT, &GPIO_InitStructure);

	/*!< 配置 SPI_LCD_SPI 引脚: DC */
	GPIO_InitStructure.GPIO_Pin = LCD_DC_PIN;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
	GPIO_Init(LCD_DC_GPIO_PORT, &GPIO_InitStructure);

	/*!< 配置 SPI_LCD_SPI 引脚: RES */
	GPIO_InitStructure.GPIO_Pin = LCD_RES_PIN;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
	GPIO_Init(LCD_RES_GPIO_PORT, &GPIO_InitStructure);

	/*!< 配置 SPI_LCD_SPI 引脚: BLK */
	GPIO_InitStructure.GPIO_Pin = LCD_BLK_PIN;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
	GPIO_Init(LCD_BLK_GPIO_PORT, &GPIO_InitStructure);
	SPI_LCD_BLK_HIGH();
	/* 停止信号 LCD: CS引脚高电平*/
	//SPI_LCD_CS_HIGH();

	/* LCD_SPI 模式配置 */
	// LCD芯片 支持SPI模式0及模式3,据此设置CPOL CPHA
	SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex;
	SPI_InitStructure.SPI_Mode = SPI_Mode_Master;
	SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b;
	SPI_InitStructure.SPI_CPOL = SPI_CPOL_High;
	SPI_InitStructure.SPI_CPHA = SPI_CPHA_2Edge;
	SPI_InitStructure.SPI_NSS = SPI_NSS_Hard;
	SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_2;
	SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;
	SPI_InitStructure.SPI_CRCPolynomial = 7;
	SPI_Init(LCD_SPI, &SPI_InitStructure);

	/* 使能 LCD_SPI  */
	SPI_Cmd(LCD_SPI, ENABLE);
	
	SPI_SSOutputCmd(LCD_SPI,ENABLE);
	SPI_CalculateCRC(LCD_SPI,DISABLE);
	SPI_ClearFlag(LCD_SPI,SPI_FLAG_TXE);
	SPI_ClearFlag(LCD_SPI,SPI_FLAG_RXNE);
}

//向SPI总线传输一个8位数据
void  SPI_WriteData(u8 Data)
{
	while(SPI_I2S_GetFlagStatus(LCD_SPI,SPI_I2S_FLAG_TXE)==RESET);
    SPI_SendData(LCD_SPI,Data);
   
//	unsigned char i=0;
//	for(i=8;i>0;i--)
//	{
//		if(Data&0x80)	
//	  LCD_SDA_SET; //输出数据
//      else LCD_SDA_CLR;
//	   
//      LCD_SCL_CLR;       
//      LCD_SCL_SET;
//      Data<<=1; 
//	}
}

//向液晶屏写一个8位指令
void Lcd_WriteIndex(u8 Index)
{
   //SPI 写命令时序开始
	SPI_LCD_CS_LOW();
	SPI_LCD_DC_LOW();
	SPI_WriteData(Index);
	SPI_LCD_CS_HIGH();
}

//向液晶屏写一个8位数据
void Lcd_WriteData(u8 Data)
{
	SPI_LCD_CS_LOW();
	SPI_LCD_DC_HIGH();
	SPI_WriteData(Data);
	SPI_LCD_CS_HIGH();
}

//向液晶屏写一个16位数据
void LCD_WriteData_16Bit(u16 Data)
{
	SPI_LCD_CS_LOW();
	SPI_LCD_DC_HIGH();
	SPI_WriteData(Data>>8); 	//写入高8位数据
	SPI_WriteData(Data); 		//写入低8位数据
	SPI_LCD_CS_HIGH();
}

void Lcd_WriteReg(u8 Index,u8 Data)
{
	Lcd_WriteIndex(Index);
	Lcd_WriteData(Data);
}

void Lcd_Reset(void)
{
	SPI_LCD_RES_LOW();
	delay_ms(100);
	SPI_LCD_RES_HIGH();
	delay_ms(50);
}

//LCD Init For 1.44Inch LCD Panel with ST7735R.
void Lcd_Init(void)
{	
	LCD_Driver_Init();
	Lcd_Reset(); //Reset before LCD Init.

	//LCD Init For 1.44Inch LCD Panel with ST7735R.
	Lcd_WriteIndex(0x11);//Sleep exit 
	delay_ms (120);
		
	//ST7735R Frame Rate
	Lcd_WriteIndex(0xB1); 
	Lcd_WriteData(0x01); 
	Lcd_WriteData(0x2C); 
	Lcd_WriteData(0x2D); 

	Lcd_WriteIndex(0xB2); 
	Lcd_WriteData(0x01); 
	Lcd_WriteData(0x2C); 
	Lcd_WriteData(0x2D); 

	Lcd_WriteIndex(0xB3); 
	Lcd_WriteData(0x01); 
	Lcd_WriteData(0x2C); 
	Lcd_WriteData(0x2D); 
	Lcd_WriteData(0x01); 
	Lcd_WriteData(0x2C); 
	Lcd_WriteData(0x2D); 
	
	Lcd_WriteIndex(0xB4); //Column inversion 
	Lcd_WriteData(0x07); 
	
	//ST7735R Power Sequence
	Lcd_WriteIndex(0xC0); 
	Lcd_WriteData(0xA2); 
	Lcd_WriteData(0x02); 
	Lcd_WriteData(0x84); 
	Lcd_WriteIndex(0xC1); 
	Lcd_WriteData(0xC5); 

	Lcd_WriteIndex(0xC2); 
	Lcd_WriteData(0x0A); 
	Lcd_WriteData(0x00); 

	Lcd_WriteIndex(0xC3); 
	Lcd_WriteData(0x8A); 
	Lcd_WriteData(0x2A); 
	Lcd_WriteIndex(0xC4); 
	Lcd_WriteData(0x8A); 
	Lcd_WriteData(0xEE); 
	
	Lcd_WriteIndex(0xC5); //VCOM 
	Lcd_WriteData(0x0E); 
	
	Lcd_WriteIndex(0x36); //MX, MY, RGB mode 
	Lcd_WriteData(0xC0); 
	
	//ST7735R Gamma Sequence
	Lcd_WriteIndex(0xe0); 
	Lcd_WriteData(0x0f); 
	Lcd_WriteData(0x1a); 
	Lcd_WriteData(0x0f); 
	Lcd_WriteData(0x18); 
	Lcd_WriteData(0x2f); 
	Lcd_WriteData(0x28); 
	Lcd_WriteData(0x20); 
	Lcd_WriteData(0x22); 
	Lcd_WriteData(0x1f); 
	Lcd_WriteData(0x1b); 
	Lcd_WriteData(0x23); 
	Lcd_WriteData(0x37); 
	Lcd_WriteData(0x00); 	
	Lcd_WriteData(0x07); 
	Lcd_WriteData(0x02); 
	Lcd_WriteData(0x10); 

	Lcd_WriteIndex(0xe1); 
	Lcd_WriteData(0x0f); 
	Lcd_WriteData(0x1b); 
	Lcd_WriteData(0x0f); 
	Lcd_WriteData(0x17); 
	Lcd_WriteData(0x33); 
	Lcd_WriteData(0x2c); 
	Lcd_WriteData(0x29); 
	Lcd_WriteData(0x2e); 
	Lcd_WriteData(0x30); 
	Lcd_WriteData(0x30); 
	Lcd_WriteData(0x39); 
	Lcd_WriteData(0x3f); 
	Lcd_WriteData(0x00); 
	Lcd_WriteData(0x07); 
	Lcd_WriteData(0x03); 
	Lcd_WriteData(0x10);  
	
	Lcd_WriteIndex(0x2a);
	Lcd_WriteData(0x00);
	Lcd_WriteData(0x00);
	Lcd_WriteData(0x00);
	Lcd_WriteData(0x7f);

	Lcd_WriteIndex(0x2b);
	Lcd_WriteData(0x00);
	Lcd_WriteData(0x00);
	Lcd_WriteData(0x00);
	Lcd_WriteData(0x9f);
	
	Lcd_WriteIndex(0xF0); //Enable test command  
	Lcd_WriteData(0x01); 
	Lcd_WriteIndex(0xF6); //Disable ram power save mode 
	Lcd_WriteData(0x00); 
	
	Lcd_WriteIndex(0x3A); //65k mode 
	Lcd_WriteData(0x05); 
	
	Lcd_WriteIndex(0x29);//Display on	 
}


/*************************************************
函数名:LCD_Set_Region
功能:设置lcd显示区域,在此区域写点数据自动换行
入口参数:xy起点和终点
返回值:无
*************************************************/
void Lcd_SetRegion(u16 x_start,u16 y_start,u16 x_end,u16 y_end)
{		
	Lcd_WriteIndex(0x2a);
	Lcd_WriteData(0x00);
	Lcd_WriteData(x_start);//Lcd_WriteData(x_start+2);
	Lcd_WriteData(0x00);
	Lcd_WriteData(x_end+2);

	Lcd_WriteIndex(0x2b);
	Lcd_WriteData(0x00);
	Lcd_WriteData(y_start+0);
	Lcd_WriteData(0x00);
	Lcd_WriteData(y_end+1);
	
	Lcd_WriteIndex(0x2c);

}

/*************************************************
函数名:LCD_Set_XY
功能:设置lcd显示起始点
入口参数:xy坐标
返回值:无
*************************************************/
void Lcd_SetXY(u16 x,u16 y)
{
  	Lcd_SetRegion(x,y,x,y);
}

	
/*************************************************
函数名:LCD_DrawPoint
功能:画一个点
入口参数:无
返回值:无
*************************************************/
void Gui_DrawPoint(u16 x,u16 y,u16 Data)
{
	Lcd_SetRegion(x,y,x+1,y+1);
	LCD_WriteData_16Bit(Data);

}    

/*****************************************
 函数功能:读TFT某一点的颜色                          
 出口参数:color  点颜色值                                 
******************************************/
unsigned int Lcd_ReadPoint(u16 x,u16 y)
{
  unsigned int Data;
  Lcd_SetXY(x,y);

  //Lcd_ReadData();//丢掉无用字节
  //Data=Lcd_ReadData();
  Lcd_WriteData(Data);
  return Data;
}
/*************************************************
函数名:Lcd_Clear
功能:全屏清屏函数
入口参数:填充颜色COLOR
返回值:无
*************************************************/
void Lcd_Clear(u16 Color)               
{	
   unsigned int i,m;
   Lcd_SetRegion(0,0,X_MAX_PIXEL-1,Y_MAX_PIXEL-1);
   Lcd_WriteIndex(0x2C);
   for(i=0;i<X_MAX_PIXEL;i++)
    for(m=0;m<Y_MAX_PIXEL;m++)
    {	
	  	LCD_WriteData_16Bit(Color);
    }   
}

void LCD_Show_Info(uint16_t x, uint16_t y, const lv_font_t *font, const lv_color_t value, const char *format, ...)
{
	static lv_obj_t * label = NULL;
	char buf[128];  // 定义一个足够大的缓冲区用于存储格式化后的字符串
	va_list args;

	va_start(args, format);  // 初始化可变参数列表
	vsnprintf(buf, sizeof(buf), format, args);  // 将格式化后的字符串存储到缓冲区
	va_end(args);  // 结束可变参数处理

	if (label != NULL) {
        // 清除旧标签内容
        lv_obj_del(label); // 删除标签
        label = NULL;
    }
	
	//lv_obj_t * label = lv_label_create(lv_scr_act());
	label = lv_label_create(lv_scr_act());
    lv_label_set_text(label, buf);
	static lv_style_t label_style;
    lv_style_init(&label_style);
    lv_style_set_text_font(&label_style, font);                    // 设置字体
    lv_style_set_text_color(&label_style, value); // 设置字体颜色
    lv_obj_add_style(label, &label_style, LV_PART_MAIN);
	lv_obj_align(label, LV_ALIGN_OUT_LEFT_TOP, x, y);
	
	//Gui_DrawFont_GBK16(x, y, BLUE, GRAY0, buf);  // 调用显示函数,将格式化后的字符串显示到 LCD 上
}

液晶驱动初始化
LCD_Driver_Init 函数是液晶屏初始化的关键,负责:
启用SPI时钟和GPIO时钟。
设置SPI接口的工作模式。
配置液晶的复位、显示控制等GPIO引脚。
配置SPI工作模式:设置数据方向、数据位宽、时钟极性和相位等。

LCD初始化
Lcd_Init 函数通过对LCD发送一系列初始化命令,配置LCD的显示模式、亮度、对比度等参数。包括:
退出休眠模式,恢复显示。
设置显示区域、显示方向、RGB模式。
配置驱动IC的Gamma曲线,以提高显示质量。

设置显示区域
Lcd_SetRegion 函数用于设置LCD的显示区域。通过传递起始和结束坐标来指定需要显示内容的区域,减少不必要的刷新,提高显示效率。

绘制点
Gui_DrawPoint 函数用于在指定坐标位置绘制一个点。首先通过 Lcd_SetRegion 设置显示区域,然后使用 LCD_WriteData_16Bit 向LCD写入颜色数据。颜色值以16位数据格式(RGB565)表示。

清屏功能
Lcd_Clear 函数实现了全屏清除功能。它通过设置整个屏幕为指定颜色来清除显示内容。此函数可以用来在显示新内容之前清空屏幕。

显示文本
LCD_Show_Info 函数用于将格式化的文本显示在LCD屏幕上。它通过 vsnprintf 将传入的文本格式化后显示,支持动态变化的文本内容。

总结 

其实这个非常简单,这些代码也不可能是我们全部自己手敲的,我们买到屏幕,向厂家要个驱动代码就行,由于代码封装的非常好,我们只需要根据我们的接线,修改对应的宏就行了,修改宏地方如下:

移植完之后,我们之后只要调用对应的函数来显示我们的内容即可,由于我们用的是LVGL,我们只需要告诉LVGL打点函数,之后他就会根据我们给的打点函数,来绘制出我们需要的GUI界面了,这个我们在学习LVGL的时候应该学习过,如图所示:

做完这最后一步,我们就成功移植了我们的屏幕了到LVGL上面了,非常简单。


http://www.kler.cn/a/522627.html

相关文章:

  • Spring MVC 综合案例
  • 计算机网络之计算机网络主要性能
  • 低代码产品表单渲染架构
  • Nuitka打包python脚本
  • DPO、KTO、DiffusionDPO
  • JAVA实战开源项目:蜗牛兼职平台(Vue+SpringBoot) 附源码
  • Java学习笔记(二十五)
  • Python面向对象编程实战:构建强大的 `Person` 类
  • CSS知识总结
  • zookeeper-3.8.3-基于ACL的访问控制
  • 私域流量池构建与转化策略:以开源链动2+1模式AI智能名片S2B2C商城小程序为例
  • Hive详细讲解-调优分区表速通
  • The Simulation技术浅析(二):模型技术
  • Python爬虫获取custom-1688自定义API操作接口
  • 【异步编程基础】FutureTask基本原理与异步阻塞问题
  • constexpr 实现编译时加密
  • Spark入门(Python)
  • python基础语法(4) ----- 学习笔记分享
  • 基于SpringBoot的网上摄影工作室开发与实现 | 含论文、任务书、选题表
  • 【JavaSE】String类常用字符串方法总结
  • Django-Admin WebView 集成项目技术规范文档 v2.1
  • 【2024年华为OD机试】 (C卷,100分)- 用户调度问题(JavaScriptJava PythonC/C++)
  • games101-(2)线性代数
  • LosslessScaling-学习版[steam价值30元的游戏无损放大/补帧工具]
  • Unexpected WSL error Error code: Wsl/Service/0x8007273的解决
  • 【creo】CREO配置快捷键方式和默认单位