刚好手边有块Nokia 5110 LCD 就拿它来做测试吧~虽然这块LCD年份久远了,但还是很适合来做些小东西玩玩!
先介绍一下这块LCD上面的接脚 :
脚位 | 说明 | 连接脚位 |
---|---|---|
RST | LCD 重置 | PB15 |
CS | 选择脚位 | PB6 |
D/C | 资料或命令切换 | PB13 |
DIN | 资料输入 | PA7 |
CLK | 系统时钟 | PA5 |
VCC | 电源 | 3.3v |
BLC | 背光控制 | PB14 |
GND | 接地 | GND |
Nokia 5110 是使用SPI协议但没有MISO只有MOSI,所以MISO透过程序模拟就可以了。
上方表是各个脚位的连接,在这边我使用SPI1所以主要使用是PA5-7,CS透过软件选择则是PB6,除了电源与接地外其余的脚位可以依照个人去更改。
接下来看看LCD的指令有哪些~
可以看到其中功能设置、写指令、设置RAM XY位置等等,可以先将会使用到的函数先写出来,方便之後去使用。
D | E | Mode |
---|---|---|
0 | 0 | 显示空白 |
1 | 0 | 普通模式 |
0 | 1 | 打开所有显示 |
1 | 1 | 反转 |
上方功能中的RAM是什麽?可以把它想成显示pixel的地址,这一块是48x84的LCD也就是说共有4032个pixel,每一个Pixel都会像下图一样排好各有各的地址。
水平寻址於垂直寻址又是什麽呢?下方是整个LCD的RAM格式寻址,在垂直的部分为6x8 = 48,而x的部分则为0-83共84刚好对应到了48x84的LCD。
#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
static void StartSPI(void)
{
HAL_GPIO_WritePin(GPIOB,GPIO_PIN_6,GPIO_PIN_RESET);
}
//CS_High
static void StopSPI(void)
{
HAL_GPIO_WritePin(GPIOB,GPIO_PIN_6,GPIO_PIN_SET);
}
//传送
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;
}
void LCD_Writebyte(unsigned char data, unsigned char dc)
{
StartSPI();
if(dc==0)
HAL_GPIO_WritePin(GPIOB,GPIO_PIN_13,RESET); //命令
else
HAL_GPIO_WritePin(GPIOB,GPIO_PIN_13,SET); //资料
SPI_Tx(data);
StopSPI();
}
void LCD_Init(void)
{
//Reset
HAL_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);
}
void LCD_SetPosition(uint8_t X, uint8_t Y)
{
LCD_Writebyte(0x40 | Y, 0); // column
LCD_Writebyte(0x80 | X, 0); // row
}
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上方,下方这张图可以搭配看可能会比较好理解,假设希望产生下方英文:
while (1)
{
HAL_GPIO
LCD_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上,网路上有些软件可以直接提取对应的位置,就不用这麽麻烦一个一个去写,可以直接透过[]数组的方式去显示就可以了~
>>: Emotet 社交工程邮件,寄件者或是内容中包含贵公司的员工资料或是签名档
这里要来介绍如何优化 css 有时候我们因为要加前缀词(有的旧浏览器不支援,所以需要加) 但这会浪费...
使用 React 作为前端架构的朋友对於 Flux 应该都不陌生,React 也内建了 Flux 让...
前一篇文章中,我们介绍了 State Flow 以及它的使用方式,本篇将继续讨论 State Flo...
Step 1 修改专案属性 专案->属性 修改目标framework的值 点选"是&...
某间面包店的面包师傅想研究不同配方做出的面包所销售出的差异,但依照部烤箱的不同温度又会有所不同,故想...