stm32驱动5110显示屏
最近打算做个5110串口屏,但是第一步肯定是先驱动它。之前没有用过这个型号的,所以就花了一天时间把他的资料研究了一下,在此做个总结。
5110这个屏幕的分辨率是48*84的,其他优点请自行百度搜索。驱动我用的是stm32F030R8的单片机。5110和单片机的连接线主要就是5根:
- SCLK————-这个接spi的时钟线
- DIN—————这个接spi的mosi线
- DC—————-命令和数据选择,随便接个单片机io口就可以了,当为低的时候选择命令,高的时候选择数据
- SCE—————5110的片选信号,在传送数据之前这个要拉低
- RES—————5110的复位信号,低电平的时候复位
接好线就可以配置单片机的代码。我使用的是stm32cubeMx来进行配置:
如图所示,spi配置为主模式,并配置了PA0\PA1\PA2来连接5110的RES、 CD、 DC三个引脚。接下来配置spi的具体参数:这里是重点。昨天调试半天屏都点不亮就是因为spi的极性和相位给搞错了,驱动5110的spi CPOL=0 CPHA=0,并且速度不能高于4mbit(5110最高支持4mbit/s)。具体配置如下图所示:
生成工程,这样spi底层已经配置好了。接下来重点就是5110的驱动函数了。
在写5110的驱动函数之前,我就再把5110具体控制的一些命令来啰嗦一下。(更详细请看pcd8544数据手册)
当DC等于0的时候,通过spi口传送到5110的数据会被识别为命令。那么命令又分为两大类:一类是基本指令,还有一类那就是扩展指令。问题来了我怎么确定使用的是基本指令还是扩展指令。这里还有一条独立的命令可以用来切换基本或是扩展的。
这个叫做功能设置指令。每一位的具体定义如下:
0 0 1 0 0 PD V H 一共是一个byte,8bit
可以看到高5位都是固定的,后面的三个位是可以用来用户自己配置的。
这三个位的具体功能如下:
- PD=0 正常模式 PD=1处于掉电模式 (用来做低功耗)
- V=0 水平寻址 V=1 垂直寻址 (控制显存地址是横着递增还是竖着递增)
- H=0 使用5110基本指令集 H=1 使用扩展指令集
所以切换基本指令就发送指令0x20,使用扩展指令就发送0x21
下面再看下基本指令都包含哪些:
一、显示控制指令
0 0 0 0 1 D 0 E
D和E位的组合 :
- 00————显示空白(不难理解吧,屏幕什么都不显示了)
- 10————普通正常模式(一般都配置成这种模式)
- 01————开启所有显示段(也就是屏幕一片黑,每个点都显示)
- 11————反转显示(很好理解,原来不显示的地方显示了,原来黑点显示的地方不显示了)
二、设置RAM的Y地址
0 1 0 0 0 Y2 Y1 Y0
这个命令也好理解,就是用来配置一个位置坐标的纵坐标,然后从这里开始写入数据进行显示。注意3位y的组合值范围是0-5
三、设置RAM的X地址
1 X6 X5 X4 X3 X2 X1 X0 X坐标需要注意的地方是范围是0-83
基本指令也就这三条,很简单。
接下来要登场的扩展指令集就没那么好理解
分别是:温度控制指令、偏置系统设置指令(混合率)、Vop设置指令。
我不打算细分析这三条指令了,因为确实我也搞不是很懂混合率啊、Vop啊。但是要明白后两条指令配置的参数和显示效果有很大关系。有可能不显示,显示颜色过浅或者过重通过配置后面两个寄存器的值是可以改变效果的。官方手册上面是有说明,但是还有一些计算我就懒得去搞了,我这两个参数是不断修改看效果来配置的。
最后就可以重点看代码了:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 |
void lcdWriteCmd(uint8_t cmd) { LCD_CE_LOW(); LCD_DC_C(); HAL_SPI_Transmit(&hspi1,&cmd,1,0xfff); while (HAL_SPI_GetState(&hspi1) != HAL_SPI_STATE_READY) { } LCD_CE_HIGH(); } void lcdWriteData(uint8_t dat) { LCD_CE_LOW(); LCD_DC_D(); HAL_SPI_Transmit(&hspi1,&dat,1,0xfff); while (HAL_SPI_GetState(&hspi1) != HAL_SPI_STATE_READY) { } LCD_CE_HIGH(); } void lcdSetXy(unsigned char X, unsigned char Y) { lcdWriteCmd(0x40 | Y); // column lcdWriteCmd(0x80 | X); // row } void lcdClear() { unsigned int i; lcdSetXy(0,0); lcdWriteCmd(0x0c); lcdWriteCmd(0x80); for (i=0; i<504; i++) { lcdWriteData(0); } } void lcdWriteChar() { unsigned int i; lcdSetXy(0,0); for(i=0;i<100;i++) { lcdWriteData(0x55); } } void lcd5110Init() { LCD_RESET_LOW(); HAL_Delay(1); LCD_RESET_HIGH(); lcdWriteCmd(0x21); // 使用扩展命令设置LCD模式 lcdWriteCmd(0xd0); // 设置Vop lcdWriteCmd(0x07); // 温度校正 lcdWriteCmd(0x12); // 设置偏置系统(混合率,对比度) lcdWriteCmd(0x20); // 使用基本命令 lcdClear(); // 清屏 lcdWriteCmd(0x0c); // 设定显示模式,正常显示 } |
然后再住函数调用两个函数就OK:
1 2 |
lcd5110Init(); lcdWriteChar(); |