GC9A01-TFT屏幕驱动&整理有stm32/51单片机/arduino等驱动代码
序言
不久前我们收到用户反馈问题中,多次反馈各类不同机型的屏幕驱动不上去,从0开始编撰代码耗费大量时间,也有不少初次学习驱动屏幕代码编撰经验过少等问题,因此我们决定以文章的方式发布到CSDN来分享相应的一些经验以及搜集整理好的资料,希望可以帮助用户愈发简单的学习或快速移植代码进行项目开发。
后续我们将相继分享有关GCGC99AA0101、ST7789、ST7735、ILI9341等驱动IC的屏幕驱动案例。
须要整理好的代码可以在评论区留言或私信邮箱!
关于GC9A01
市面采用GCGC99AA0101驱动IC的屏幕不多,基本上为1.28寸方形屏,机缘巧合有接触过的这款驱动IC中两款屏幕,其中一款为并行8080插口驱动的触摸屏,目前有编撰stm3232ff101010x相关的代码,但市面上使用者虽然较少,因而本文以另一款屏幕为主。
另一款为串行口驱动的屏幕,不带触摸,长下边这个样子linux系统命令,网上收集加上自己编撰以及移植整理有stm3232ff101010x、stm3232ff407407、arduino、stc8989cc516516、ESP32等单片机代码,须要整理好的代码可以在评论区留言或私信邮箱!
综合了解并观察屏幕一下的一些参数以后开始进行驱动。
硬件插口使用的PH2.0和FPC0.5的两种插口linux 电容触摸屏驱动,配了一根PH2.0转杜邦母头的线,这儿没哪些非常要求肯定是使用PH2.0的插口直接插到stm32开发板上。
GC9A01参数
供电电流
3.3~5.5V
驱动IC
GC9A01
帧率
240x240
规格
1.28
驱动插口
4线SPI
产商在屏幕设计上添加了3.3V稳压芯片以及电平转换芯片,致使这款原先3.3V供电的裸屏可以兼容5V和3.3V的单片机,这也意味着arduino和51单片机的用户也可以驱动这款屏幕了,尽管51单片机性能很通常但总比不能驱动的好。
最后了解各个引脚功能以后就可以开始进行驱动
引脚名称引脚功能
GND
电源负,地
VCC
电源正,3.3-5V,须要与通讯电平一致
SCL
SPI时钟讯号输入端口
SDA
SPI数据输入端口
RES
复位,低电平使能
DC
数据/命令选择,低电平命令,高电平数据
CS
片选,低电平使能
BLK
背光,悬空使能接地关掉,默认上拉至3.3V
stm32驱动引脚接线
代码方面先依照下表接好线烧写程序然后再对代码移植的关键部份进行说明
stm32f10xGC9A01
3V3
VIN
GND
GND
SCL
PA5
SDA
PA4
RES
PA6
DC
PA7
CS
PB6
BLK
PB7
BLK背光引脚不用可以悬空不接
默认的代码烧写进行然后显示里面图片中大大的优信电子logo,先把示例代码驱动上去linux教程下载,假如示例代码驱动不上去先检测一下接线供电方面的问题,不然后边代码改了半天没有用找问题就和我刚驱动的时侯一样头皮发痒。
驱动成功然后用户可以开始移植代码。
代码移植文件复制
将lcd、lcd_init的C文件和肉文件复制到自己的工程上面,这四个文件包含屏幕初始化以及驱动画点划线显示文字图象的代码。
另外还有两个文件为image.h和lcdfont.h,这两个文件分别储存显示图片链表与显示文字链表。
复制到自己工程中编译后会报错,由于缺乏了pbdata.h中的微秒级延时函数,可以把原工程中的ms延时函数复制过来也可以使用自己编撰的,名称与下边的相同即可
void delay_ms(u16 a)
添加好文件到工程上面然后再度编译通常不会报错,假如依然报错就只能看具体报错信息去更改了
和里面的接线不变,编撰下边主函数先进行测试
int main(void)
{
LCD_Init();
LCD_Fill(0,0,LCD_W,LCD_H,WHITE); //填充为白色背景色
while(1)
{
LCD_ShowPicture(0,0,LCD_W,LCD_H,YXDZ_logo); //显示一张图片
}
}
须要用户更改的插口通常有一下几个点
端口更改
lcdfont.h文件中包含对使用引脚的宏定义,更改其中的GPIO以及引脚即可更改使用的端口
//-----------------LCD端口定义----------------
#define LCD_SCLK_Clr() GPIO_ResetBits(GPIOA,GPIO_Pin_5)//SCL=SCLK
#define LCD_SCLK_Set() GPIO_SetBits(GPIOA,GPIO_Pin_5)
#define LCD_MOSI_Clr() GPIO_ResetBits(GPIOA,GPIO_Pin_4)//SDA=MOSI
#define LCD_MOSI_Set() GPIO_SetBits(GPIOA,GPIO_Pin_4)
#define LCD_RES_Clr() GPIO_ResetBits(GPIOA,GPIO_Pin_6)//RES
#define LCD_RES_Set() GPIO_SetBits(GPIOA,GPIO_Pin_6)
#define LCD_DC_Clr() GPIO_ResetBits(GPIOA,GPIO_Pin_7)//DC
#define LCD_DC_Set() GPIO_SetBits(GPIOA,GPIO_Pin_7)
#define LCD_CS_Clr() GPIO_ResetBits(GPIOB,GPIO_Pin_6)//CS
#define LCD_CS_Set() GPIO_SetBits(GPIOB,GPIO_Pin_6)
#define LCD_BLK_Clr() GPIO_ResetBits(GPIOB,GPIO_Pin_7)//BLK
#define LCD_BLK_Set() GPIO_SetBits(GPIOB,GPIO_Pin_7)
但值得注意的是仅仅更改这儿的宏定义是没办法使用的,在lcdfont.c文件中包含着对GPIO引脚以及时钟初始化的函数须要进行端口的更改
void LCD_GPIO_Init(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_GPIOB, ENABLE); //使能端口时钟
GPIO_InitStructure.GPIO_Pin = 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(GPIOA, &GPIO_InitStructure);
GPIO_SetBits(GPIOA,GPIO_Pin_4|GPIO_Pin_5|GPIO_Pin_6|GPIO_Pin_7);
GPIO_InitStructure.GPIO_Pin = 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_6|GPIO_Pin_7);
}
更改完这儿以后才算是将端口更改完毕
在lcdfont.h底部还有两个宏定义可以自行决定是否更改,分别对应这屏幕显示方向和屏幕码率的参数
#define USE_HORIZONTAL 0 //设置横屏或者竖屏显示 0或1为竖屏 2或3为横屏
#define LCD_W 240
#define LCD_H 240
显示函数
在lcd.h中包含了屏幕显示内容的函数,以及部份颜色的色号主要用于刷新屏幕背景色的
void LCD_Fill(u16 xsta,u16 ysta,u16 xend,u16 yend,u16 color);//指定区域填充颜色
void LCD_DrawPoint(u16 x,u16 y,u16 color);//在指定位置画一个点
void LCD_DrawLine(u16 x1,u16 y1,u16 x2,u16 y2,u16 color);//在指定位置画一条线
void LCD_DrawRectangle(u16 x1, u16 y1, u16 x2, u16 y2,u16 color);//在指定位置画一个矩形
void Draw_Circle(u16 x0,u16 y0,u8 r,u16 color);//在指定位置画一个圆
void LCD_ShowChinese(u16 x,u16 y,u8 *s,u16 fc,u16 bc,u8 sizey,u8 mode);//显示汉字串
void LCD_ShowChinese12x12(u16 x,u16 y,u8 *s,u16 fc,u16 bc,u8 sizey,u8 mode);//显示单个12x12汉字
void LCD_ShowChinese16x16(u16 x,u16 y,u8 *s,u16 fc,u16 bc,u8 sizey,u8 mode);//显示单个16x16汉字
void LCD_ShowChinese24x24(u16 x,u16 y,u8 *s,u16 fc,u16 bc,u8 sizey,u8 mode);//显示单个24x24汉字
void LCD_ShowChinese32x32(u16 x,u16 y,u8 *s,u16 fc,u16 bc,u8 sizey,u8 mode);//显示单个32x32汉字
void LCD_ShowChar(u16 x,u16 y,u8 num,u16 fc,u16 bc,u8 sizey,u8 mode);//显示一个字符
void LCD_ShowString(u16 x,u16 y,const u8 *p,u16 fc,u16 bc,u8 sizey,u8 mode);//显示字符串
u32 mypow(u8 m,u8 n);//求幂
void LCD_ShowIntNum(u16 x,u16 y,u16 num,u8 len,u16 fc,u16 bc,u8 sizey);//显示整数变量
void LCD_ShowFloatNum1(u16 x,u16 y,float num,u8 len,u16 fc,u16 bc,u8 sizey);//显示两位小数变量
void LCD_ShowPicture(u16 x,u16 y,u16 length,u16 width,const u8 pic[]);//显示图片
//画笔颜色
#define WHITE 0xFFFF
#define BLACK 0x0000
#define BLUE 0x001F
#define BRED 0XF81F
#define GRED 0XFFE0
#define GBLUE 0X07FF
#define RED 0xF800
#define MAGENTA 0xF81F
#define GREEN 0x07E0
#define CYAN 0x7FFF
#define YELLOW 0xFFE0
#define BROWN 0XBC40 //棕色
#define BRRED 0XFC07 //棕红色
#define GRAY 0X8430 //灰色
#define DARKBLUE 0X01CF //深蓝色
#define LIGHTBLUE 0X7D7C //浅蓝色
#define GRAYBLUE 0X5458 //灰蓝色
#define LIGHTGREEN 0X841F //浅绿色
#define LGRAY 0XC618 //浅灰色(PANNEL),窗体背景色
#define LGRAYBLUE 0XA651 //浅灰蓝色(中间层颜色)
#define LBBLUE 0X2B12 //浅棕蓝色(选择条目的反色)
在使用的时侯只须要看前面的英文注释去调用对应的函数即可,十分便捷使用
而且假如须要显示文字和图片的话只是直接调用里面的函数还不够,汉字链表储存的lcdfont.h文件中只包含了中英文字母、数字、符号以及特别少量的英文链表,英文链表储存在以下几个字段中,根据相同的格式自行添加进去即可
英文汉字字段
typedef struct
{
unsigned char Index[2];
unsigned char Msk[24];
}typFNT_GB12;
const typFNT_GB12 tfont12[]={
"优",0x24,0x01,0x24,0x02,0x22,0x00,0xFA,0x07,0xA3,0x00,0xA2,0x00,0xA2,0x00,0xA2,0x00,
0x92,0x00,0x92,0x04,0x8A,0x04,0x06,0x07,
"信",0x44,0x00,0x84,0x00,0xFA,0x07,0x02,0x00,0xF3,0x03,0x02,0x00,0xF2,0x03,0x02,0x00,
0xF2,0x03,0x12,0x02,0xF2,0x03,0x12,0x02,
"电",0x10,0x00,0x10,0x00,0xFF,0x01,0x11,0x01,0x11,0x01,0xFF,0x01,0x11,0x01,0x11,0x01,
0xFF,0x01,0x11,0x04,0x10,0x04,0xE0,0x07,
"子",0x00,0x00,0xFC,0x01,0x80,0x00,0x40,0x00,0x20,0x00,0x20,0x00,0xFF,0x07,0x20,0x00,
0x20,0x00,0x20,0x00,0x20,0x00,0x38,0x00,
};
typedef struct
{
unsigned char Index[2];
unsigned char Msk[32];
}typFNT_GB16;
const typFNT_GB16 tfont16[]={
"优",0x10,0x09,0x10,0x11,0x10,0x11,0x08,0x01,0xE8,0x7F,0x0C,0x05,0x0C,0x05,0x0A,0x05,
0x09,0x05,0x08,0x05,0x88,0x04,0x88,0x44,0x88,0x44,0x48,0x44,0x48,0x78,0x28,0x00,
"信",0x10,0x02,0x10,0x04,0xD0,0x7F,0x08,0x00,0x08,0x00,0x8C,0x3F,0x0C,0x00,0x0A,0x00,
0x89,0x3F,0x08,0x00,0x08,0x00,0x88,0x3F,0x88,0x20,0x88,0x20,0x88,0x3F,0x88,0x20,
"电",0x80,0x00,0x80,0x00,0x80,0x00,0xFC,0x1F,0x84,0x10,0x84,0x10,0x84,0x10,0xFC,0x1F,
0x84,0x10,0x84,0x10,0x84,0x10,0xFC,0x1F,0x84,0x50,0x80,0x40,0x80,0x40,0x00,0x7F,
"子",0x00,0x00,0xFE,0x1F,0x00,0x08,0x00,0x04,0x00,0x02,0x80,0x01,0x80,0x00,0xFF,0x7F,
0x80,0x00,0x80,0x00,0x80,0x00,0x80,0x00,0x80,0x00,0x80,0x00,0xA0,0x00,0x40,0x00,
};
链表名子上面的GB12和GB16代表了12号字体和16号字体的字段,文件中也有24号和32号
图片
图片储存在image.h文件中linux 电容触摸屏驱动,图片文件中的内容比较简单,一个纯字段取模放进去的
const unsigned char YXDZ_logo[115200] = { /*0X10,0X10,0X00,0XF0,0X00,0XF0,0X01,0X1B,*/
0XFF,0XDF,0XFF,0XDF,0XFF,0XDF,0XFF,0XFF,0XFF,0XFF,0XFF,0XDF,0XFF,0XDF,0XFF,0XDF,
...................
0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,
};
记得在链表后面加const就行
其他单片机驱动
使用其他单片机编撰的代码显示的疗效与前面的STM32的相同,都是一张图片,空间不够的单片机只是显示了一张小一点的图片。
51单片机
51单片机程序由stm32的移植过去的,所以是一样的使用,惟一的区别是51单片机空间小显示不了大图片,速率也比较慢
arduino/ESP32
arduino驱动是网上找到的微雪的类库更改的,个人对Arduino使用没有做过多研究,大部份情况调库使用。
ESP32驱动直接调用的GFX的库编撰驱动,具体使用方式可以作者的github上有,这个库特别的强悍,同样的也很复杂,所以咱这水平也只能是去调用一下他人写好的函数使用。
总结
后续我们将编撰、移植或则搜集测试好的一些屏幕代码分享相应的一些LCD、OLED等显示元件的驱动案例,须要整理好的代码可以在评论区留言或私信邮箱,供你们共同学习进步,前行路上,优信与你们同在,欢迎一键三连,谢谢诸位大鳄!