Работаем с Lcd дисплеем WH1602 в STM32 f4 discovery

Практически в любой микроконтроллерной системе есть необходимость выводить информацию пользователю, именно для этих целей и будем применять наш дисплей.
Выглядит он вот так:
 


 

Хотя может ещё быть вариант с пинами в два ряда сбоку…
Управляется такой дисплей очень просто. Есть два режима: по 8 проводной шине данны и по 4ёх проводной. Будем пользоваться первой системой т.к. она проще.
Другая не намного сложнее (данные нужно слать тетрадами), но отвлечёт от всей «магии»))

 Распиновка дисплея такая:


Обратите внимание, что дисплей питается от 5В в то время как контроллеры stm32 от 3,3В.
Упростим себе задачу и не будем считывать флаг занятости с устройства. Заменим эту функцию задержкой в коде. Следовательно пин 5 (RW) суем на землю.

ГРАБЛИ 1!! Пин 3 — регулировка контрастности дисплея.
Ложим её на землю видим закрашенные квадраты (таким образом можно проверить целостность дисплея). Для нормального вывода туда нужно напряжения 0,7-0,9В.
Делается это либо переменным резистором либо делителем напряжения.

Теперь разберёмся с тем как управлять. Каждая буква имеет свой код. Для латинского алфавита этот код совпадает с кодом символа (char), для русского можно создать массив с нужными кодами. Смотрите даташит.
Присоединили 8 пинов данных к ногам контроллера. Рекомендую это делать к соответствующим ногам чтобы сразу писать в регистр без сдвигов данных.
т.е.

DB7 — PC7
DB6 — PC6

и так далее…
Это всё существенно упрощает и даёт нам разбираться.

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

void lcd_init_gpio() {
    RCC_AHB1PeriphClockCmd(LCD_RCC_GPIO,ENABLE);
    GPIO_InitTypeDef init;
    init.GPIO_Mode = GPIO_Mode_OUT;
    init.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_2 | GPIO_Pin_3 | GPIO_Pin_4 | GPIO_Pin_5 | GPIO_Pin_6 | GPIO_Pin_7 | GPIO_Pin_10 | GPIO_Pin_12;
    init.GPIO_OType = GPIO_OType_PP;

    GPIO_Init(LCD_PORT,&init);
}

Теперь посылаем данные.

void lcd_init() {
    lcd_init_gpio();
    int del = 99999;
    GPIO_ResetBits(LCD_PORT, LCD_RS_Pin);  // rs = 0

    delay(del);
    lcd_write_data(0b00110000); //init1

    delay(del);
    lcd_write_data(0b00110000); //init2

    delay(del);
    lcd_write_data(0b00110000); //init3

    delay(del);
    lcd_write_data(0b00111000); // function set  8bit 2line 5x8 dots

    delay(del);
    lcd_write_data(0b00001111); // display on + cursor underline + blinking

    delay(del);
    lcd_write_data(0b00000001); //clear

    delay(del);
    lcd_write_data(0b00000110); //entry mode set

    delay(del);
    lcd_write_data(0b00000010); // return to home

    delay(del);
    GPIO_SetBits(LCD_PORT,LCD_RS_Pin);  //rs = 1
}

Обратите внимание, что пин RS нужно установить в ноль, чтобы контроллер дисплея воспринял управляющие команды. Иначе он решит что это данные.
Теперь о функции записи данных. она посылает данные на указанные в ноги.
Я соблюдал номера ног и номера разрядов данных, поэтому меня интересует только порт на который подключен дисплей.

void lcd_write_data(u16 data) {
    GPIO_SetBits(LCD_PORT,data | LCD_E_Pin);
    delay(0xFFFF);
    GPIO_ResetBits(LCD_PORT,LCD_E_Pin | data);
}

Мы «выставляем» данные на ноги порта соединённого с lcd и устанавливаем пин E в 1.
Ждём пока данные «зарегистрируются» и устанавливаем E в ноль. Остальные пины тоже сбрасываем.

Вот и всё. Уже сейчас можно выводить порции данных на дисплей.
Но мы ещё опишем функцию для перемещения курсора:

void lcd_set_cursor(int line,int pos) {
    pos |= 0b10000000;
    if (line == 1) {
        pos += 0x40;
    }
    lcd_write_cmd(pos);
}

line — номер строки (0 или 1)
pos — позиция. тоже от 0 до 16.

Так как коды символов совпадают, можно также написать функцию для вывода строк:

void lcd_write_str(char*str) {
    do {
        lcd_write_data(*str);
    }while(*++str);
}

Задержку я сделал просто циклом:

void delay(unsigned int s){
    while(--s > 0) {
        __NOP();
    }
}

Для работы также нужно определить константы порта и пинов RS,E
У меня вот так:

#define LCD_PORT GPIOC
#define LCD_RCC_GPIO RCC_AHB1Periph_GPIOC
#define LCD_E_Pin GPIO_Pin_12
#define LCD_RS_Pin GPIO_Pin_10

Вот собственно архив с либой.

зы не претендую на самый крутой код и прочее. Даю гарантию работоспособности в Eclipse + st-util + stm32f4discovery + wh1602b

Доказательства:

 

Похожий код:

Фото аватара
Алексей Петров

Программист, разработчик с 5 летним опытом работы. Учусь на разработчика игр на Unity и разработчика VR&AR реальности (виртуальной реальности). Основные языки программирования: C#, C++.

Оцените автора
Бла, бла код
Добавить комментарий