8080 时序也叫因特尔总线,一般应用在mcu(mpu)模式的lcd上。Inter总线控制线有四根:
RD:写使能
WR:读使能
DC(RS):数据/命令
CS:片选
LCD控制及传输数据所需要的管脚:
管脚名称 | 功能描述 |
---|---|
CS | 片选信号 |
DC(RS) | 数据或者命令管脚(1:数据读写,0:命令读写) |
WR | MCU(MPU)向LCD写入数据控制线,上升沿有效,写数据时 RD拉高 |
RD | MCU (MPU) 从LCD读数据控制线,上升沿有效,读数据时,WR拉高 |
DB[x:0] | 8/9/16/18bit 双向数据总线,一般8位MCU接口用的比较多 |
RST | 硬件复位 LCD 信号 |
BL | LCD背光信号 |
IM2/IM1/IM0 | 接口控制. IM2=0 串行,IM2 =1,IM1=0,IM0=0,6800/8080 8bit 并行接口;IM1=0,IM0=1,6800/8080 16bit 并行接口;IM1=1,IM0=0,6800/8080 9bit 并行接口;IM1=1,IM0=1,6800/8080 18bit 并行接口; |
P68 | 6800/8080 选择。0 表示8080,1 表示6800 |
读时序图。通用时序图如下:
读数据的过程:
CS 拉低,选中
DC/RS 为高(读数据)
WR 为高,禁止写
在RD的上升沿,读线上的数据(D[0:7]),假设8位 8080并口
CS 拉高,取消片选
伪代码:
LCD_CS = 0; //开始片选
LCD_DC = 1; //读数据
LCD_WR = 1; //禁止写
LCD_RD = 0; //开始读
data = DATAIN();//读取数据
LCD_RD = 1; //结束读
LCD_CS = 1; //结束片选
写时序图。通用时序图如下:
写数据的过程:
CS为低,选中
RD为高, 禁止写
DC/RS为高(写数据,写命令拉低)
在WR的上升沿,使数据写入到 驱动 IC 里面
CS为高,结束一组数据读取
伪代码:
LCD_CS = 0; //开始片选
LCD_RD = 1; //禁止读
LCD_DC = 1; //写数据
DATAOUT(Data); //输出数据 ,先准备好数据,然后上升沿一次性更新到lcd
LCD_WR = 0; //写入开始
LCD_WR = 1; //写入结束
LCD_CS = 0; //结束片选
以GC9106 这块LCD 驱动IC为例,介绍一下,如何根据datasheet,去模拟读写操作,方便后续遇到新的屏幕,可以快速入手。事实上,大部分时候,我们的主控一般都会存在lcd控制器,支持读写操作,只需要配置寄存器即可。不过通过GPIO模拟,对整个过程会有更新的认识。
第一步:根据硬件确认屏幕所接接口,确认引脚及协议:以8080 8位并行为例
协议:8080时序
引脚:LCD_CS、LCD_RD、LCD_WR、LCD_DC、LCD_Data[7:0]
第二步:根据 datasheet 阅读读写时序
读时序
驱动IC会在下降沿产生数据,主控(MCU)在上升沿从D[7:0] 读数据
整个读数据的过程,分为两步:写入一个command address, 读数据。
写入cmd:
读数据:根据时序图,真正读数据的过程中,第一个周期的数据是无效的,这个可以很好的解释command列表中,为何第一次数据都是dummy data
写时序
主控(MCU)会在下降沿产生数据,驱动IC在上升沿从D[7:0] 读数据
整个写数据的阶段分为两个:写命令和写数据,唯一的区别是DC不一样。
第三步:查看command列表。这里以读ID为列(04H)
阅读command信息
根据timing,先写入一个cmd(04H)
紧接着,读四次数据。
舍弃第一个数据(dummy data)
注意:初始状态和初始值。如果读不出来数据,可能是上电时序的问题,这个时候可以通过硬件GPIO 复位一下lcd,然后在读取数据。
write_cmd(0x04);
read_data(); //dummy data
ID0 = read_data();
ID1 = read_data();
ID2 = read_data();
第四步:模拟基本读写时序操作。根据通用8080协议时序即可
此处用伪代码表示思路即可:
static void write_lcd_dc(int isCmd, unsignedint value)
{
LCD_CS = 0; /* 拉低 */
LCD_RD = 1; /* 禁止读 */
if(isCmd == 1) {
LCD_DC = 0; /* 拉低 写命令 */
} else{
LCD_DC = 1; /* 拉高 写数据 */
}
data_out(value); /* 准备数据 */
LCD_WR = 0; /* 拉低 */
delay10us(); /* 上升沿更新数据*/
LCD_WR = 1; /* 拉高*/
delay10us();
LCD_CS = 1; /*拉低, 取消片选*/
}
static void data_out(unsignedint value)
{
/* 假设 data[0:8] 在一组GPIO上,并且连续
* 设置data[0:8] 为输出状态,切默认都输出0
*/
int i = 0;
for(int i = 0; i < 8; i++) {
LCD_Data[i] = ((value >> i) & 0x01);
}
}
static unsigned int read_lcd_data()
{
int ret = 0;
LCD_CS = 0; /* 拉低,选中 */
LCD_WR = 1; /* 拉高, 禁止写 */
LCD_DC = 1; /* 拉高,表明将要读数据 */
LCD_RD = 0; /* 拉低, 开始读数据*/
delay10us();
ret = data_In(); /* 读数据*/
delay10us();
LCD_RD = 1;/* 拉高, 结束读数据 */
delay10us();
LCD_CS = 1; /* 取消片选*/
return ret;
}
static unsigned int data_in()
{
int ret = 0;
/* 假设 data[0:8] 在一组GPIO上,并且连续
* 设置data[0:8] 为输入状态
*/
int i = 0;
for(int i = 0; i < 8; i++) {
ret |= (gpio_get_value(LCD_Data[i]) << i);
}
return ret ;
}
本文介绍了8080协议的基础时序,以及通用的读写操作,旨在了解学习8080协议。然后通过实际的lcd 驱动IC 应用举例,介绍如何阅读 lcd datasheet.通过GPIO 模拟读写操作,达到对整个协议的理解。
事实上,大多数情况下,我们不需要亲自模拟时序,调试一款新屏时,一般通过配置lcd控制器,会自动模拟时序,只需要将原厂的setting,按照对应的规则,加入到驱动中即可。当然,也可以通过gpio模拟读写,将lcd的setting,通过自己模拟的读写接口,设进去。
寒冬来临,2022也接近尾声,这一年,你经历了哪些事情,人生轨迹发生了哪些变化?或是从你的职业角度,对来年又有哪些想法,欢迎畅所欲言,分享交流。
活动时间:即日起——2月1日
要求:
1、在面包板社区发表自己的年终总结,标题以【2022年终总结】开头。
2、内容与电子行业相关。
3、必须原创,字数不限
活动奖励:
一等奖,每人奖励200元京东E卡一张。
二等奖,每人奖励50元京东E卡一张。
优秀奖,每人奖励30元京东E卡一张。
所有参与者均可获得50E币奖励![ E币可在商城兑换奖品 ]
👇👇点击阅读原文,看更多工程师总结