我正在尝试编写一个程序,使我能够将数据从我的TI微控制器发送到非常常见的HD4478 LCD。与其使用并行引脚设置,不如尝试使用串行设置,这样LCD就有了PCF8574T I2C I/O扩展器背包。我对编写嵌入式程序相当陌生,这是我第一次使用任何真正的串行布线通信协议(I2C/SPI),所以我正在努力让它正常工作。在我解释我的困惑之前,以下是3个相应组件的数据表:
微控制器数据表:https://www.ti.com/lit/ds/symlink/tm4c123gh6pm.pdf
LCD数据表:https://circuitdigest.com/sites/default/files/HD44…
I/O扩展器数据表:https://www.nxp.com/docs/en/data-sheet/PCF8574_PCF…
我的主要问题是,我真的不知道我做错了什么,但我假设这与我将LCD初始化为4位模式的方式有关。我对LCD数据表上的初始化演练感到有点困惑:
后一种解释进一步解释了如何将其初始化为4位模式,这就是我将使用的I/O扩展器:
我不太清楚是在8位模式还是4位模式下将初始函数集命令发送到4位模式,以及在初始化过程中何时发生到4位模式的精确转换
我通过数据线传输数据的方式是4位模式,所以我发送的是上半字节。然后再往下咬。这适用于数据字节和命令字节。下面是我的代码。目前闪烁和运行对LCD没有任何影响。我知道我是在正确的从机地址下操作的,因为在初始从机地址传输之后,我没有得到任何指示错误的标志。但是,I2C_LCD_Enable中的所有命令以及main()中尝试向LCD发送单个字符的后一个命令也没有效果
“包括”;TM4C123.h";/设备标题
#包括「;RTE_Components.h";//组件选择
//i2c模块中的数据引脚应为开漏
#定义数据1
#定义命令0
//我可以将每个连接到命令/控制的引脚看作是一个单独的位
作废GPIOE_启用(作废);
无效I2C_启用(无效);
无效I2C_LCD_启用(无效);
无效I2C_传输_字节(字符字节,int模式);
无效延迟50毫秒(无效);
uint32地址传送值;
uint32数据值;
#定义E 0x04//位2
int main(){
GPIOE_enable();
I2C_启用();
I2C_LCD_启用();
I2C_传输_字节(0x01,命令);
I2C_传输_字节(0x80,命令);//将光标设置为第一行
延迟50毫秒();
I2C_传输_字节('a',数据);
}
//端口E引脚pe4和pe5具有替代功能,充当I2C模块2的时钟/数据线
作废GPIOE_启用(作废){
SYSCTL->;RCGCGPIO |=0x10;//启用端口E
GPIOE->;DIR |=0x10 | 0x20;
GPIOE->;DEN |=0x10 | 0x20;//启用引脚pe4和pe5
GPIOE->;AFSEL=0x10 | 0x20;//启用插脚Pe4和Pe5的备用功能
GPIOE->;ODR |=0x20;//pe5是数据引脚,必须设置为开漏
GPIOE->;PCTL |=(3<;<;16)|(3<;<;20);
}
无效I2C_启用(无效){
SYSCTL->;RCGCI2C |=0x04;
I2C2->;MCR |=0x10;//初始化I2C主机
GPIOE->;PUR |=0x10 | 0x20;//我拉起了时钟和数据线,因为它们很低:不拉起它们将不允许它们在传输开始时从高状态转移到低状态,I2C->;MCS&;0x01状态永远挂起
I2C2->;MTPR=0x09;//参见数据表:这将SCL速度初始化为100k kbps
I2C2->;MSA=(0x27<;<;1);//请参见数据表:此设置从机地址并设置传输模式
I2C2->;MCS |=0x07;
而(I2C2->;MCS&;0x01);
}
//HD775数据表第24页和第42页解释了初始化过程
无效I2C_LCD_启用(无效){
//还不知道如何初始化。。。
/*I2C2->;MDR=0x28;//此命令初始化4位模式。此命令和此命令仅进行一次写入,因为它仍处于8位模式
I2C2->;MCS |=0x07;
而(I2C2->;MCS&;0x01);
延迟50毫秒();
I2C2->;MDR=(1<;<;E);//将启用设置为高
I2C2->;MCS |=0x07;
而(I2C2->;MCS&;0x01);
延迟50毫秒();
I2C2->;MDR=~(1<;<;E);//将启用设置为低
I2C2->;MCS |=0x07;
而(I2C2->;MCS&;0x01);
延迟50毫秒()*/
I2C_传输_字节(0x28,命令);
I2C_传输_字节(0x06,命令);//向右移动光标
I2C_传输_字节(0x01,命令);//清除屏幕
I2C_传输_字节(0x0F,命令);//打开显示
}
//上面4位是数据管脚:D4、D5、D6、D7(位0-3)
//低3位为:RS、RW、E
//要发送命令,我们应该将RS设置为0以选择";命令模式";液晶显示器打开
//如果模式为0或命令,则使用0执行逻辑or,这将RS位0设置为0
//如果模式为1或数据,则使用1执行逻辑or,因此RS位0设置为1
//我们还需要脉冲E或enable,以确保这些数据/命令中的任何一个被实际执行
//E引脚对应于第2位,因此我将发送每个数据字节,首先启用E,然后将E设置为低,以脉冲启用
//发送上半字节,脉冲启用,发送下半字节,脉冲启用
无效I2C_传输_字节(字符字节,整数模式){
字符字节_移位;
字符字节\上半字节\半字节;
字符字节\u低位\u半字节;
字节移位=字节<;<;4;
byte_upper_nibble=字节&;0xF0;
I2C2->;MDR=(模式|(I2C2->;MDR&;0xF0)|字节|上半字节| E;//将命令设置为最高有效位,并启用E
I2C2->;MCS |=0x07;
而(I2C2->;MCS&;0x01){
数据值=I2C2->;MBMON;
}
延迟50毫秒();
I2C2->;MDR=(模式|(I2C2->;MDR&;0xF0)|字节_上半字节)&;~E;//将命令设置为最高有效位,并禁用E(脉冲E启用命令/数据)
I2C2->;MCS |=0x07;
而(I2C2->;MCS&;0x01);
延迟50毫秒();
字节低字节=字节移位&0xF0;
I2C2->;MDR=(模式|(I2C2->;MDR&;0x0F)|字节|低位|半字节| E;
I2C2->;MCS |=0x07;
而(I2C2->;MCS&;0x01);
延迟50毫秒();
I2C2->;MDR=(模式|(I2C2->;MDR&;0x0F)|字节(低位));
I2C2->;MCS |=0x07;
而(I2C2->;MCS&;0x01);
延迟50毫秒();
}
//时钟频率为1000000周期/秒
无效延迟50毫秒(无效){
SYSCTL->;RCGCTIMER |=0x01;
TIMER0->;CTL=0;
定时器0->;CFG |=0x04;
TIMER0->;TAMR |=0x01 | 0x10;//单次激发模式,启用中断
TIMER0->;taillr=20000;//1000000/200000=50
TIMER0->;CTL=0x01;
而((TIMER0->;RIS&;0x01)==0);
}
我使用TI板上的车载3.3V电源作为VCC电源
我想在讨论LCD工作不正常之前,我想知道I2C是否工作正常,以及地址引脚是否定义
I/O扩展器IC的地址引脚全部连接到高位,因此您的从机地址为0x27
(我只是想确定这部分是否正常,因为如果出现问题,后续测试中会出现问题)
如果I2C通信工作正常,I/O扩展器IC控制应正确
(发送一些命令,查看IC是否根据您的命令输出)
如果I/O扩展器IC工作异常,您可以使用逻辑分析仪或示波器检查I2C信号,以检查MCU的I2C信号是否正确。(从机地址、确认等)
如果以上各项正确,我们可以开始检查LCD部件
提醒:LCD和I/O扩展器IC数据表的超链接失败。
对于内部复位电路初始化的部分
这意味着当您向LCD供电时,它将执行下面的操作1~4
在此期间,您可以使用示波器或逻辑分析仪测量BF引脚。它应该是高的,总是当你的VCC上升到4.5V时,BF会在拉低之前再持续10毫秒
但如果VCC没有上升到4.5V,则必须通过MPU进行初始化
我在文章的结尾看到了
我使用TI板上的3.3V电源作为VCC
供应
您的LCD是否使用3.3V作为电源?如果是,则应通过MPU初始化LCD。
(但我建议使用5V电源,这样可以减少调试时间。)
如果使用内部初始化功能,LCD设置如下:
- 8位接口
- 单线显示
- 5×8点字符字体
因此,如果要切换到4位模式,需要使用功能设置指令再次设置。(数据表第28页)
必须根据时序图测试信号传输部分
发送命令需要4个步骤
- 传输高位4位数据
- 忙标志检查(BF=1)
- 忙标志检查(BF=0)
- 传输低4位数据
以HD44780U数据表为例进行测试(数据表p.42)
第6步,需要分2次发送
它会在LCD上显示“H”