|
最近在玩LCD12864,M051驱动,为了节省硬件引脚开支,采用4线驱动。
硬件连接:P2.7-P2.4 → D7-D4;
P2.1 → RS;
P2.2 → RW;
P2.3 → E。
之前有做过LCD1602的4线模式,而1602和12864的大部分指令集是兼容的,当初写1602的库时,是直接从网上拿的他人的初始化代码,没有深入研究。我基本没对原始库做任何改动,初始化12864就成功了,也显示了出来,改了一下显示位置的函数,整屏显示都没问题了,今天突然想研究下初始化,于是拿出DATASHEET细细看了一番。按照datasheet的初始化流程怎么也不成功,忒奇怪,后来好不容易搞定。
原因是:我在写4BIT的数据发送程序时,先发高四位,在发低四位,而4BIT模式下,初始化只要求发高4位,我加了个标志位,就搞定了。贴上代码:
void LCD_Send_Data(unsigned char Data_Type, unsigned char Data, unsigned char ChkBF){
if(ChkBF) LCD_Check_Busy();
switch (Data_Type) {
case DT_Cmd:
LCD_Set_Status(OP_Write_Cmd);
break;
case DT_Data:
LCD_Set_Status(OP_Write_Data);
break;
}
LCD_Bus_Port &= 0x0F;
LCD_Bus_Port |= (Data & 0xF0); /* High 4bits */
LCD_Positive_Pulse();
System_Delay_Ms(15);
if(!Init_Flag) {
LCD_Bus_Port &= 0x0F;
LCD_Bus_Port |= ((Data & 0x0F) << 4); /* Low 4 bits */
LCD_Positive_Pulse();
}
if(ChkBF) LCD_Check_Busy();
}
以上是发送数据的代码,改好后的初始化代码如下:
void LCD_Init(void){
System_Delay_Ms(800);
Init_Flag = 1;
LCD_Send_Data(DT_Cmd, 0x20, 0); /* 4BIT传送模式,只发高四位 */
Init_Flag = 0;
System_Delay_Ms(15);
LCD_Send_Data(DT_Cmd, 0x02, 0); /* 复位AC位置 */
System_Delay_Ms(15);
LCD_Send_Data(DT_Cmd, 0x0C, 1); /* 显示开启,无游标,无反白 */
LCD_Send_Data(DT_Cmd, 0x06, 1); /* 游标移动方向为正 */
LCD_Send_Data(DT_Cmd, 0x01, 1); /* 清除显示屏 */
System_Delay_Ms(100);
}
上面的这段代码可以正常工作。如果不加入对标志位的控制,把第一条初始化指令改为0x03,则也能完成初始化!只是有点不太稳定。代码如下。
void LCD_Init(void){
System_Delay_Ms(800);
Init_Flag = 0;
LCD_Send_Data(DT_Cmd, 0x03, 0);
// Init_Flag = 0;
LCD_Send_Data(DT_Cmd, 0x20, 0); /* 4BIT模式了 */
LCD_Send_Data(DT_Cmd, 0x00, 0);
System_Delay_Ms(15);
LCD_Send_Data(DT_Cmd, 0x0C, 1);
LCD_Send_Data(DT_Cmd, 0x06, 1);
LCD_Send_Data(DT_Cmd, 0x01, 1);
System_Delay_Ms(100);
}
我好奇了,于是继续更改初始化代码。
void LCD_Init(void){
System_Delay_Ms(800);
Init_Flag = 0;
LCD_Send_Data(DT_Cmd, 0x03, 0); /* 如果直接去掉这条指令,初始化就不成功 */
System_Delay_Ms(15);
// Init_Flag = 0;
LCD_Send_Data(DT_Cmd, 0x02, 0); /* 设置4BIT模式 */
// LCD_Send_Data(DT_Cmd, 0x00, 0);
System_Delay_Ms(15);
LCD_Send_Data(DT_Cmd, 0x0C, 1);
LCD_Send_Data(DT_Cmd, 0x06, 1);
LCD_Send_Data(DT_Cmd, 0x01, 1);
// LCD_Send_Data(DT_Cmd, 0x06, 1);
System_Delay_Ms(100);
}
这段代码还是可以工作!!而且很稳定。但是如果把首先发的0x03这条命令去掉,就不行了,先发0x02再发0x20还是不行。这是第一个奇怪的问题。
第二个奇怪的问题就是:对于进入点设定指令0x06(游标右移),必须放在清屏指令0x01之前,否则初始化也不成功!
贴上ST7920的初始化流程图和相关命令解释:
(原文件名:LCD12864初始化流程图.JPG)
(原文件名:进入点设定.JPG) |
阿莫论坛20周年了!感谢大家的支持与爱护!!
月入3000的是反美的。收入3万是亲美的。收入30万是移民美国的。收入300万是取得绿卡后回国,教唆那些3000来反美的!
|