Nokia 5110 LCD 介绍
刚好手边有块Nokia 5110 LCD 就拿它来做测试吧~虽然这块LCD年份久远了,但还是很适合来做些小东西玩玩!
先介绍一下这块LCD上面的接脚 :
Nokia 5110 是使用SPI协议但没有MISO只有MOSI,所以MISO透过程式模拟就可以了。
上方表是各个脚位的连接,在这边我使用SPI1所以主要使用是PA5-7,CS透过软体选择则是PB6,除了电源与接地外其余的脚位可以依照个人去更改。
接下来看看LCD的指令有哪些~
可以看到其中功能设置、写指令、设置RAM XY位置等等,可以先将会使用到的函数先写出来,方便之后去使用。
上方功能中的RAM是什么?可以把它想成显示pixel的地址,这一块是48x84的LCD也就是说共有4032个pixel,每一个Pixel都会像下图一样排好各有各的地址。
水平寻址于垂直寻址又是什么呢?下方是整个LCD的RAM格式寻址,在垂直的部分为6x8 = 48,而x的部分则为0-83共84刚好对应到了48x84的LCD。


上述图片来源:手册
IOC档设置
Ioc档设置:先点选左侧的Connectivity可以在里面找到SPI1、SPI2、SPI3,会看到SPI1是禁止的,原因是因为板载LED将PA5设置为Output,取消PA5就可以选择了选择最上方的Reset_State。





实作程式码
定义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();}
初始化LCDvoid 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}
清除LCDvoid 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上方,下方这张图可以搭配看可能会比较好理解,假设希望产生下方英文:
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);}
上方只是为了好理解如何将文字显在在LCD上,网路上有些软体可以直接提取对应的位置,就不用这么麻烦一个一个去写,可以直接透过[]数组的方式去显示就可以了~