[英]AVR Atmega168 I2C LCD does not want to initialize
我正在使用 I2C 转换器将数据发送到我的液晶显示器。 转换器基于PCF85741,lcd为Hitachi hd44780。
PCF85741与lcd的端口映射如下:
P0 -> RS
P1 -> RW
P2 -> E
P3 -> ?
P4 -> D4
P5 -> D5
P6 -> D6
P7 -> D7
文档说我的从站的默认地址是 0x20,但是对于 RW 位,我需要发送 0x40。
这是我的代码:
void twi_start()
{
TWCR = (1 << TWINT) | (1 << TWEN) | (1 << TWSTA);
while (!(TWCR & (1 << TWINT)));
}
void twi_stop()
{
TWCR = (1 << TWINT) | (1 << TWEN) | (1 << TWSTO);
while (!(TWCR & (1 << TWSTO)));
}
void twi_write(uint8_t byte)
{
TWDR = byte;
TWCR = (1 << TWINT) | (1 << TWEN);
while (!(TWCR & (1 << TWINT)));
}
void twi_write_byte(uint8_t byte)
{
uint8_t SLAVE_ADDRESS = 0x40;
twi_start();
twi_write(SLAVE_ADDRESS);
twi_write(byte);
twi_stop();
}
液晶显示器
void lcd_init2()
{
for (int i = 0; i < 3; i++) {
twi_write_byte(0x03);
_delay_ms(20);
}
twi_write_byte(0x02);
_delay_ms(20);
//4 bit mode
twi_write_byte(0x24); // D5 -> 1, E -> 1
_delay_ms(10);
twi_write_byte(0x20); // D5 -> 1, E -> 0
_delay_ms(10);
//2 lines
twi_write_byte(0x24); // D5 -> 1, E -> 1
_delay_ms(10);
twi_write_byte(0x20); // D5 -> 1, E -> 0 first nibble
_delay_ms(10);
twi_write_byte(0x84); // D7 -> 1, E -> 1
_delay_ms(10);
twi_write_byte(0x80); // D7 -> 1, E -> 0 second nibble
_delay_ms(10);
}
在这段代码之后,lcd 应该是 4bit 模式,有 2 行,但它不是 lcd 上的任何变化。
1)请说明你有什么 I2C 到并行的 IC? 我找不到 PCF85741 是什么,我只看到PCF8574 和 PCF8574A 的数据表。
在第一种情况下,从地址将为(包括 r/w 位)0x40...0x4F,在第二种情况下 - 0x70...0x7F。
根据我的经验,这些显示器附带的常用 I2C 电路上有 PCF8574A(即地址为 0x7*)。 顺便说一下,那里的引脚 3 用于控制背光。
2)确定您拥有地址的低位? 输入 A0 A1 A2 是上拉还是接地?
同样,根据我的经验,这些电路板通常有上拉到 +5,电路板上有可焊接的跳线,将它们短接到地。 默认情况下,跳线不焊接,因此 A0 A1 A2 具有高逻辑电平,因此设备的 I2C 地址为0x7E (写入)/0x7F(读取)。 如果板上有 PCF8574T,则地址将为0x4E /0x4F
您可以通过检查 TWSR 寄存器(TWSR & TW_STATUS_MASK)
TWS 位在地址发送后是否等于TW_MT_SLA_ACK
(0x18) 或在数据字节发送后TW_MT_DATA_ACK
(0x28) 来轻松检测 IC 是否应答。 (请参阅数据表部分19.8.1 主发送器模式第 186-188 页)
或者,更简单地说,如果您将 PCF8574 的 P3 连接到背光,您可以尝试输出0x08
/ 0x00
以查看背光是否打开和关闭。
3)有关初始化序列,请查看HD44780 数据表第 46 页的图 24 4 位接口注意位 DB5 和 DB4 为高。 另外,请注意,由于您只是在写入显示控制器,因此位R/W (即输出的位 1)应始终为零(注意您发送的是wi_write_byte(0x03);
然后是twi_write_byte(0x02);
位 1 设置为高)。
该示例可能如下所示:
void send4bits(uint8_t fourbits, bool is_cmd) {
uint8_t d = (fourbits << 4) | 0b1000;
if (!is_cmd) d |= 1;
twi_write_byte(d | 0b100); // E high
twi_write_byte(d); // E low
}
void sendcmd(uint8_t cmd) {
send4bits(cmd >> 4, true);
send4bits(cmd & 0xF, true);
}
void senddata(uint8_t cmd) {
send4bits(cmd >> 4, false);
send4bits(cmd & 0xF, false);
}
// initialization sequence
send4bits(0b0011, true);
_delay_ms(5);
send4bits(0b0011, true);
_delay_ms(1);
send4bits(0b0011, true);
// since I2C is slow enough the required 100us pause already happened here
send4bits(0b0010, true);
sendcmd(0b00101000);
sendcmd(0b00001000);
sendcmd(0b00000001);
delay_ms(2);
sendcmd(0b00000110);
sendcmd(0b00001110);
// Initialization is done
sendcmd(0x80); // Set cursor at the beginning
for (uint8_t i = 'A' ; i <= 'Z' ; i++) {
senddata(i); // Send some random data
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.