SH1106 - Передача длинного буфера через SPI

Я использую SH1106 и создаю для него свой собственный драйвер. Почти все работает отлично, время отправки составляет около 2/3 мс с использованием transfer16. Однако я заметил, что могу использовать transfer с буфером и длиной, чтобы получить время отображения 1 мс; это было бы крайне полезно.

Для справки привожу технический паспорт: http://support.technologicalarts.ca/docs/Components/OLED13-SPI/SH1106.pdf

Итак, рабочее решение следующее:

SPI.beginTransaction(settings);
//
for (int page = 0; page < 8; page++)
{   
    digitalWrite(DC, LOW);
    SPI.transfer(0xB0 + page);
    SPI.transfer(0x02);
    SPI.transfer(0x10);
    digitalWrite(DC, HIGH);

    for (int column = 0; column < 128; column += 2)
        SPI.transfer16(buffer[(page * 128) + column]);
}
digitalWrite(DC, LOW);
//
SPI.endTransaction();

Это для каждой из 8 страниц записывает 128 байтов по 2 за раз. Я хочу записать 128 байтов за один вызов. Это будет что-то вроде этого:

SPI.transfer(buffer + (page * 128), 128);

Однако это как бы инвертирует дисплей. Он буквально включает каждый пиксель по какой-то причине, и я не могу понять, почему. Я просто использую несколько байтов, установленных на 255 для тестирования, и с оригинальным методом это работает идеально.

Я неправильно использую вызов? Есть ли ограничение на размер буфера, который я могу использовать, я пока ничего об этом не видел. Я пробовал изменить арифметику указателя, но безуспешно. Я пробовал переместить 128 байт во временное местоположение и использовать его, но все равно ничего.

Очевидно, что это не так уж важно, и, возможно, я мог бы как-то улучшить передачу другими способами, но если у вас есть какие-либо советы, я был бы рад их получить

----- ПРАВКА -----

Мне теперь повезло с использованием метода передачи с буфером, когда я изменил тип данных страницы на uint8_t. Однако это также вызвало еще несколько проблем, и я не уверен, что именно их вызывает.

  • Во-первых, при высокой частоте обновления дисплея дисплей снова инвертируется, и все пиксели включаются.
  • С задержкой между вызовами дисплея это работает! Но через несколько секунд эти пиксели медленно исчезают, чего я никогда раньше не испытывал.

Вот отредактированный код:

SPI.beginTransaction(settings);
//
for (uint8_t page = 0; page < 8; page++)
{
    SPI.transfer(0xB0 + page);
    SPI.transfer(0x02);
    SPI.transfer(0x10);

    digitalWrite(DC, HIGH);
    SPI.transfer(buffer + (page * 128), 128);
    digitalWrite(DC, LOW);
}
//
SPI.endTransaction(); 

Трудно объяснить, что на самом деле происходит. Но без большой задержки между вызовами метода передачи буфера экран сходит с ума и, возможно, полностью инвертируется, если это происходит слишком часто. Даже при большой задержке пиксели со временем случайным образом исчезают, чего я никогда не видел.

Метод отправки 2 байт не имеет ни одной из этих проблем. Без задержки все будет работать нормально.

, 👍0

Обсуждение

Проверьте порядок байтов. Поменяйте порядок байтов для каждой пары из 2 байтов в буфере для проверки. (for(int i=0; i < sizeof(buffer); i +=2) { byte tmp = buffer[i]; buffer[i] = buffer[i+1]; buffer[i+1] = tmp; }, @Maximilian Gerhardt

Никаких проблем, просто этот метод сам по себе, @Reece

Где объявлен buffer?, @Maximilian Gerhardt

Внутри класса, как 'uint8_t buffer[1024] = {0}', @Reece


1 ответ


1

Кажется, вы поняли следующее, но просто для ясности:

transfer16(uint16_t word), как следует из названия, сдвигает 16 бит/2 байта вместо 8 бит/1 байта, как transfer(uint8_t byte).

transfer(uint8_t* buffer, unsigned int size) с другой стороны, принимает указатель и количество байт для сдвига.

Теперь к арифметике указателей. Операции над переменными указателей зависят от их явного типа данных (а также от архитектуры процессора!). Поэтому в нашем случае +1 на uint8_t* val переместит указатель на 8 бит. +1 на uint32_t* val сделает это на 4 байта/32 бита.

Проверьте тип данных буфера

Это должно быть любое из следующих значений: char, unsigned char, uint8_t, int8_t

,