如何在I2C数据包之前插入要发送的单个字节?

时间:2013-06-04 09:50:26

标签: avr i2c atmel

我正在使用xMega32a4u在Atmel Studio 6中开发应用程序。我正在使用Atmel提供的TWI库。一切都进展顺利。

这是我的问题:为了更新我正在使用的OLED显示器(SSD1306控制器,128x32),必须在I2C START命令,从地址和控制字节之后立即写入显示RAM的全部内容,以便显示器知道将数据输入显示RAM。如果控制字节不在显示RAM包之前,则无效。

我正在使用Saleae逻辑分析仪验证总线正在做它应该做的事情。

这是我用来编写显示的功能:

void OLED_buffer(){ // Used to write contents of display buffer to OLED
    uint8_t data_array[513];
    data_array[0] = SSD1306_DATA_BYTE;
    for (int i=0;i<512;++i){
        data_array[i+1] = buffer[i];
    }
    OLED_command(SSD1306_SETLOWCOLUMN | 0x00);
    OLED_command(SSD1306_SETHIGHCOLUMN | 0x00);
    OLED_command(SSD1306_SETSTARTLINE | 0x00);
    twi_package_t buffer_send = {
        .chip = OLED_BUS_ADDRESS,
        .buffer = data_array,
        .length = 513
    };
    twi_master_write(&TWIC, &buffer_send);
}

显然,这是非常低效的,因为每次调用此函数都会将整个数组“buffer”重新创建为新数组“data_array”,一次一个元素。这一点是将控制字节(SSD1306_DATA_BYTE = 0x40)插入到阵列中,以便立即发送整个“包”,并且控制字节位于正确的位置。我可以将原始的“缓冲”数组放大一个元素并添加控制字节作为第一个元素,跳过这个过程,但这会使大小为513而不是512,并且可能会混淆一些操纵这个的文本/图形函数数组并依赖于它是正确的大小。

现在,我想我可以编写这样的代码:

void OLED_buffer(){ // Used to write contents of display buffer to OLED
    uint8_t data_byte = SSD1306_DATA_BYTE;
    OLED_command(SSD1306_SETLOWCOLUMN | 0x00);
    OLED_command(SSD1306_SETHIGHCOLUMN | 0x00);
    OLED_command(SSD1306_SETSTARTLINE | 0x00);
    twi_package_t data_control_byte = {
        .chip = OLED_BUS_ADDRESS,
        .buffer = data_byte,
        .length = 1
    };
    twi_master_write(&TWIC, &data_control_byte);
    twi_package_t buffer_send = {
        .chip = OLED_BUS_ADDRESS,
        .buffer = buffer,
        .length = 512
    };
    twi_master_write(&TWIC, &buffer_send);
}
/*

这不起作用。第一个“twi_master_write”命令发送START,地址,控制,STOP。然后下一个这样的命令发送一个START,地址,数据缓冲区,STOP。因为后一个事务中缺少控制字节,所以这不起作用。我需要的是在通过I2C总线发送时在地址字节和缓冲器阵列之间插入一个0x​​40字节。 twi_master_write是Atmel TWI库中提供的函数。我试图检查库以找出它的内部工作原理,但我无法理解它。

当然,除了找出如何重新创建twi_write函数以便按照我需要的方式工作之外,还有一种更简单的方法来添加前面的控制字节?理想情况下,我的第一个代码示例不会浪费时钟周期吗?实际上显示仍然非常快速地更新,足以满足我的需求,但这并没有改变这是低效代码的事实。

我感谢你们所有人的建议。提前谢谢!

1 个答案:

答案 0 :(得分:1)

bufferdata_array指向相同的uint8_t[513]数组,但从第二个元素开始buffer。然后,您可以像今天一样继续使用buffer,但也可以直接使用data_array,而无需先复制buffer中的所有元素。

uint8_t data_array[513];
uint8_t *buffer = &data_array[1];