0

我正在使用 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);
}

显然,这是非常低效的,因为每次调用此函数都会将整个数组“缓冲区”重新创建到一个新数组“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 总线发送时,我需要在地址字节和缓冲区数组之间插入一个 0x40 字节。twi_master_write 是 Atmel TWI 库中提供的函数。我试图检查这些库以找出它的内部工作原理,但我无法理解它。

当然,与其弄清楚如何重新创建一个 twi_write 函数以按照我需要的方式工作,还有一种更简单的方法来添加这个前面的控制字节?理想情况下,它不像我的第一个代码示例那样浪费时钟周期?实际上,显示器的更新速度仍然非常快,足以满足我的需求,但这并不能改变这是低效代码的事实。

我很感激你们可能有的任何建议。提前致谢!

4

1 回答 1

1

如何拥有bufferdata_array指向同一个uint8_t[513]数组,但从buffer第二个元素开始。然后你可以像今天一样继续使用buffer,也可以data_array直接使用,而不必先从buffer.

uint8_t data_array[513];
uint8_t *buffer = &data_array[1];
于 2013-06-05T05:27:25.640 回答