找了好久没找到能用的,就自己移植HAL库,现在分享一下
最近屏幕涨价不少,为了图便宜就在某宝花了23买了一块1.8寸无触摸TFT(ST7735)的屏幕,买回来后发现跟其他的有些许不太一样,网上没看见相关参考,仅有几个店家给的例程,但是例程里面的针脚定义跟我拿到手的也不一样,没办法控制背光,我拿到的就是下面这块屏幕
可以看到仅有CLK、SDA(MOSI)、RS、RST、CS五个有效引脚,少了控制背光LED引脚的,但是这并不是大问题,因为项目其他功能都是使用HAL库开发,所以就只能把STM32F103固件库的驱动例程自己改一下移植到STM32F407HAL库上。
目录
硬件平台
本次使用的硬件平台是STM32F407VET6核心板
软件则用的是 Keil5.35 和 STM32CubeMX
接线方式
- VCC 3.3V(5V容易烧坏屏幕)
- GND GND
- GND GND
- NC 悬空
- NC 悬空
- NC 悬空
- CLK PD0
- SDA/MOSI PD1
- RS/DC PD2
- RST/RES PD3
- CS/CE PD4
STM32CubeMX配置
第一步选择芯片:
然后找到你开发板上的芯片型号(我推荐是把自己开发板上的芯片型号点哪个星星收藏一下,下次直接点搜索框旁边的收藏夹就能直接选择了)
第二步开启调试(防止芯片锁住)并配置IO口
选择使用外部高速时钟HSE
配置IO
后面的四个配置方式一样无上下拉,推挽输出,并把IO速率开到最高very high(为了屏幕刷新快一点 )
第三步配置时钟
因为板子上带的是8M的晶振所以需要改一下,cubemx默认25M晶振
第四步设置工程配置
最后一步生成代码
先生成报告,得到一个cubemx的ioc文件等后续还可以继续配置
接着点右上角生成代码(生成代码的路径不能存在中文,否则生成代码会失败)
生成成功后直接点击打开工程
打开工程后配置一下下载
接着选择pack取消掉(防止下载后不会复位运行)
完成之后先编译一遍工程
然后回到工程目录创建一文件用来装移植过来的程序
打开里面放移植的程序
回到keil接着点这个
接着新建一个
选中新键的往里面添加文件
找到刚刚移植过来的C文件添加进去再点ok
接着添加头文件目录
接着新建一个路径,点旁边序号选择头文件路径
然后点ok
到这里大部分移植过程已经完成了,接下来就是改代码
代码部分
Lcd_Driver.h(部分代码)
#include "stm32f4xx_hal.h"
#include "stm32f407xx.h"
#define RED 0xf800
#define GREEN 0x07e0
#define BLUE 0x001f
#define WHITE 0xffff
#define BLACK 0x0000
#define YELLOW 0xFFE0
#define GRAY0 0xEF7D //灰色0 3165 00110 001011 00101
#define GRAY1 0x8410 //灰色1 00000 000000 00000
#define GRAY2 0x4208 //灰色2 1111111111011111
#define LCD_CTRL GPIOD //定义TFT数据端口
#define LCD_RS GPIO_PIN_2 //TFT --RS/DC
#define LCD_CS GPIO_PIN_4 //TFT --CS/CE
#define LCD_RST GPIO_PIN_3 //TFT --RST
#define LCD_SCL GPIO_PIN_0 //TFT --SCL/SCK
#define LCD_SDA GPIO_PIN_1 //TFT --SDA/DIN
#define LCD_CS_SET LCD_CTRL->BSRR=LCD_CS
#define LCD_RS_SET LCD_CTRL->BSRR=LCD_RS
#define LCD_SDA_SET LCD_CTRL->BSRR=LCD_SDA
#define LCD_SCL_SET LCD_CTRL->BSRR=LCD_SCL
#define LCD_RST_SET LCD_CTRL->BSRR=LCD_RST
#define LCD_LED_SET LCD_CTRL->BSRR=LCD_LED
void LCD_GPIO_Init(void);
void Lcd_WriteIndex(uint8_t Index);
void Lcd_WriteData(uint8_t Data);
void Lcd_WriteReg(uint8_t Index,uint8_t Data);
uint16_t Lcd_ReadReg(uint8_t LCD_Reg);
void Lcd_Reset(void);
void Lcd_Init();
void Lcd_Clear(uint16_t Color);
void Lcd_SetXY(uint16_t x,uint16_t y);
void Gui_DrawPoint(uint16_t x,uint16_t y,uint16_t Data);
unsigned int Lcd_ReadPoint(uint16_t x,uint16_t y);
Lcd_Driver.c(部分代码)
/******************************************************************************
接口定义在Lcd_Driver.h内
#define LCD_CTRL GPIOD
#define LCD_SCL GPIO_Pin_0 //SCL/SCK
#define LCD_SDA GPIO_Pin_1 //SDA/DIN
#define LCD_RS GPIO_Pin_2 //RS/DC
#define LCD_RST GPIO_Pin_3 //RST
#define LCD_CS GPIO_Pin_4 //CS/CE
*******************************************************************************/
void LCD_GPIO_Init(void)
{
GPIO_InitTypeDef GPIO_InitStruct = {0};
__HAL_RCC_GPIOD_CLK_ENABLE();
GPIO_InitStruct.Pin = GPIO_PIN_0|GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_3
|GPIO_PIN_4;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
HAL_GPIO_Init(GPIOD, &GPIO_InitStruct);
}
/****************************************************************************
* 名 称:Lcd_WriteIndex(uint8_t Index)
* 功 能:写 ST7735 控制器寄存器地址
* 入口参数:Index 寄存器地址
* 出口参数:无
* 说 明:调用前需先选中控制器,内部函数
* 调用方法:Lcd_WriteIndex(0xB1);
****************************************************************************/
void Lcd_WriteIndex(uint8_t Index)
{
uint8_t i=0;
//SPI 写命令时序开始
LCD_CS_CLR;
LCD_RS_CLR;
for(i=8;i>0;i--)
{
if(Index&0x80){
LCD_SDA_SET; }//输出数据
else
LCD_SDA_CLR;
LCD_SCL_CLR;
LCD_SCL_SET;
Index<<=1;
}
LCD_CS_SET;
}
/****************************************************************************
* 名 称:void Lcd_WriteData(uint8_t Data)
* 功 能:写 ST7735 寄存器数据
* 入口参数:Data 寄存器数据
* 出口参数:无
* 说 明:向控制器指定地址写入数据,调用前需先写寄存器地址,内部函数
* 调用方法:Lcd_WriteData(0x01);
****************************************************************************/
void Lcd_WriteData(uint8_t Data)
{
uint8_t i=0;
LCD_CS_CLR;
LCD_RS_SET;
for(i=8;i>0;i--)
{
if(Data&0x80) {
LCD_SDA_SET;} //输出数据
else LCD_SDA_CLR;
LCD_SCL_CLR;
LCD_SCL_SET;
Data<<=1;
}
LCD_CS_SET;
}
/*************************************************
函数名:Lcd_WriteReg
功能:写寄存器
入口参数:Index,Data
返回值:无
*************************************************/
void Lcd_WriteReg(uint8_t Index,uint8_t Data)
{
Lcd_WriteIndex(Index);
Lcd_WriteData(Data);
}
/*************************************************
函数名:Lcd_Reset
功能:重置LCD
入口参数:无
返回值:无
*************************************************/
void Lcd_Reset(void)
{
LCD_RST_CLR;
HAL_Delay(100);
LCD_RST_SET;
HAL_Delay(50);
}
/*************************************************
函数名:Lcd_SetRegion
功能:设置lcd显示区域,在此区域写点数据自动换行
入口参数:x_start起点,y_start起点,x_end,y_end终点
返回值:无
*************************************************/
void Lcd_SetRegion(uint16_t x_start,uint16_t y_start,uint16_t x_end,uint16_t y_end)
{
Lcd_WriteIndex(0x2a);
Lcd_WriteData(0x00);
Lcd_WriteData(x_start);
Lcd_WriteData(0x00);
Lcd_WriteData(x_end);
Lcd_WriteIndex(0x2b);
Lcd_WriteData(0x00);
Lcd_WriteData(y_start);
Lcd_WriteData(0x00);
Lcd_WriteData(y_end);
Lcd_WriteIndex(0x2c);
}
/*************************************************
函数名:Lcd_SetXY
功能:设置lcd显示起始点
入口参数:xy坐标
返回值:无
*************************************************/
void Lcd_SetXY(uint16_t x,uint16_t y)
{
Lcd_SetRegion(x,y,x,y);
}
/*************************************************
函数名:Gui_DrawPoint
功能:画一个点
入口参数:x,y,Data
返回值:无
*************************************************/
void Gui_DrawPoint(uint16_t x,uint16_t y,uint16_t Data)
{
Lcd_SetRegion(x,y,x+1,y+1);
Lcd_WriteData(Data>>8);
Lcd_WriteData(Data);
}
/*****************************************
函数名:Lcd_ReadPoint
函数功能:读TFT某一点的颜色
出口参数:Data 点颜色值
******************************************/
unsigned int Lcd_ReadPoint(uint16_t x,uint16_t y)
{
unsigned int Data;
Lcd_SetXY(x,y);
//Lcd_ReadData();//丢掉无用字节
//Data=Lcd_ReadData();
Lcd_WriteData(Data);
return Data;
}
/*************************************************
函数名:Lcd_Clear
功能:全屏清屏函数
入口参数:填充颜色Color
返回值:无
*************************************************/
void Lcd_Clear(uint16_t Color)
{
unsigned int i,m;
Lcd_SetRegion(0,0,X_MAX_PIXEL-1,Y_MAX_PIXEL-1);
Lcd_WriteIndex(0x2C);
for(i=0;i<128;i++)
for(m=0;m<160;m++)
{
Lcd_WriteData(Color>>8);
Lcd_WriteData(Color);
}
}
上面值得注意的是F103的BSRR置位寄存器和BRR复位寄存器在F407中都已经变成
如果屏幕边上有花屏,表示像素没填充够,修改Lcd_Driver.c和GUI.c内循环体数值即可
而整个屏幕图形显示函数的编写实现实际上就是点亮对应坐标像素并显示颜色
好了到这里全部工作就已经全部完成,烧录看一下效果。
运行效果
可以看见屏幕刷新率还是蛮快的,得益于STM32F407IO速率的提升
而F103则相对慢一些
取模部分
图片取模
文字取模
当然了STM32F103C8T6HAL库也移植有,如果有需要在评论留言。
代码我已经上传,有积分的好兄弟给点,没有的评论留个邮箱
版权声明:本文为CSDN博主「fbuilke」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/m0_50846041/article/details/119433305
找了好久没找到能用的,就自己移植HAL库,现在分享一下
最近屏幕涨价不少,为了图便宜就在某宝花了23买了一块1.8寸无触摸TFT(ST7735)的屏幕,买回来后发现跟其他的有些许不太一样,网上没看见相关参考,仅有几个店家给的例程,但是例程里面的针脚定义跟我拿到手的也不一样,没办法控制背光,我拿到的就是下面这块屏幕
可以看到仅有CLK、SDA(MOSI)、RS、RST、CS五个有效引脚,少了控制背光LED引脚的,但是这并不是大问题,因为项目其他功能都是使用HAL库开发,所以就只能把STM32F103固件库的驱动例程自己改一下移植到STM32F407HAL库上。
目录
硬件平台
本次使用的硬件平台是STM32F407VET6核心板
软件则用的是 Keil5.35 和 STM32CubeMX
接线方式
- VCC 3.3V(5V容易烧坏屏幕)
- GND GND
- GND GND
- NC 悬空
- NC 悬空
- NC 悬空
- CLK PD0
- SDA/MOSI PD1
- RS/DC PD2
- RST/RES PD3
- CS/CE PD4
STM32CubeMX配置
第一步选择芯片:
然后找到你开发板上的芯片型号(我推荐是把自己开发板上的芯片型号点哪个星星收藏一下,下次直接点搜索框旁边的收藏夹就能直接选择了)
第二步开启调试(防止芯片锁住)并配置IO口
选择使用外部高速时钟HSE
配置IO
后面的四个配置方式一样无上下拉,推挽输出,并把IO速率开到最高very high(为了屏幕刷新快一点 )
第三步配置时钟
因为板子上带的是8M的晶振所以需要改一下,cubemx默认25M晶振
第四步设置工程配置
最后一步生成代码
先生成报告,得到一个cubemx的ioc文件等后续还可以继续配置
接着点右上角生成代码(生成代码的路径不能存在中文,否则生成代码会失败)
生成成功后直接点击打开工程
打开工程后配置一下下载
接着选择pack取消掉(防止下载后不会复位运行)
完成之后先编译一遍工程
然后回到工程目录创建一文件用来装移植过来的程序
打开里面放移植的程序
回到keil接着点这个
接着新建一个
选中新键的往里面添加文件
找到刚刚移植过来的C文件添加进去再点ok
接着添加头文件目录
接着新建一个路径,点旁边序号选择头文件路径
然后点ok
到这里大部分移植过程已经完成了,接下来就是改代码
代码部分
Lcd_Driver.h(部分代码)
#include "stm32f4xx_hal.h"
#include "stm32f407xx.h"
#define RED 0xf800
#define GREEN 0x07e0
#define BLUE 0x001f
#define WHITE 0xffff
#define BLACK 0x0000
#define YELLOW 0xFFE0
#define GRAY0 0xEF7D //灰色0 3165 00110 001011 00101
#define GRAY1 0x8410 //灰色1 00000 000000 00000
#define GRAY2 0x4208 //灰色2 1111111111011111
#define LCD_CTRL GPIOD //定义TFT数据端口
#define LCD_RS GPIO_PIN_2 //TFT --RS/DC
#define LCD_CS GPIO_PIN_4 //TFT --CS/CE
#define LCD_RST GPIO_PIN_3 //TFT --RST
#define LCD_SCL GPIO_PIN_0 //TFT --SCL/SCK
#define LCD_SDA GPIO_PIN_1 //TFT --SDA/DIN
#define LCD_CS_SET LCD_CTRL->BSRR=LCD_CS
#define LCD_RS_SET LCD_CTRL->BSRR=LCD_RS
#define LCD_SDA_SET LCD_CTRL->BSRR=LCD_SDA
#define LCD_SCL_SET LCD_CTRL->BSRR=LCD_SCL
#define LCD_RST_SET LCD_CTRL->BSRR=LCD_RST
#define LCD_LED_SET LCD_CTRL->BSRR=LCD_LED
void LCD_GPIO_Init(void);
void Lcd_WriteIndex(uint8_t Index);
void Lcd_WriteData(uint8_t Data);
void Lcd_WriteReg(uint8_t Index,uint8_t Data);
uint16_t Lcd_ReadReg(uint8_t LCD_Reg);
void Lcd_Reset(void);
void Lcd_Init();
void Lcd_Clear(uint16_t Color);
void Lcd_SetXY(uint16_t x,uint16_t y);
void Gui_DrawPoint(uint16_t x,uint16_t y,uint16_t Data);
unsigned int Lcd_ReadPoint(uint16_t x,uint16_t y);
Lcd_Driver.c(部分代码)
/******************************************************************************
接口定义在Lcd_Driver.h内
#define LCD_CTRL GPIOD
#define LCD_SCL GPIO_Pin_0 //SCL/SCK
#define LCD_SDA GPIO_Pin_1 //SDA/DIN
#define LCD_RS GPIO_Pin_2 //RS/DC
#define LCD_RST GPIO_Pin_3 //RST
#define LCD_CS GPIO_Pin_4 //CS/CE
*******************************************************************************/
void LCD_GPIO_Init(void)
{
GPIO_InitTypeDef GPIO_InitStruct = {0};
__HAL_RCC_GPIOD_CLK_ENABLE();
GPIO_InitStruct.Pin = GPIO_PIN_0|GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_3
|GPIO_PIN_4;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
HAL_GPIO_Init(GPIOD, &GPIO_InitStruct);
}
/****************************************************************************
* 名 称:Lcd_WriteIndex(uint8_t Index)
* 功 能:写 ST7735 控制器寄存器地址
* 入口参数:Index 寄存器地址
* 出口参数:无
* 说 明:调用前需先选中控制器,内部函数
* 调用方法:Lcd_WriteIndex(0xB1);
****************************************************************************/
void Lcd_WriteIndex(uint8_t Index)
{
uint8_t i=0;
//SPI 写命令时序开始
LCD_CS_CLR;
LCD_RS_CLR;
for(i=8;i>0;i--)
{
if(Index&0x80){
LCD_SDA_SET; }//输出数据
else
LCD_SDA_CLR;
LCD_SCL_CLR;
LCD_SCL_SET;
Index<<=1;
}
LCD_CS_SET;
}
/****************************************************************************
* 名 称:void Lcd_WriteData(uint8_t Data)
* 功 能:写 ST7735 寄存器数据
* 入口参数:Data 寄存器数据
* 出口参数:无
* 说 明:向控制器指定地址写入数据,调用前需先写寄存器地址,内部函数
* 调用方法:Lcd_WriteData(0x01);
****************************************************************************/
void Lcd_WriteData(uint8_t Data)
{
uint8_t i=0;
LCD_CS_CLR;
LCD_RS_SET;
for(i=8;i>0;i--)
{
if(Data&0x80) {
LCD_SDA_SET;} //输出数据
else LCD_SDA_CLR;
LCD_SCL_CLR;
LCD_SCL_SET;
Data<<=1;
}
LCD_CS_SET;
}
/*************************************************
函数名:Lcd_WriteReg
功能:写寄存器
入口参数:Index,Data
返回值:无
*************************************************/
void Lcd_WriteReg(uint8_t Index,uint8_t Data)
{
Lcd_WriteIndex(Index);
Lcd_WriteData(Data);
}
/*************************************************
函数名:Lcd_Reset
功能:重置LCD
入口参数:无
返回值:无
*************************************************/
void Lcd_Reset(void)
{
LCD_RST_CLR;
HAL_Delay(100);
LCD_RST_SET;
HAL_Delay(50);
}
/*************************************************
函数名:Lcd_SetRegion
功能:设置lcd显示区域,在此区域写点数据自动换行
入口参数:x_start起点,y_start起点,x_end,y_end终点
返回值:无
*************************************************/
void Lcd_SetRegion(uint16_t x_start,uint16_t y_start,uint16_t x_end,uint16_t y_end)
{
Lcd_WriteIndex(0x2a);
Lcd_WriteData(0x00);
Lcd_WriteData(x_start);
Lcd_WriteData(0x00);
Lcd_WriteData(x_end);
Lcd_WriteIndex(0x2b);
Lcd_WriteData(0x00);
Lcd_WriteData(y_start);
Lcd_WriteData(0x00);
Lcd_WriteData(y_end);
Lcd_WriteIndex(0x2c);
}
/*************************************************
函数名:Lcd_SetXY
功能:设置lcd显示起始点
入口参数:xy坐标
返回值:无
*************************************************/
void Lcd_SetXY(uint16_t x,uint16_t y)
{
Lcd_SetRegion(x,y,x,y);
}
/*************************************************
函数名:Gui_DrawPoint
功能:画一个点
入口参数:x,y,Data
返回值:无
*************************************************/
void Gui_DrawPoint(uint16_t x,uint16_t y,uint16_t Data)
{
Lcd_SetRegion(x,y,x+1,y+1);
Lcd_WriteData(Data>>8);
Lcd_WriteData(Data);
}
/*****************************************
函数名:Lcd_ReadPoint
函数功能:读TFT某一点的颜色
出口参数:Data 点颜色值
******************************************/
unsigned int Lcd_ReadPoint(uint16_t x,uint16_t y)
{
unsigned int Data;
Lcd_SetXY(x,y);
//Lcd_ReadData();//丢掉无用字节
//Data=Lcd_ReadData();
Lcd_WriteData(Data);
return Data;
}
/*************************************************
函数名:Lcd_Clear
功能:全屏清屏函数
入口参数:填充颜色Color
返回值:无
*************************************************/
void Lcd_Clear(uint16_t Color)
{
unsigned int i,m;
Lcd_SetRegion(0,0,X_MAX_PIXEL-1,Y_MAX_PIXEL-1);
Lcd_WriteIndex(0x2C);
for(i=0;i<128;i++)
for(m=0;m<160;m++)
{
Lcd_WriteData(Color>>8);
Lcd_WriteData(Color);
}
}
上面值得注意的是F103的BSRR置位寄存器和BRR复位寄存器在F407中都已经变成
如果屏幕边上有花屏,表示像素没填充够,修改Lcd_Driver.c和GUI.c内循环体数值即可
而整个屏幕图形显示函数的编写实现实际上就是点亮对应坐标像素并显示颜色
好了到这里全部工作就已经全部完成,烧录看一下效果。
运行效果
可以看见屏幕刷新率还是蛮快的,得益于STM32F407IO速率的提升
而F103则相对慢一些
取模部分
图片取模
文字取模
当然了STM32F103C8T6HAL库也移植有,如果有需要在评论留言。
代码我已经上传,有积分的好兄弟给点,没有的评论留个邮箱
版权声明:本文为CSDN博主「fbuilke」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/m0_50846041/article/details/119433305
暂无评论