Дисплеи, датчики и прочие функциональные узлы, управляемые МК.
Ответить

OLED дисплей с контроллером SSD1306 + AVR

Вс сен 18, 2016 18:30:22

Уважаемые форумчане. Есть у кого-нибудь библиотека для работы с OLED дисплеем 128х64 SSD1306 с микроконтроллером AVR. Нигде ничего вразумительного не могу найти. Может кто подключал. Дисплей вот такой:
Изображение

Re: OLED дисплей с контроллером SSD1306 + AVR

Вс сен 18, 2016 20:08:08

Вбил в поисковик всего-лишь строку "SSD1306". Результат - https://www.yandex.ru/yandsearch?clid=9 ... 74222223.1
А Вы пробовали ? :dont_know:
И статьи, и всякие блоги, исходники, библиотеки, .... Всё есть.

Re: OLED дисплей с контроллером SSD1306 + AVR

Вс сен 18, 2016 20:30:58

А вы сами эти статьи смотрели? 90% - это подключение к Ардуино, остальное STM....

Re: OLED дисплей с контроллером SSD1306 + AVR

Вс сен 18, 2016 20:35:00

Вот вроде что-то нащупал... Буду пробовать, но уже завтра.... Если всё получится - выложу исходники)

Re: OLED дисплей с контроллером SSD1306 + AVR

Вс сен 18, 2016 21:48:54

Dr. Alex писал(а):А вы сами эти статьи смотрели?
Да. И исходники смотрел. Вполне себе нормально-читабельный код. И не важно под какой он МК, всё упирается всего-лишь в модуль SPI (настройка, отправка байта). Для своего МК подправить - нет проблем.

Re: OLED дисплей с контроллером SSD1306 + AVR

Пн сен 19, 2016 06:26:14

В первом посте модуль с i2c ...

Re: OLED дисплей с контроллером SSD1306 + AVR

Вт сен 20, 2016 08:32:48

Да! А у вас что-то на него есть?

Re: OLED дисплей с контроллером SSD1306 + AVR

Вт сен 20, 2016 09:34:20

А что нужно кроме даташита на контроллер?
Да и в сети примеров как грязи, и хрен с ним что они на аурдунью и стм... :)))
Заказал несколько, придут запущу с STM32F0, тогда поговорим...

Re: OLED дисплей с контроллером SSD1306 + AVR

Вт сен 20, 2016 09:49:13

Да что-то я даташит никак не могу раскурить....

Re: OLED дисплей с контроллером SSD1306 + AVR

Сб сен 24, 2016 07:02:25

Не можете? Там раскуривать, мягко говоря, нечего.
Если бы взяли SPI - я бы свои "выкрутасы" мог сбросить, а вот I2C - не особо люблю эту шину "исторически" у нас не сложилось изначально, хотя в последствии и научился работать, но... SPI как-то проще.

Собственно, даже в случае с I2C проблем быть не должно. Инициализируете - получаете "мусор" на экране. Заливаете нулями память (очистка), а дальше - рисуете что хотите.

Собственно, как это работает у меня (вариант с SPI шиной, но переписать аппаратные функции, думаю, труда не должно составить).
Код:
void LCD_Init(void) {
   LCD_PORT |= (1<<RESET_PIN);
   send_cmd(0xAE);      // Display OFF
   // multiplex ratio
   send_cmd(0xA8);
   send_cmd(0x3F);
   // display offset
   send_cmd(0xD3);
   send_cmd(0x00);
   // set display startline(64)
   send_cmd(0x40);
   // segment remap(col.127 mapped to SEG0)
   send_cmd(0xA1);
   // set COM output scan direction
   send_cmd(0xC8);
   // set addressiing mode is "horisontal"
   send_cmd(0x20);
   send_cmd(0x00);
   // set COM pins hardware configuration   
   send_cmd(0xDA);
   send_cmd(0x12);
   // pre-charge period
   send_cmd(0xD9);
   send_cmd(0xE1);
   // set VCOMH deselect level
   // Brightness
   send_cmd(0xDB);
   send_cmd(0x10);
   // contrast control
   send_cmd(0x81);      // Set contrast cmd
   send_cmd(0x01);      // Contrast value
   // set entire display ON/OFF
   send_cmd(0xA4);
   // set normal,inverse display
   send_cmd(0xA6);
   send_cmd(0xD5);      //clock divide, OSC freq
   send_cmd(0xF0);
   // enable sharge pump
   send_cmd(0x8D);
   send_cmd(0x14);
   // display ON   
   send_cmd(0xAF);      // Вот здесь появляется "мусор"
};


В вашем случае аппаратно-зависимые функции должны выглядеть как-то так:
Код:
// Инициализация интерфейса I2C
void I2C_init(void){
   PRR0 &= ~(1<<PRTWI);         // Разрешаем работу интерфейса TWI
   TWBR = TWBR_val;
};
uint8_t I2C_start(uint8_t address){
   unsigned int RetryCount = 0;         // Счётчик попыток.
   TWCR = 0;               // reset TWI control register
   TWCR = (1<<TWINT) | (1<<TWSTA) | (1<<TWEN);   // transmit START condition
   // wait for end of transmission
   while( !(TWCR & (1<<TWINT)) )         // Ждём, пока переферия не сбросит бит занятости.
   {
      RetryCount++;            // Считаем таймер...
      if (RetryCount > 20000) break;      // Если ждём слишком долго - выход.
   };
   // check if the start condition was successfully transmitted
   if((TWSR & 0xF8) != TW_START){ return 1; }
   // load slave address into data register
   TWDR = address;
   // start transmission of address
   TWCR = (1<<TWINT) | (1<<TWEN);
   // wait for end of transmission
   while( !(TWCR & (1<<TWINT)) )
   {
      RetryCount++;
      if (RetryCount > 20000) break;
   };
   // check if the device has acknowledged the READ / WRITE mode
   uint8_t twst = TW_STATUS & 0xF8;
   if ( (twst != TW_MT_SLA_ACK) && (twst != TW_MR_SLA_ACK) ) return 1;
   return 0;
};
uint8_t I2C_write(uint8_t data){
   unsigned int RetryCount = 0;
   // load data into data register
   TWDR = data;
   // start transmission of data
   TWCR = (1<<TWINT) | (1<<TWEN);
   // wait for end of transmission
   while( !(TWCR & (1<<TWINT)) )
   {
      RetryCount++;
      if (RetryCount > 60000) break;
   };
   if( (TWSR & 0xF8) != TW_MT_DATA_ACK ){ return 1; }
   return 0;
};
uint8_t I2C_read_ack(void){
   unsigned int RetryCount = 0;
   // start TWI module and acknowledge data after reception
   TWCR = (1<<TWINT) | (1<<TWEN) | (1<<TWEA);
   // wait for end of transmission
   while( !(TWCR & (1<<TWINT)) )
   {
      RetryCount++;
      if (RetryCount > 60000) break;
   };
   // return received data from TWDR
   return TWDR;
};
uint8_t I2C_read_nack(void){
   unsigned int RetryCount = 0;
   // start receiving without acknowledging reception
   TWCR = (1<<TWINT) | (1<<TWEN);
   // wait for end of transmission
   while( !(TWCR & (1<<TWINT)) )
   {
      RetryCount++;
      if (RetryCount > 60000) break;
   };
   return TWDR;            // return received data from TWDR
};
void I2C_stop(void){
   // transmit STOP condition
   TWCR = (1<<TWINT) | (1<<TWEN) | (1<<TWSTO);
   _delay_us(5);            // Без этой паузы не получается передать STOP. И в отладке всё становится грустно.
                  // Самое смешное, что в железе работает нормально.
   TWCR = 0;
};



Дальше. Определитесь, где у Вас будет находиться пин переключения режима данные/команда и опишите его в следующи функциях:
Код:
void ssd1306_SendCMD(uint8_t cmd) {
 PORTD &= ~1;
 I2C_write(cmd);
};
void ssd1306_SendData(uint8_t data) {
 PORTD |= 1;
 I2C_write(data);
};

Ну, как-то так.
Дерзайте.
Учтите, в данном коде КУЧА мест, где не проведена инициализация портов, но думаю разберётесь ;)

Re: OLED дисплей с контроллером SSD1306 + AVR

Сб сен 24, 2016 12:55:56

Ну во-первых я взял I2C потому что другого не видел). А во-вторых - спасибо!

Re: OLED дисплей с контроллером SSD1306 + AVR

Сб сен 24, 2016 13:23:35

Пару недель назад тоже возился с такими I²C дисплеями, добавлял в свой проект.

Если интересно - можете глянуть исходники. I2C реализован программный, т.к. аппаратный у меня используется для других целей и работает на 100кГц. По умолчанию код заточен на выполнение на ATmega32u4 на 16МГц (использую Arduino Leonardo в качестве платы с МК и выводами), но это легко правится под себя в Makefile и pins.h.

Re: OLED дисплей с контроллером SSD1306 + AVR

Сб сен 24, 2016 13:34:24

Спасибо - гляну. В AVR Studio 4 откроется?

Re: OLED дисплей с контроллером SSD1306 + AVR

Сб сен 24, 2016 13:38:08

Не знаю. Написано под avr-gcc плюс сборка через make - можно компилировать хоть из консоли.

Сам я в качестве IDE использую QtCreator, там же в исходниках файлы проекта именно под него.

Re: OLED дисплей с контроллером SSD1306 + AVR

Сб сен 24, 2016 13:42:17

Ладно, буду что-то пробовать)))) :beer:

Re: OLED дисплей с контроллером SSD1306 + AVR

Сб сен 24, 2016 13:44:51

А под какой контроллер надо? Скажите контроллер, частоту, используемые ножки для SDA/SCL - за минуту могу собрать, там и проверите.

Re: OLED дисплей с контроллером SSD1306 + AVR

Сб сен 24, 2016 14:01:09

Хочу попробовать под Мегу8, ножки стандартные: PC5 - SCL, PC4 - SDA. Частота 12МГц.

Re: OLED дисплей с контроллером SSD1306 + AVR

Сб сен 24, 2016 14:08:20

Нет, мой вариант тут не подойдёт.

Я стремился к повышению скорости отрисовки, поэтому изначально картинка (шрифты, графика) отрисовывается в буфер в ОЗУ размером 1кБ, а потом уже этот буфер целиком отправляется в дисплей. Поэтому тут нужен контроллер с памятью больше 1кБ. Например, ATmega32 или ATmega328, или ATmega32u4.

Шина I²C и без того достаточно медленная, поэтому при другом подходе, без кадрового буфера, придётся при каждой отрисовке каждой мелочи позиционрироваться на экране, и накладные расходы на требуемые для этого команды будут слишком большими.

Re: OLED дисплей с контроллером SSD1306 + AVR

Сб сен 24, 2016 14:09:51

Ладно, и на этом спасибо! Буду ковырять) Тем более под Ардуинкой запустил)))))

Re: OLED дисплей с контроллером SSD1306 + AVR

Сб сен 24, 2016 18:02:55

Забавы ради потестировал скорость путём отображения анимации (7 кадров поочерёдно). Исходную gif-ку выкопал на просторах сети.

Ответить