STM32-11 SPI Nokia 5110 LCD 实作

Nokia 5110 LCD 介绍

刚好手边有块Nokia 5110 LCD 就拿它来做测试吧~虽然这块LCD年份久远了,但还是很适合来做些小东西玩玩!
http://img2.58codes.com/2024/20146325Px76bqYoBu.png
先介绍一下这块LCD上面的接脚 :

脚位说明连接脚位RSTLCD 重置PB15CS选择脚位PB6D/C资料或命令切换PB13DIN资料输入PA7CLK系统时钟PA5VCC电源3.3vBLC背光控制PB14GND接地GND

Nokia 5110 是使用SPI协议但没有MISO只有MOSI,所以MISO透过程式模拟就可以了。

上方表是各个脚位的连接,在这边我使用SPI1所以主要使用是PA5-7,CS透过软体选择则是PB6,除了电源与接地外其余的脚位可以依照个人去更改。

接下来看看LCD的指令有哪些~
http://img2.58codes.com/2024/20146325LoOBH4ZG0p.png
可以看到其中功能设置、写指令、设置RAM XY位置等等,可以先将会使用到的函数先写出来,方便之后去使用。

Function Set (功能设置) : 在D/C设为0,后续填入00100 PD V H,PD为0时表示选中1表示失能,V为0则代表水平寻址1则代表垂直寻址,H为0是使用标準指令及1则是扩展指令及。Write data (写指令) : 在D/C设为1,后续填入要写入的8个bit,用途为写资料到RAM上。Display control (显示控制) : D/C设置为0,后续填入 00001 D 0 E,用途为控制显示模式DEMode00显示空白10普通模式01打开所有显示11反转Set Y address of RAM (设置RAM的Y位置) : D/C设置为0,后续填入01000 Y2 Y1 Y0,同时(0≤Y≤5)。Set Y address of RAM (设置RAM的Y位置) : D/C设置为0,后续填入1 X6 X5 X4 X3 X2 X1 X0,同时(0≤X≤83)。

上方功能中的RAM是什么?可以把它想成显示pixel的地址,这一块是48x84的LCD也就是说共有4032个pixel,每一个Pixel都会像下图一样排好各有各的地址。
http://img2.58codes.com/2024/20146325avncHUVZzp.png
水平寻址于垂直寻址又是什么呢?下方是整个LCD的RAM格式寻址,在垂直的部分为6x8 = 48,而x的部分则为0-83共84刚好对应到了48x84的LCD。
http://img2.58codes.com/2024/20146325zChlARGDyp.png

垂直寻址 : 对应上方的六大格编号为0-5垂直往下接着换下一行接续,所以上方才会说Y必须小于等于5 (0b00000101)
http://img2.58codes.com/2024/20146325hpR8pwvv3G.png水平寻址 : 由纵向改为横向地址编排, 0-83接着换下一列继续接续,也就是X小于等于83 (0b01010011)
http://img2.58codes.com/2024/20146325v74f4w8B0R.png
上述图片来源:手册

IOC档设置

Ioc档设置:先点选左侧的Connectivity可以在里面找到SPI1、SPI2、SPI3,会看到SPI1是禁止的,原因是因为板载LED将PA5设置为Output,取消PA5就可以选择了选择最上方的Reset_State。
http://img2.58codes.com/2024/201463250QFZdae0PV.png接着在上方模式的部分选择Full-Duplex Master(全双工Master),让STM32做为Master。下方NSS的部分选择Disable,因为我透过软体方式去控制CS脚位。
http://img2.58codes.com/2024/20146325rf4DfvFhC3.png下方详细配置中可以点选GPIO Settings ,会清楚地看到MISO MOSI SCK脚位在哪,将LCD对应的接上去即可,但由于刚刚选择透过软体控制CS,所以我们要将原先的CS(PB6)脚位选择为OutPut。
http://img2.58codes.com/2024/20146325W2pdLO0jfq.png
http://img2.58codes.com/2024/20146325315uN5p6uO.png接着点选回Parameter Settings,当中将Data Size改为8bit。下方预分频係数可以依照传输鲍率去做选择,这边我选为Prescaler 64 Baud Rate则是1.25MBits/s。再往下会看到CPOL与CPHA设置的选项,这部分可以参考前一篇介绍去做设置。如果要使用中断方式的话记得要到NVIC当中将SPI中断打开!
http://img2.58codes.com/2024/201463252FvcqHSW58.png接下来已经将LCD上剩下RST、BLC、DIN我们还没有接上,这部分可以依照个人选择脚位,如果有其他设备不要占用到功能脚位即可,这边我选择PB13-15去做这三条线的连接。
http://img2.58codes.com/2024/20146325KEWgOyr1VP.png

实作程式码

定义SPI指令
#define NOP 0x00#define FunSetVE 0x23 //垂直寻址 扩展模式#define FunSetHE 0x21 //水平寻址 扩展模式#define FunSetVS 0x22 //垂直寻址 标準模式#define FunSetHS 0x20 //水平寻址 标準模式#define DisplayBlack 0x08//空白模式#define DisplayNormalk 0x0C //正常模式#define DisplayALL 0x09 //显示段全开#define DisplayInverse 0x0D //反转模式
定义CS_LOW与CS_High来做位时序的启动于停止
//CS_LOWstatic void StartSPI(void){    HAL_GPIO_WritePin(GPIOB,GPIO_PIN_6,GPIO_PIN_RESET);}
//CS_Highstatic void StopSPI(void){    HAL_GPIO_WritePin(GPIOB,GPIO_PIN_6,GPIO_PIN_SET);}
接着我们可以将HAL_SPI的库写成一次传送与接收1个byte,方便之后使用~
//传送static void SPI_Tx(uint8_t data){  HAL_SPI_Transmit(&hspi1, &data, 1, 10);}
//接收//回传值为接收到的资料static uint8_t SPI_Rx(void){  uint8_t retVal;  HAL_SPI_Receive(&hspi1, &retVal, 1, 10);  return retVal;}
对LCD写入资料
void LCD_Writebyte(unsigned char data, unsigned char dc){StartSPI();if(dc==0)HAL_GPIO_WritePin(GPIOB,GPIO_PIN_13,RESET); //命令elseHAL_GPIO_WritePin(GPIOB,GPIO_PIN_13,SET); //资料SPI_Tx(data);StopSPI();}
初始化LCD
void LCD_Init(void){//ResetHAL_GPIO_WritePin(GPIOB,GPIO_PIN_15,RESET); HAL_Delay(1);HAL_GPIO_WritePin(GPIOB,GPIO_PIN_15,SET); StartSPI();HAL_Delay(1);StopSPI();HAL_Delay(1);LCD_Writebyte(FunSetHE, 0); LCD_Writebyte(0xBD,0); LCD_Writebyte(0x13,0);LCD_Writebyte(0x13,0);LCD_Writebyte(FunSetHS, 0);LCD_Writebyte(DisplayNormalk, 0);}
设置Xy起始位置
void LCD_SetPosition(uint8_t X, uint8_t Y){LCD_Writebyte(0x40 | Y, 0);// columnLCD_Writebyte(0x80 | X, 0);    // row}
清除LCD
void LCD_Clear(void){uint16_t i;LCD_Writebyte(0x0c, 0);LCD_Writebyte(0x80, 0);for (i = 0; i < 504; i ++){LCD_Writebyte(0, 1);}}

看了那么多函式可能还不太懂如何去将字体显示在LCD上方,下方这张图可以搭配看可能会比较好理解,假设希望产生下方英文:
http://img2.58codes.com/2024/20146325n3Vue0D1QF.png

while (1){HAL_GPIOLCD_Clear();LCD_Writebyte(0x02, 1);LCD_Writebyte(0x02, 1);LCD_Writebyte(0x02, 1);LCD_Writebyte(0x02, 1);LCD_Writebyte(0xFE, 1);LCD_SetPosition(8,0);LCD_Writebyte(0x82, 1);LCD_Writebyte(0x82, 1);LCD_Writebyte(0xFE, 1);LCD_Writebyte(0x82, 1);LCD_Writebyte(0x82, 1);LCD_SetPosition(15,0);LCD_Writebyte(0xF0, 1);LCD_Writebyte(0x48, 1);LCD_Writebyte(0x44, 1);LCD_Writebyte(0x48, 1);LCD_Writebyte(0xF0, 1);HAL_Delay(500);}

http://img2.58codes.com/2024/20146325SInrIhmwmK.jpg
上方只是为了好理解如何将文字显在在LCD上,网路上有些软体可以直接提取对应的位置,就不用这么麻烦一个一个去写,可以直接透过[]数组的方式去显示就可以了~


关于作者: 网站小编

码农网专注IT技术教程资源分享平台,学习资源下载网站,58码农网包含计算机技术、网站程序源码下载、编程技术论坛、互联网资源下载等产品服务,提供原创、优质、完整内容的专业码农交流分享平台。

热门文章