本文将讨论一个基本的16x2 LCD模块与单片机的接口细节。
本文将看看一个基本的16×2液晶模块的引脚。然后,将讨论一些重要的说明,常见的液晶模块是兼容的HD44780LCD控制器/驱动芯片。最后,本文给出了一个AVR ATMEGA32单片机与16×2液晶显示器接口的C语言代码示例。
该模块引出线
这1602年,一个是一个16字符、2行显示,类似于今天使用的许多其他16x2显示。每个字符以5列× 8行点阵或5列× 10行点阵的形式显示。应该正确地控制这些像素,以便我们能够显示所需的字符。使用微控制器直接控制所有这些像素并不容易,这就是为什么我们通常使用带有控制器/驱动芯片的LCD模块来方便地将LCD连接到处理器。一个常见的LCD驱动程序是HD44780。这些LCD模块的引脚通常如下图1所示。
图1。16×2液晶模块的通用引脚。图片礼貌AAC.。
GND和Vcc (+ 5v)引脚为电源引脚。v销用于调节显示对比度。我们可以使用电位器将VEE连接到+5 V以下合适的正电压。Led+和Led-引脚用于打开显示器背光(分别连接到+ 5v和地)。
RS引脚是LCD控制器的寄存器选择器引脚。HD44780具有两个寄存器:指令寄存器(IR)和数据寄存器(DR)。RS引脚是一个控制引脚,指定IR或DR是否应连接到数据总线(DB0至DB7引脚)。当RS低时,选择IR,DB7-DB0被视为指令代码。例如,指令代码可以表示“显示清除”命令。当RS为高时,选择DR,DB7-DB0被视为数据。在这种情况下,DB7-DB0可以是表示诸如“A”的角色的代码。
R/W引脚指定我们是写入模块(R/W=0)还是从模块(R/W=1)读取。
E引脚(“Enable”)开始一个读/写操作,将在下一节讨论。
写操作的时序图
虽然我们可以同时从数据总线写入和读取数据,但写操作更为常见。这就是为什么在本节中,我们将研究写操作的时序图,如图2所示。不同参数的定义和期望值如表1所示。
图2。写操作时序图。图片礼貌日立。
表格1礼貌的日立。
时序图表明我们应该将RS和R / W引脚设置为适当的值并等待T作为(应该大于40ns)在设置E引脚到逻辑高之前。根据表,E信号应该有一个宽度(PW嗯)大于230纳秒。
然后,E信号应该有一个从高到低的边缘,它开始写操作。请注意,tDSW在此边缘之前,数据必须是有效的。另外,在E下降沿后,控制信号和数据在t表示的一段时间内不应发生变化啊和tH在图中。另一个重要的问题是“启用周期时间”,它应该大于500ns。这表明,在开始执行下一个读或写操作之前,我们应该等待一段时间。
总之,E上的高到低转换启动数据读写,但必须满足某些定时条件。当将LCD模块与MCU连接时,我们必须考虑这些因素。
重要说明
您可以在此页面24中找到HD44780兼容LCD模块的完整列表数据表。在这里,我们将只使用其中的一些指令来做一些基本的操作。
清晰显示
此指令清除显示。您必须将RS和R/W设置为低逻辑,并执行写入操作,将十六进制值0x01应用到数据总线。此外,数据表声明“clear display”命令“在地址计数器中设置DDRAM地址0”。这是什么意思?
图3。礼貌的日立。
显示数据RAM (DDRAM)是一种RAM,它存储我们发送到LCD模块的字符的ASCII码。DDRAM最多可以存储80个字符(它的容量为80×8位)。然而,这80个字符中只有一部分显示在LCD上。例如,在16×2 LCD的情况下,只有32个内存位置被显示。显示的DDRAM地址和LCD位置之间的关系如图4所示。
图4。礼貌的日立。
根据图4,如果我们将一个特定的字符写入DDRAM地址0x00,它将显示在上面一行的第一个单元格中。类似地,如果我们向0x40地址写入一个字符,它将出现在下一行的第一个单元格中。
要转到DDRAM的一个特定地址,我们可以将所需的地址写入地址计数器(AC)。此外,AC决定了一个写操作输入的字符在LCD上的位置。
注意,lcd支持移位操作,可以更改图4中所示的关系。例如,将左移应用于图4的默认状态将得到图5。如需更多信息,请参考数据表。
图4。礼貌的日立。
现在您熟悉DDRAM和AC,“清除显示”命令的描述应该对您有意义。“清除显示”命令“在地址计数器中设置DDRAM地址0”,因此,它将将光标返回到原始位置(上线的第一单元)。
回家
图6给出了此命令的代码及其描述。
图6。礼貌的日立。
该命令还将光标返回到主位置,并将显示返回到其原始状态(如果它被移动)。对于这个命令,不需要考虑DB0。
输入模式设置
图7给出了该命令的详细信息。
图7。礼貌的日立。
当“I / D”为1时,在写入操作之后,光标位置递增一个(它在显示器上移动到右侧)。当“I / D”为0时,光标位置由一个(它移动到左侧)递减。
S位指定是否移位显示(移位改变在LCD上显示的DDRAM地址)。当S为0时,显示不移位。对于移位选项(当S=1时),请参考数据表。
在许多情况下,我们希望在写操作之后,光标的位置递增,而显示器仍然保持不变(没有使用shift选项)。对于这样的应用程序,DB7-DB0的命令代码将是十六进制值0x06。
显示开/关控制
这个命令的详细信息如下。
图8。礼貌的日立。
通过设置D位为1或0,我们可以分别打开和关闭显示。类似地,C位可以用来打开/关闭光标。B控制光标位置的闪烁能力。因此,如果我们将十六进制值0x0C作为指令写入DB7-DB0, LCD将打开,而光标将关闭。
函数集
下图提供了“函数集”命令的详细信息。
图9。礼貌的日立。
DL位指定LCD模块的数据长度。如果DL=1,数据在数据总线(DB7到DB0)上以8位字的形式发送和接收。当DL=0时,数据以4位长度(DB7到DB4)发送和接收。为了简单起见,我们将在本文中使用8位选项。
N位表示显示行数。对于单行显示,N应该是0。对于两行以上的,N应该是1。
“F”决定了字符的字体,通常是0。
因此,当使用16×2 LCD接收和发送8位长度的数据时,DB7-DB0的“函数集”代码将是十六进制值0x38。
设置DDRAM地址
这条指令设置DDRAM的地址。它可以用于在LCD的特定单元中写入一个字符。例如,将十六进制值0x80发送到数据总线将使游标移动到上一行的第一个单元格。
图10。礼貌的日立。
现在,我们将使用上面的命令来操作16×2液晶显示器。下表总结了上面讨论的命令。
表2
连接液晶显示器与AVR
现在,我们将编写一些函数来连接16×2 LCD到ATMEGA32。假设如图11所示,A端口连接LCD数据总线,B端口的前3个引脚用于控制LCD的RS、RW、E引脚。注意,图11中没有显示VSS、VDD和VEE的连接。
图11.
我们需要两个函数来编写命令和数据到LCD模块。在此之前,让我们定义以下三个常量:
const unsigned char rs_pin = 0x01;const unsigned char rw_pin = 0x02;const unsigned char e_pin = 0x04;
这些常量将在整个代码中用于指定连接到LCD控制引脚的PORTB引脚编号。例如,RS连接到图11中端口B的第一引脚,因此RS引脚为00000001。E连接到第三引脚,所以E_Pin是00000100。通过这种方式,我们可以很容易地修改常量,以适应使用不同引脚连接的未来项目的代码。我们可以使用以下功能向LCD发送指令:
Void lcd_write_struct (unsigned char struct) {delay_ms(2);PORTB = PORTB & (~ (RS_Pin));PORTB=PORTB & (~(RW_Pin));//它是写操作PORTB=PORTB & (~(E_Pin));//设置E为0(见图1)//将指令放到数据总线上PORTB=PORTB | (E_Pin);//设E为1(见图1)PORTB=PORTB & (~(E_Pin));//设置E为0生成下降边}
这里,“指令”是必须发送到LCD数据总线的命令代码。代码的第一行使用“delay.h”库中的delay_ms()函数引入2毫秒的延迟。我们需要给LCD一些时间来完成它当前的工作(如果有)。引入此延迟是为了考虑图2中的“启用周期时间”约束。类似地,我们可以编写一个函数来发送一个字符到LCD:
Void lcd_write_char (unsigned char c) {delay_ms(2);PORTB = PORTB | (RS_Pin);PORTB=PORTB & (~(RW_Pin));PORTB = PORTB & (~ (E_Pin));门= c;PORTB = PORTB | (E_Pin);PORTB = PORTB & (~ (E_Pin));}
“C”是必须发送到LCD数据总线的数据。以下函数通过从表2中发送一些命令初始化LCD。它还指定MCU的POLTA和PORTB作为输出。
void lcd_init(void){delay_ms(2);DDRA = 0xFF;ddrb = 0xff;lcd_write_instruc(0x06);//光标LCD_WRITE_INSTURC(0x0C)的增量模式;//显示屏,光标关闭LCD_WRITE_INSTRUC(0x38);// 8位数据总线,双线显示}
以下功能清除显示:
Void lcd_clear(Void) {delay_ms(2);lcd_write_instruc (0 x01);//清除display lcd_write_instrc (0x02);//返回显示到它的原始状态,如果它被移动。}
要将AC设置为给定地址,我们可以使用以下功能:
Void lcd_goto(unsigned char column, unsigned char row) {delay_ms(2);If (row==0) lcd_write_struct (0x80 + column); / /写入//查看图4和10 if(row==1) lcd_write_strucc (0xC0+ column);//参见图4和图10}
最后,要编写一个字符串,可以依次使用lcd_write_char()函数:
Void lcd_write_string(char *s) {delay_ms(2);While (*s != 0) {lcd_write_char(*s);s + +;}}
使用这些功能,我们可以具有LCD模块的基本功能。以下代码显示了示例的main()函数:
void main(void){lcd_init();lcd_clear();lcd_goto(0,0);lcd_write_string(“全部约”);lcd_goto(0,1);lcd_write_string(“电路”);虽然(1){继续;}}
使用CodeVision和Proteus工具编译和模拟上述代码的输出结果如图12所示。
图12.
值得提及以上执行上述代码的不同行的MCU延迟提供足够的延迟,以满足图2的不同时序约束,特别是与E信号相关的不同时间约束。事实上,我使用了上面的函数,甚至更快的32位MCU,但如果您遇到任何问题,您可以在代码的相应行中引入小延迟,以确保满足定时要求。
在本文中,我们研究了基本16×2 LCD模块的引脚。我们还检查了HD44780兼容LCD模块的一些最重要的说明。可以调整文章中给出的示例C代码以与来自其他供应商的MCU一起使用。
要查看我完整的文章列表,请访问这个页面。
在章节标题为“接口液晶与AVR”,当分配E_Pin到一个引脚值对我来说没有意义,“E是连接到第三引脚,所以E_Pin是00000100”。它不应该是“E_Pin是连接到Atmega32上的第三个引脚,所以E_Pin是00000011”,代码应该是“const unsigned char =0x03”。请建议。
伟大的教程,它提供足够的信息来让我很好奇。
将此代码直接复制和粘贴到AVR Studio 7需要对代码进行次要更改。大多数时间都花了配置AS7与SparkFun的AVR Pocket Programmer一起使用。
说明可以在这里找到:
1。https://medium.com/jungletronics/how-to -load-programs-to-anaarduino-uno-from-atmel-studio-7-83c8dd8d175d
2。http://www.microdigitaled.com/avr/hardware/arduino/usingarduinoboardsinatmelsudio.pdf.
https://www.arnabkumardas.com/platforms/atmel/how-to-flash-or-program-arduino-from-atmel-studio/
3.https://www.arnabkumardas.com/platforms/atmel/how-to-flash-or-program-arduino-from-atmel-studio/
我没有成功地将RS_Pin、RW_Pin和E_Pin作为分配给0x01、0x02或0x03的const unsigned char。
我旋转(位移动)而不是位屏蔽。
LCD上的RS_Pin、RW_Pin、E_Pin分别使用PB0、PB1、PB2; D0-D7分别使用PD0-PD7。
例如,从Write_char函数中更改以下内容:
PORTB = PORTB & (~ (RS_Pin)); - > PORTB = PORTB & (~ (1 < < 0));//清除PORTB的PB0位,即RS_Pin . pdb0
PORTB = PORTB & (~ (RW_Pin)); - > PORTB = PORTB & (~ (1 < < 1));//清除PORTB的PB1 bit (RW_Pin . PB1
portb = portb&(〜(e_pin)); - >到portb = portb&(〜(1 << 2));//清除pb2 portb aka e_pin
任何引用const unsigned char的地方,都用移位操作替换。
然后可以注释掉const unsigned char。
在本教程提供的代码中,函数delay_ms()需要有一个前导下划线。因此将所有delay_ms()更改为_delay_ms()。前导下划线表示内部库的使用,即delay.h。
最后,按照如下顺序定义CPU频率:
#include
#定义F_CPU 16000000 ul
# include“util / delay.h”
玩得开心。