目录
前言
本人平时忙于做项目,懒得写文章,借着工作摸鱼的时间写一下,好记录一下自己的学习记录和遇到的坑。之前接触的都是0.96寸OLED显示屏,没怎么用其他屏,还以为其他屏没有那么难,没想到还是有点难度,特别是越学到最后涉及到的知识点和坑就越多。这是本人第一次在CSDN写的文章,所以写的会有点草率。废话不多说,本文章采用的是直接将图片存到STM32的RAM中,然后将读RAM的值,转发给0.99寸TFT屏的显示方法,这种的优点是显示速度快,缺点就是主控芯片的RAM有限,存不了多少张图片。
一、0.99英寸彩色TFT屏幕
黄保凯中景园0.99寸TFT LCD彩屏高清IPS显示屏液晶屏GC9107圆屏,以下是屏幕实物图
0.99寸TFT LCD彩屏
买这个裸屏需要自己画一个转接板,FPC连接器连接裸屏,另一个端子连接主控板。
以下是0.99寸TFT LCD彩屏转接板原理图:
二、硬件设计
STM32F103RCT6与0.99寸TFT圆屏硬件连接图如下:
STM32F103RCT6 | 0.99寸TFT圆屏 |
---|---|
3.3V | VCC |
GND | GND |
PB7 | SDA_MOSI |
PB6 | SCL_SCLK |
PB5 | RES |
PB4 | DC |
PB3 | CS |
PD2 | BLK |
实物图如下:
三、将图片转成二进制数组
1、由于该屏的像素大小是128*115的,所以在将图片转成二进制数组前,先将图片的像素点转成128*115的。
将鼠标移到图片位置,右键->打开方式->画图,如下图:
可以看到这个图片还是240*240像素的,不是我们需要的128*115像素的,点击菜单栏上的图像->重新调整大小
切换到像素选项,取消勾选“保持纵横比(M)”,在水平输入128,垂直输入115,点击确定
点击确定后,可以看到图片像素已经改好了,点击保存
2、打开Img2Lcd软件,软件界面如下:
点击菜单栏中的打开,选择要取模的图片并打开,如下图:
观察左下角的输入图像
打开图片后 设置如下
输出数据类型:
扫描模式
输出灰度
最大宽度和高度
在16位彩色的颜色数据排列为 :红色 绿色 蓝色
设置好后点击一下
注意:此软件只能缩小图片不能放大图片!缩小是等比例缩小!
然后观察右下角这个输出图像是实际生成的图片的大小
这一部分勾选高位在前
然后点击保存,选择要保存的位置和命名
然后打开这个文件,可以看到图片已经生成二进制数组了
然后将生成的数组复制到到例程pic.h文件内,直接调用这个数组发送给屏幕就能显示了
完整界面如下:
四、软件解析
采用的是软件SPI,所以速度相对较慢,本程序是鉴于中景园的程序上修改。这里按.c文件介绍。
①lcd_init
先配置TFT屏的引脚,按上面讲的硬件设计对应配置:
void LCD_GPIO_Init(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB|RCC_APB2Periph_GPIOD, ENABLE); //使能A端口时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);//打开AFIO(复用功能)时钟
GPIO_PinRemapConfig(GPIO_Remap_SWJ_JTAGDisable, ENABLE); //改变指定管脚的映射,JTAG的其他引脚PA15 PB3、PB4有其他用途,设置关闭JTAG部分功能,保留SWD功能
//SCL:该引脚用于串行接口时钟;SDA:SPI接口输入/输出引脚,数据被锁存在SPI接口的上升沿。SCL 信号。
//RES:此信号将重置设备,必须应用该信号才能正确初始化芯片。信号处于低电平有效状态。
//DC:在 4 行串行接口中显示数据/命令选择引脚。;CS:芯片选择引脚;低启用,高禁用
//CS、DC、RES、SCL=SCLK、SDA=MOSI
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3|GPIO_Pin_4|GPIO_Pin_5|GPIO_Pin_6|GPIO_Pin_7;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; //推挽输出
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;//速度50MHz
GPIO_Init(GPIOB, &GPIO_InitStructure);
GPIO_SetBits(GPIOB,GPIO_Pin_3|GPIO_Pin_4|GPIO_Pin_5|GPIO_Pin_6|GPIO_Pin_7);
//BLK:液晶屏背光控制信号,高电平点亮
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2;
GPIO_Init(GPIOD, &GPIO_InitStructure);
GPIO_SetBits(GPIOD,GPIO_Pin_2);
}
软件SPI发送、接收程序
/******************************************************************************
函数说明:LCD串行数据写入函数
入口数据:dat 要写入的串行数据
返回值: 无
******************************************************************************/
void LCD_Writ_Bus(u8 dat)
{
u8 i;
LCD_CS_Clr();//启用芯片
for(i=0;i<8;i++)
{
LCD_SCLK_Clr();
if(dat&0x80)//先发送高位
{
LCD_MOSI_Set();//主机发送“1”数据
}
else
{
LCD_MOSI_Clr();//主机发送“0”数据
}
LCD_SCLK_Set();//上升沿进行数据采集
dat<<=1;
}
LCD_CS_Set();
}
/******************************************************************************
函数说明:LCD写入数据
入口数据:dat 写入的数据
返回值: 无
******************************************************************************/
void LCD_WR_DATA8(u8 dat)
{
LCD_Writ_Bus(dat);
}
/******************************************************************************
函数说明:LCD写入数据
入口数据:dat 写入的数据
返回值: 无
******************************************************************************/
void LCD_WR_DATA(u16 dat)
{
LCD_Writ_Bus(dat>>8);
LCD_Writ_Bus(dat);
}
/******************************************************************************
函数说明:LCD写入命令
入口数据:dat 写入的命令
返回值: 无
******************************************************************************/
void LCD_WR_REG(u8 dat)
{
LCD_DC_Clr();//写命令
LCD_Writ_Bus(dat);//写数据
LCD_DC_Set();//写数据
}
设置显示屏的显示方向
/******************************************************************************
函数说明:设置起始和结束地址
入口数据:x1,x2 设置列的起始和结束地址
y1,y2 设置行的起始和结束地址
返回值: 无
******************************************************************************/
void LCD_Address_Set(u16 x1,u16 y1,u16 x2,u16 y2)
{
if(USE_HORIZONTAL==0)
{
LCD_WR_REG(0x2a);//列地址设置
LCD_WR_DATA(x1);//列起始地址
LCD_WR_DATA(x2);//列结束地址
LCD_WR_REG(0x2b);//行地址设置
LCD_WR_DATA(y1+45);//行起始地址
LCD_WR_DATA(y2+45);//行结束地址
LCD_WR_REG(0x2c);//储存器写
}
else if(USE_HORIZONTAL==1)
{
LCD_WR_REG(0x2a);//列地址设置
LCD_WR_DATA(x1);
LCD_WR_DATA(x2);
LCD_WR_REG(0x2b);//行地址设置
LCD_WR_DATA(y1);
LCD_WR_DATA(y2);
LCD_WR_REG(0x2c);//储存器写
}
else if(USE_HORIZONTAL==2)
{
LCD_WR_REG(0x2a);//列地址设置
LCD_WR_DATA(x1+45);
LCD_WR_DATA(x2+45);
LCD_WR_REG(0x2b);//行地址设置
LCD_WR_DATA(y1);
LCD_WR_DATA(y2);
LCD_WR_REG(0x2c);//储存器写
}
else if(USE_HORIZONTAL==3)
{
LCD_WR_REG(0x2a);//列地址设置
LCD_WR_DATA(x1);
LCD_WR_DATA(x2);
LCD_WR_REG(0x2b);//行地址设置
LCD_WR_DATA(y1);
LCD_WR_DATA(y2);
LCD_WR_REG(0x2c);//储存器写
}
else if(USE_HORIZONTAL==4)
{
LCD_WR_REG(0x2a);//列地址设置
LCD_WR_DATA(x1);
LCD_WR_DATA(x2);
LCD_WR_REG(0x2b);//行地址设置
LCD_WR_DATA(y1+45);
LCD_WR_DATA(y2+45);
LCD_WR_REG(0x2c);//储存器写
}
else
{
LCD_WR_REG(0x2a);//列地址设置
LCD_WR_DATA(x1);
LCD_WR_DATA(x2);
LCD_WR_REG(0x2b);//行地址设置
LCD_WR_DATA(y1);
LCD_WR_DATA(y2);
LCD_WR_REG(0x2c);//储存器写
}
}
这里的USE_HORIZONTAL值为4和5是本人添加的,可以将USE_HORIZONTAL值为0和1显示方向镜像。这样只需要修改USE_HORIZONTAL的值,就可以设置显示屏显示方向,可以在lcd_init.h里面修改。
#define USE_HORIZONTAL 0 //设置横屏或者竖屏显示 0或1为竖屏 2或3为横屏,4或5为竖屏镜像显示
#if USE_HORIZONTAL==0||USE_HORIZONTAL==1||USE_HORIZONTAL==4||USE_HORIZONTAL==5
#define LCD_W 128 //LCD屏的宽度
#define LCD_H 115 //LCD屏的高度
#else
#define LCD_W 115
#define LCD_H 128
#endif
然后就是0.99寸TFT屏初始化程序。
③lcd.c
lcd.c主要是0.99寸TFT屏显示程序,字符、字符串、中文字符、数字、图片等显示程序,这里就不一 一介绍了。
④main.c
主要是初始化各个函数,显示字符、字符串、中文字符、数字、图片等,还加了光敏二极管,主要用于对光反射。
最终显示效果如下:
总结
采用软件SPI显示,程序简单,容易理解,但是传输速率不高,有明显的感觉到显示方向,适合用于显示图片,不适合动态显示或者显示视频。
最后代码放在CSDN上了,可通过这个链接下载,第一次发布文章,不知道通过这个链接下载要不要钱,如果要钱的话,可以在评论区@我要https://download.csdn.net/download/weixin_45534031/89478446?spm=1001.2014.3001.5503