【问题标题】:AVR Atmega168 I2C LCD does not want to initializeAVR Atmega168 I2C LCD 不想初始化
【发布时间】:2019-11-25 20:58:53
【问题描述】:

我正在使用 I2C 转换器将数据发送到我的液晶显示器。 转换器基于PCF85741,lcd为日立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 行,但不是 液晶显示器没有任何变化。

【问题讨论】:

    标签: c avr i2c atmega lcd


    【解决方案1】:

    1) 请说明您拥有的 I2C 转并行 IC 是什么?我找不到 PCF85741 是什么,我只看到 PCF8574 and 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 寄存器中的 TWS 位 (TWSR &amp; TW_STATUS_MASK) 在发送地址后是否等于 TW_MT_SLA_ACK (0x18) 或在数据后检查 TW_MT_DATA_ACK (0x28) 来轻松检测 IC 是否应答字节被传输。 (请参阅the datasheet 部分 19.8.1 主发射器模式 第 186-188 页)

    或者,更简单的说,如果你有PCF8574的P3连接到背光,你可以尝试输出0x08/0x00,看看背光是否开启和关闭。

    3)有关初始化序列,请参见HD44780 datasheet 第 46 页上的 图 24 4 位接口 注意位 DB5 和 DB4 为高。另外,请注意,由于您只是在写入显示控制器,因此位 R/W(即输出的位 1)应始终为零(注意您正在发送 wi_write_byte(0x03);然后将位 1 的twi_write_byte(0x02); 设置为高)。

    例子可能如下:

    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
    }
    

    【讨论】:

    • 谢谢AterLux,您对地址的建议是正确的。如果我将 0x4E 作为 SLA+W 发送,则 TWSR 中的状态为 0x18,这意味着 SLA+W 已发送,并且 ACK 已收到。发送任何其他 SLA+W 字节在 TWSR 中返回 0x20 状态,因此地址 0x4E 是正确的。但是当我发送下一个字节(0x08 应该设置背光)时,写入功能卡住了。请看一下这段代码。 pastebin.com/rrahhtec 你可以看到 led_on() 函数永远不会被调用,因为写循环永远不会停止。
    • @bielu000 我在您的代码中没有看到 TWBR 初始化。默认情况下,它的值为零,在 16MHz CPU 上给出 1MHz I2C 频率(请参阅数据表的 22.5.2 比特率发生器单元部分)。您必须将 I2C 速度限制在最大 100kHz。因此,对于 16MHz CPU,将 TWBR 设置为 72,对于 8MHz CPU,设置为 32。
    • 你完全正确。我完全忘记了比特率发生器。就我而言,我将 TWBR 设置为 52,因为我的 CPU 速度是 12 Mhz。谢谢。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-03-19
    • 1970-01-01
    • 2015-09-29
    • 2014-01-11
    • 1970-01-01
    相关资源
    最近更新 更多