Как я могу вставить один байт для отправки до пакета данных I2C?

Я разрабатываю приложение в Atmel Studio 6, используя xMega32a4u. Я использую библиотеки TWI, предоставленные Atmel. По большей части все идет хорошо.

Вот моя проблема: чтобы обновить OLED-дисплей, который я использую (контроллер SSD1306, 128x32), все содержимое оперативной памяти дисплея должно быть записано сразу после команды I2C START, адреса подчиненного устройства и байта управления, чтобы дисплей знал ввести данные в ОЗУ дисплея. Если байт управления не предшествует непосредственно пакету ОЗУ дисплея, ничего не работает.

Я использую логический анализатор 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 отправляет СТАРТ, адрес, управление, СТОП. Затем следующая такая команда отправляет СТАРТ, адрес, буфер данных, СТОП. Поскольку в последней транзакции отсутствует контрольный байт, это не работает. Все, что мне нужно, это вставить байт 0x40 между байтом адреса и массивом буферов, когда он отправляется по шине I2C. twi_master_write - это функция, которая предоставляется в библиотеках Atmel TWI. Я пытался изучить библиотеки, чтобы понять их внутреннюю работу, но не могу понять этого.

Конечно, вместо того, чтобы выяснять, как воссоздать функцию twi_write, чтобы она работала так, как мне нужно, есть более простой способ добавить этот предыдущий управляющий байт? В идеале такой, который не был бы так расточителен по тактовым циклам, как мой первый пример кода? На самом деле дисплей по-прежнему обновляется очень быстро, более чем достаточно для моих нужд, но это не меняет того факта, что это неэффективный код.

Я ценю любой совет, который вы можете дать. Заранее спасибо!


person SVFeingold    schedule 04.06.2013    source источник


Ответы (1)


Как насчет того, чтобы buffer и data_array указывали на один и тот же массив uint8_t[513], но buffer начинался со второго элемента. Затем вы можете продолжать использовать buffer, как сегодня, но также использовать data_array напрямую, без предварительного копирования всех элементов из buffer.

uint8_t data_array[513];
uint8_t *buffer = &data_array[1];
person Ivar Bonsaksen    schedule 05.06.2013
comment
Это блестяще! Очень элегантное решение. Могу ли я в этом случае получить элемент буферной части массива как обычно? Т.е. buffer [128] дает мне 129-й элемент этого массива? - person SVFeingold; 05.06.2013
comment
Да, buffer[128] == data_array[129]. - person Ivar Bonsaksen; 05.06.2013