Эксперимент #26: Использование графического дисплея на контроллере SBN1661G (SED1520).

Исходный материал: PIC16F877A, WG12232E-YYK-NA.

WG12232E-YYK-NA представляет собой графический дисплей с разрешением 122×32,габариты 80.0×36.0 , напряжение питания 5В, питание подсветки 4.2В. В основе дисплея лежит контроллер SBN1661G(SED1520) который может организовать матрицу разрешением 80×32. В нашем случае разрешение составляет 122×32 пикселя, а это значит что используется два контроллера, о чем свидетельствуют выводы CS1 и CS2 дисплея, которые предназначены для выбора левого или правого контроллера. Управление дисплея осуществляется по пятнадцати линиям: 8 линий данных, шесть линий управления и одна линия внешнего тактирования.

Распиновка и описание выводов WG12232E-YYK-NA:

Адресация пиксельных матриц:

Каждая половина дисплея состоит из четырех строк по вертикали и шестидесяти одного столбца по горизонтали. Каждый столбец имеет размер один байт, в него мы и пишем непосредственно наши данные. За один цикл чтения/записи мы можем обратиться минимум к одному столбцу, т.е. обратиться к одному пикселю нельзя. Если выбрать нужный нам столбец и записать в него данные, то при следующем цикле записи адрес можно столбца можно не указывать, (если это требуется) счетчик столбцов инкрементируется автоматически(это удобно например при выводе текстовой информации). Счетчик страниц автоматически не инкрементируется.

Описание команд дисплея:

Схема подключения дисплея к МК:

Для сборки использовались следующие рисунки печатных плат:

Плата для подключения дисплея

И плата для подключения МК

При распечатке рисунков плат – зеркалить не надо.

Написание протокола обмена данными:

Начну с единственной неприятной особенности дисплея – это вывод CL. Для того что бы дисплей нормально начал функционировать, нужно завести на этот вывод сигнал примерно два, три килогерца. Если все нормально, то будет работать изменение контрастности, т.е. без этого сигнала нельзя регулировать контрастность. Я использовал для этого аппаратный ШИМ PIC16F877A.Настройка следующая:

Расчет ШИМ:

  1. при PR2 = 255 и предделитель = 1
  2. Fpwm = FOSC/((PR2 x 1) x 4 х предделитель)
  3. Fpwm = 4000000/((250 x 1) x 4 x 1) = 4000Гц = 4Кгц
  4. PR2 = FOSC/(Fpwm x 4 x prescaler TMR2) – 1
  5. PR2 = 4000000/(4000 x 4 x 1) – 1 = 250
  6. Период шим = ((PR2)+1) x 4 x Tosc x (prescaler TMR2)
  7. Период шим = ((250)+1) x 4 x 4 x (1) = 1004

Код программы:

PR2 = 250;//регистр периода
CCPR1L = 128;CCP1X = 0;CCP1Y = 0;//cкважность шим
TRISC2 = 0;//наспраиваем линию на выход
T2CKPS1 = 0;
T2CKPS0 = 0;//выбор коэффициента деления предделителя 1:1
TMR2ON = 1;//включение таймера TMR2
CCP1M3 = 1;
CCP1M2 = 1;//включаем ШИМ режим

Теперь сам протокол. Для начала выберем выводы для подключения:

#define E RC1//Строб разрешения чтения / записи
#define RW RB0//Выбор: чтение/запись
#define A0 RC3//Выбор: команды/данные
#define CS1 RC5//Е1 Выбор кристалла 1
#define CS2 RC4//Е2 Выбор кристалла 2
#define RST RC0//RES Сброс (начальная установка)
#define DATA_BUS PORTD//шина данных

Инициализация МК:

void INIT_MK (void)
{
INTCON = 0;  // чистим регистр прерываний
TRISA = 0b00000000; // направление работы ножек порта А
TRISB = 0b00000000; // направление работы ножек порта В
TRISC = 0b00000000;
TRISD = 0b00000000;
CMCON = 0x07; // отключение компараторов
PORTA = 0; // очищаем порт А
PORTB = 0; // очищаем порт Б
PORTC = 0; // очищаем порт C
PORTD = 0;
RBPU = 1;  // подтягивающие R выкл
RST = 0;
CS1 = 0;//активируем кристалл
CS2 = 0; //активируем кристалл
}

Пишем функцию стробирования:

void LCD_STROBE (void)//функция стробирования
{
E = 0;
E = 1;
}

Пишем функцию записи в дисплей:

void LCD_WRITE(unsigned char data)//функция отправки данных на шину
{
DATA_BUS = data;
LCD_STROBE();
}

Пишем функцию для отправки команд:

void LCD_WRITE_COMAND(unsigned char data)//функция отправки команды
{
A0 = 0;RW = 0;
LCD_WRITE(data);
}

Пишем функцию отправки данных:

void LCD_WRITE_DATA(unsigned char data)//функция отправки данных в ОЗУ
{
A0 = 1;RW = 0;
LCD_WRITE(data);
}

Инициализация дисплея:

  1. Подать логический ноль на вывод RES на время не менее 10мкс
  2. Подать логическую единицу на вывод RES
  3. Ожидать сброса бита RESET в байте состояния или выждать не менее 2 мс;
  4. Подать команду снятия флага RMW (END);
  5. Подать команду включения обычного режима работы (Static Drive ON/OFF);
  6. Подать команду выбора мультиплекса (Duty Select);
  7. Подать команду включения дисплея (Display ON/OFF).

Пишем:

void LCD_INIT(void)//функция инициализации
{
RST = 0;
__delay_us(15);//удерживаем вывод RES не менее 10 мкс в состоянии лог.нуля
RST = 1;
__delay_ms(5);//ожидать сброса бита RESET в байте состояния или выждать не менее 2 мс
LCD_WRITE_COMAND(0b11101110);//подать команду снятия флага RMW (END)
LCD_WRITE_COMAND(0b10100100);//подать команду включения обычного режима работы (Static Drive ON/OFF)
LCD_WRITE_COMAND(0b10101001);//подать команду выбора мультиплекса (Duty Select)1/32
LCD_WRITE_COMAND(0b10100000);//ADC Select обратное соответствие (движение слева на пправо)
LCD_WRITE_COMAND(0b10101111);//подать команду включения дисплея (Display ON/OFF)
}

Пишем функцию выбора страницы и столбца:

void LCD_SET_ADDRESS(unsigned char addres,unsigned char page)//функция выбора адреса и страницы
{
LCD_WRITE_COMAND(addres);//пишем адрес
page = page ^ 0b10111000;
LCD_WRITE_COMAND(page);//пишем страницу
}

Очистка дисплея:

void LCD_CLEAR (void)//очистка дисплея
{
unsigned char addres = 0;
unsigned char page = 0;
unsigned char count;
unsigned char cicle;
CS1 = 0;
CS2 = 0;
for(cicle = 0;cicle < 4; cicle++)
{
for(count = 0; count < 61; count++)
{
LCD_SET_ADDRESS(addres,page);
LCD_WRITE_DATA(0);//Записали  данные
addres++;
}
page++;
addres = 0;
}
}

Этих функций достаточно, что бы отправлять данные ЖК. Например, что бы записать данные в первую страницу и десятый столбец нужно вызвать функцию выбора адреса, а затем вызвать функцию для записи данных:

void main (void)
{
INIT_MK();//начальная установка МК
LCD_INIT();//инициализация дисплея
LCD_CLEAR();//очистка дисплея

LCD_SET_ADDRESS(10,0);//выбор страницы и столбца
LCD_WRITE_DATA(0xFF);//пишем данные
while(1)
{
}
}

Результат работы программы:

Данные отобразились в обоих половинках поскольку активны оба кристалла.

Пробовать собирать только в железе, данный дисплей в Протеусе работает некорректно.

Эксперимент #26: Использование графического дисплея на контроллере SBN1661G (SED1520).: 13 комментариев

  1. как всегда Сарж меня опередил,зато я вроде как с модбус закончил,много времени потратил на подъем этого протокола,уж больно везде он стал требоваться

    Ответить

    sarge Ответил:

    Это не я писал, статья и работа Сергея Евстратова, там вверху написано, так что чуть что вопросы к нему :)

    Ответить

  2. Нет состояний CS1, CS2 во время инициализации. Электрический конфликт, если CS1 = 0, или CS2 = 0, или CS1=CS2=0 на шинге данных ОБЕСПЕЧЕН !!!

    Ответить

    sdn_ Ответил:

    DEL предудущий мой пост

    Ответить

    electronic255 Ответил:

    первоначальное состояние задается в функции INIT_MK(); , потом вызывается инициализация LCD_INIT(); , если CS1=CS2=0 то данные будут просто писаться в оба контроллера дисплея, когда мы пишем CS1=0 или CS2=0 , выбираем правый и левый контроллер, откуда должен взяться электрический конфликт? пока писал программу глюков ни каких не было

    Ответить

  3. На самом деле: при комбинации A0 = 0 + CS1=CS2=0 или CS1=0, CS2=0 модуль, по питанию, начинает потреблять значительный ток (около 32 ма), если последовательно с модулем, в его + питания установлен, ограничительный резистор или в этот момент напряжение на модуле падает ниже 3 в, то и возникает тот самый электрический конфликт между портом м/к и модулем (ток потребления модуля растет до сотен миллиампер). Модуль не может выйти из этого состояния самостоятельно.
    p.s.
    Ошибка в описании команды RESET: номер страницы, после её отработки, = 3, а не 0

    Ответить

  4. Подать команду включения обычного режима работы (Static Drive ON/OFF)
    Эта команда лишняя, так как после сброса, однобитный регистр (Static Drive ON/OFF) уже содержит лог 0. То есть нормальный режим включен сразу же после сброса автоматически.

    Ответить

  5. На самом деле: при комбинации A0 = 0 + CS1=CS2=0 или CS1=0, CS2=0 модуль, по питанию, начинает потреблять значительный ток (около 32 ма) + выдача команды записи инструкции. (в этот момент)

    Ответить

    electronic255 Ответил:

    состояние выводов A0, CS1 и CS2 тут ни при чем, 32ма хавает схема целиком, т.е проц и еще подсветка LCD, отключите подсветку и ток будет в пределах 7ма, уберите все линии данных и запитайте проц с дисплеем и подсветкой и ток останется практически тот же,где то 30-32ма,а вот откуда вы сотни миллиампер взяли я так и не понял

    Ответить

  6. состояние выводов A0, CS1 и CS2 тут ни при чем, 32ма хавает схема целиком, т.е проц и еще подсветка LCD, отключите подсветку и ток будет в пределах 7ма

    Теоретики, они такие теоретики. Поставьте токоограничительный резистор 100 ом последовательно со вторым пином (+ питания) и наблюдайте за просадками напряжения между первым и вторым пином (+ и -) в зависимости от выдачи инструкции/команды. Будете удивлены.
    А сотни миллиапер – это когда напряжение питания у контроллера выше хотя бы на вольт, чем напряжения питания модуля. Тогда открыт один из защитных диодов выводов порта модуля.
    Через него и выводы порта м/к в сумме и набегают сотни миллиапер.

    Ответить

    electronic255 Ответил:

    состояние выводов A0, CS1 и CS2 тут ни при чем, 32ма хавает схема целиком, т.е проц и еще подсветка LCD, отключите подсветку и ток будет в пределах 7ма

    это я проверил на практике.

    Зачем в цепи питания резистор на 100Ом если он не нужен? У меня работает нормально,ни чего не греется и не глючит, если вы считаете что код корявый то выложите нормальный код

    Ответить

Добавить комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *

Можно использовать следующие HTML-теги и атрибуты: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code class="" title="" data-url=""> <del datetime=""> <em> <i> <q cite=""> <strike> <strong> <pre class="" title="" data-url=""> <span class="" title="" data-url="">

Этот сайт использует Akismet для борьбы со спамом. Узнайте как обрабатываются ваши данные комментариев.