Использую дисплей UG-5664ASWEF01 (256x64) с драйвером SSD1322 и микроконтроллер Fujitsu MB96F696RB. Интерфейс SPI 4-wire для организации взаимодействия. Передача информации осуществляется асинхронно через прерывание из очереди длиной 1024 байта.
- Код: Выделить всё
/** инициализация таблицы градаций яркости */
static void lcd_set_gray_scale(void)
{
unsigned char cnt = 0;
unsigned char step = 0x0C;
unsigned char max_step = 0xB4;
spi_write(CMD, 0xB8); /** таблица градаций яркости */
for (cnt = step; cnt <= max_step; cnt += step)
spi_write(DTA, cnt);
spi_write(CMD, 0x00); /** разрешить работу таблицы градаций яркости */
}
static void lcd_set_col(unsigned char start, unsigned char end)
{
spi_write(CMD, 0x15); /** Set Column Address */
spi_write(DTA, start); /** начальный адрес */
spi_write(DTA, end); /** конечный адрес */
}
static void lcd_set_row(unsigned char start, unsigned char end)
{
spi_write(CMD, 0x75); /** Set Row Address */
spi_write(DTA, start); /** начальный адрес */
spi_write(DTA, end); /** конечный адрес */
}
static void lcd_set_start_line(unsigned char start)
{
spi_write(CMD, 0xA1);
spi_write(DTA, start);
}
static void lcd_set_wr_ram(void)
{
spi_write(CMD, 0x5C); /** Разрешает микроконтроллеру записать данные в RAM */
}
static void lcd_current_control(unsigned char val)
{
spi_write(CMD, 0xC7); // Master Contrast Current Control
spi_write(DTA, (val > 0x0F) ? 0x0F : val);
}
/** очистка дисплея */
static void lcd_clr(void)
{
unsigned int i = 0, j = 0;
lcd_set_col(0x1C, 0x5B); /** 112 SEG до 367 SEG = 112 SEG / 4 до 367 SEG / 4 = 0x1C - 0x5B */
lcd_set_row(0x00, 0x3F);
for (i = 0; i < 64; i++)
{
lcd_set_wr_ram();
for (j = 0; j < 128; j++)
spi_write(DTA, 0x00);
}
}
/** зарисовка дисплея */
static void lcd_fill(void)
{
unsigned int i = 0, j = 0;
lcd_set_col(0x1C, 0x5B); /** 112 SEG до 367 SEG = 112 SEG / 4 до 367 SEG / 4 = 0x1C - 0x5B */
lcd_set_row(0x00, 0x3F);
for (i = 0; i < 64; i++)
{
lcd_set_wr_ram();
for (j = 0; j < 64; j++)
{
spi_write(DTA, 0xFF);
spi_write(DTA, 0xFF);
}
}
}
/** сетка */
static void lcd_grid(void)
{
unsigned int x = 0, y = 0;
lcd_set_col(0x1C, 0x5B); /** 112 SEG до 367 SEG = 112 SEG / 4 до 367 SEG / 4 = 0x1C - 0x5B */
lcd_set_row(0x00, 0x3F);
for (y = 0; y < 64; y++)
{
lcd_set_wr_ram();
for (x = 0; x < 128; x++)
spi_write(DTA, (y & 0x01) ? 0xF0 : 0x0F);
}
}
/** список команд инициализации дисплея */
void lcd_init(void)
{
spi_write(CMD, 0xAB); /** 0xAB - внутренний регулятор Vdd, 0x01 - разрешить работу внутреннего регулятора для VDD */
spi_write(DTA, 0x01);
spi_write(CMD, 0xFD); /** Set Command Lock */
spi_write(DTA, 0x12); /** разблокировка */
spi_write(CMD, 0xB3); // Set Front Clock Divider / Oscillator Frequency
spi_write(DTA, 0xD0); // = reset / 1100b
spi_write(CMD, 0xCA); // Set MUX Ratio
spi_write(DTA, 0x3F); // = 63d = 64MUX
spi_write(CMD, 0xA2); // Set Display Offset
spi_write(DTA, 0x00); // = RESET
spi_write(CMD, 0xA1); // Set Display Start Line
spi_write(DTA, 0x00); // = register 00h
spi_write(CMD, 0xA0); // Set Re-map and Dual COM Line mode
spi_write(DTA, 0x14); // 10= Reset except Disable Nibble Re-map, Scan from COM[N-1] to COM0, where N is the Multiplex ratio
spi_write(DTA, 0x11); // 01= Reset except Disable Dual COM mode (MUX = 63)
spi_write(CMD, 0xB5); // Set GPIO
spi_write(DTA, 0x00); // = GPIO0, GPIO1 = HiZ, Input Disabled
spi_write(CMD, 0xB4); // Display Enhancement A
spi_write(DTA, 0xA0); // = Enable external VSL
spi_write(DTA, 0xB5); // = Normal (reset)
spi_write(CMD, 0xC1); // Set Contrast Current
spi_write(DTA, 0x9F); // = 0x7F - default
spi_write(CMD, 0xC7); // Master Contrast Current Control
spi_write(DTA, 0x0F);
spi_write(CMD, 0xB9); /** Сбрасывает таблицу градаций яркости в состояние по умолчанию (линейная таблица с нарастанием яркости от GS0 до GS1) */
spi_write(CMD, 0xB1); // Set Phase Length
spi_write(DTA, 0xE2); // 0xE2= Phase 1 period (reset phase length) = 5 DCLKs, Phase 2 period (first pre-charge phase length) = 14 DCLKs
spi_write(CMD, 0xD1); // Display Enhancement B
spi_write(DTA, 0xA2); // 0xA2 = Normal (default); 0x82 = reserved
spi_write(DTA, 0x20); // 0x20 = as-is
spi_write(CMD, 0xBB); // Set Pre-charge voltage
spi_write(DTA, 0x1F); // 0x17 = default; 0x1F = 0.60*Vcc (spec example)
spi_write(CMD, 0xB6); // Set Second Precharge Period
spi_write(DTA, 0x08); // 0x08 = 8 dclks (default)
spi_write(CMD, 0xBE); // Set VCOMH
spi_write(DTA, 0x07); // 0x04 = 0.80*Vcc (default); 0x07 = 0.86*Vcc (spec example)
spi_write(CMD, 0xA9); // Exit Partial Display // команда выключает режим отображения части экрана
spi_write(CMD, 0xA6); // Set Display Mode = Normal Display
}
При активации передачи данных по шине SPI выставляю Chip Select в 0 на время всей передачи данных/команд и в зависимости от типа передаваемой информации перед началом передачи очередного байта выставляю D/C#.
http://microsin.net/adminstuff/hardware/ssd1322-oled-controller.html
В семплах на данный драйвер ф-ция lcd_set_wr_ram() вызывается до циклов единожды (lcd_clr, lcd_fill, lcd_grid), но у меня в таком случае выводится только одна строка, а все остальные данные игнорируются. Поэтому выполняю lcd_set_wr_ram() каждый раз при переходе на следующую строку. Возможно я делаю что-то не так что приходится каждый раз разрешать запись в RAM дисплея?
В функции lcd_grid() предполагается, что на дисплее каждая строка в зависимости от её четности будет выводится 0x0F или 0xF0 соответственно, тем самым создавая сетку, но при выводе падает практически до минимума контрастность и яркость пикселей. На дисплее отображается частично сетка и частично сбитые по координатам пикселы. Возможно что-то не учтено, подскажите, пожалуйста.