PIC Урок 20. LCD 20×4. 4-битный режим



Давайте немного отдохнём от сложных модулей и поработаем с нашим старым добрым символьным дисплеем, собранном на контроллере HD44780, в котором доступно для отображения 80 символов, организованных в 4 строки по 20 символов в каждой.

В 10 уроке мы подключали данный режим, используя все его контакты данных, в 8-битном режиме. Но последнее время всё больше актуальна возможность контроллера дисплея работать в 4-битном режиме, когда мы подключаем только 4 ножки данных и передаём по ним байты данных только по ножкам D4-D7, сначала один полубайт, потом второй.

Также нам такой режим потребуется не только для экономии ножек портов, а ещё для того, чтобы мы могли работать с переходником, который преобразует сигналы последовательной шины I2C в сигналы параллельной шины. Данный переходник используется именно для такого дисплея и для связи его с дисплеем используется именно 4-битный способ передачи данных. Поэтому и родился такой внеочередной урок.

Плату и контроллер мы будем использовать те же, что и в 10 уроке, только подключать в разъём мы дисплей не будем, а подключим его туда с помощью проводов, пропустив ненужные контакты D0-D3.

Подключение будет выглядеть вот таким вот способом

 

 

Проект за основу мы возьмём из 10 урока с именем LCD2004_8BIT и назовём его LCD2004_4BIT.

Откроем проект в MPLAB.X, сделаем его главным, а в настройках убедимся, что программатор не будет питать схему, так как питать мы её будем от внешнего источника питания.

Идём сразу в файл lcd.h и добавим там макрос частоты тактирования, так как мы будем использовать стандартные задержки

 

#include <xc.h>

//--------------------------------------------------------------

#define _XTAL_FREQ 4000000

//--------------------------------------------------------------

 

Так как отправлять информацию физически в контроллер дисплея мы будем только по 4 проводам (полубайтами или тетрадами), то перейдём в файл lcd.c сначала в функцию настройки портов LCD_PORT_init, удалим всё её тело, и  для порта D инициализируем направление передачи данных только нужным ножкам, а заодно то же самое проделаем и для порта C, так как используем мы там только 3 ножки

 

void LCD_PORT_init()

{

  TRISC4=0;

  TRISC5=0;

  TRISC6=0;

  TRISD4=0;

  TRISD5=0;

  TRISD6=0;

  TRISD7=0;

}

 

Также в связи с тем же ниже этой функции напишем функцию передачи полубайта (тетрады) в 4-битный порт контроллера дисплея

 

//--------------------------------------------------------------

void sendhalfbyte(unsigned char c)

{

  c<<=4;

  PORTD&=0b00001111;

  PORTD|=c;

  e=1;

  __delay_us(1);

  e=0;

  __delay_us(50);

}

//--------------------------------------------------------------

 

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

Затем мы стираем информацию на информационных входах, сгенерируем импульс на линии E, и немного подождём.

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

Первым делом удалим из её тела передачу числа в порт C

 

PORTD=c;

 

Создадим локальную переменную

 

void sendbyte(unsigned char c, unsigned char mode)

{

  unsigned char hc=0;

 

После определения режима передачи данных или команды мы присвоим данной переменной старшую часть нашего байта

 

else rs=1;

hc=c>>4;

 

 

Удалим весь код после данной операции из тела функции и передадим в шину сначала старшую тетраду байта, а затем младшую

 

  hc=c>>4;

  sendhalfbyte(hc);sendhalfbyte(c);

}

 

Функцию инициализации LCD_Init нам тоже придётся подправить, так как инициализация 4-битного режима несколько отличается от инициализации 8-битного

 

 

Причём проще тело функции будет не подправить, а полностью переписать, поэтому мы данное тело удалим.

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

Первым делом сразу задержка на 50 милисекунд, дадим включиться дисплею

 

void LCD_Init()

{

  __delay_ms(50);

 

Очистим все уровни на участвующих ножках шины

 

__delay_ms(50);

PORTC &= ~0x70;

PORTD &= ~0xF0;

 

Подождём ещё немного

 

PORTD &= ~0xF0;

__delay_ms(100);

 

Дальше передадим серию команд, по которым контроллер дисплея поймёт, что с ним хотят общаться именно по 4 проводам

 

__delay_ms(100);

sendhalfbyte(0x03);

__delay_us(4500);

sendhalfbyte(0x03);

__delay_us(4500);

sendhalfbyte(0x03);

__delay_us(200);

sendhalfbyte(0x02);

 

 

Настроим режимы. От той же самой операции для 8-битного режима наша операция будет отличаться только 1 битом

 

sendhalfbyte(0x02);

__delay_ms(1);

sendbyte(0x28, 0);//mode 4 bit, 2 lines (from our large display is 4 lines, font 5x8

 

Остальное практически не изменилось, за исключением некоторых деталей, мы установили курсор на место (невизуальный или воображаемый, визуального у нас нет)

 

  sendbyte(0x28, 0);//mode 4 bit, 2 lines (from our large display is 4 lines, font 5x8

  sendbyte(0x0C,0);//Display ON, Cursor OFF, blink OFF

  __delay_ms(1);

  sendbyte(0x01,0);// Clear Display

  __delay_ms(2);

  sendbyte(0x06,0);// direction left to right

  __delay_ms(1);

  sendbyte(0x02,0);//Cursor reset

  sendbyte(0X80,0);//SET POS LINE 0

  __delay_ms(2);

}

 

Ниже функции инициализации добавим также функцию очистки дисплея, она нам непременно пригодится

 

//--------------------------------------------------------------

void LCD_Clear(void)

{

  sendbyte(0x01, 0);

  __delay_us(1500);

}

//--------------------------------------------------------------

 

Добавим в заголовочном файле на данную функцию прототип, попробуем собрать код и прошить контроллер.

А вот и результат

 

 

Так как мы сегодня быстро справились со своей задачей, то мы ещё можем написать небольшой тест, который будет выводить цифры в реальном времени, что сделает наш тест немного динамичнее.

Для этого сначала перейдём в файл main.h и добавим там возможность работы со строковыми функциями

 

#include <xc.h>

#include <stdio.h>

#include <string.h>

 

Далее идём в файл main.c и добавим там глобальный символьный массив

 

#include "main.h"

//------------------------------------------------

char str01[30]={'\0'};

//------------------------------------------------

 

Затем переходим в функцию main() и начала очистим дисплей через 2 секунды после отображения наших строк

Объявим локальную переменную для счёта

 

void main()

{

  unsigned int i = 0;

 

После вывода строк на дисплей подождём 2 секунды и очистим дисплей

 

LCD_String((char*)"String 4");

__delay_ms(2000);

LCD_Clear();

 

А теперь мы в бесконечный цикл добавим вот такой вот алгоритм

 

while(1)

{

  i++;

  sprintf(str01,"%5u",i);

  LCD_SetPos(4,3);

  LCD_String(str01);

  sprintf(str01,"%5u",65536-i);

  LCD_SetPos(10,3);

  LCD_String(str01);

  __delay_ms(200);

}

 

Мы инкрементируем наш счётчик, выводим показания в определённую позицию, а также в другую позицию мы выводим показания данного счётчика, но вычтенные из числа 65536. Таким образом, согласно задержке, примерно 5 раз в секунду наши данные будут обновляться на дисплее. Мы используем затирание лишних символов для того, чтобы постоянно не очищать дисплей.

Соберём код, прошьём контроллер и посмотрим результат нашей работы на практике

 

 

Всё отлично работает!

Таким образом, данный урок нас научил работать с символьным дисплеем в 4-битном режиме, что позволило нам освободить целых 4 ножки порта.

Всем спасибо за внимание!

 

 

Предыдущий урок Программирование МК PIC Следующий урок

 

Исходный код

 

 

Купить программатор (неоригинальный) можно здесь: PICKit3

Купить программатор (оригинальный) можно здесь: PICKit3 original

Отладочную плату PIC Open18F4520-16F877A можно приобрести здесь: PIC Open18F4520-16F877A

Дисплей LCD 20×4 можно приобрести тут: Дисплей LCD 20×4

 

 

Смотреть ВИДЕОУРОК (нажмите на картинку)

 

PIC LCD 20x4. 4-битный режим

3 комментария на “PIC Урок 20. LCD 20×4. 4-битный режим
  1. Alex:

    Подскажите как можно подправить прошивку, если к примеру данные RD0-RD3, а управляющие сигналы RD4 -> RS, RD5 -> E? Спасибо.

  2. Андрей:

    В исходном коде sendbyte(unsigned char c, unsigned char mode) — не исправлена.
    Там — unsigned char hc=0;
    PORTD=c; — а это надо вычеркнуть

    ———

    Alex:
    void sendhalfbyte(unsigned char c)
    {
    //c<<=4;
    PORTD&=0b11110000;
    PORTD|=c;
    e=1;
    __delay_us(1);
    e=0;
    __delay_us(50);
    }
    -то есть убираем сдвиг.
    Ну и соотвественно TRISD меняем в инициализации.

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

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

*