В предыдущей части занятия мы познакомились с дисплеем, со схемой и её компонентами, а также создали и настроили проект.
Перейдём в файл lcd.c и начнём потихоньку писать библиотеку, используя накопленный опыт программирования других типов контроллеров.
Добавим макросы для ножек управления дисплеем
#include "lcd.h"
//--------------------------------------------------------------
#define rs RC4
#define rw RC5
#define e RC6
//--------------------------------------------------------------
Напомню, что ножка rs — это ножка для переключения режима данных — данные/команда. То есть если мы передаём данные, то на данной ножке мы предварительно устанавливаем высокий уровень, а если команду, то низкий.
Ножка rw служит для переключения режима направления данных. Если на ней уровень низкий, то мы данные в контроллер дисплея пишем, а если высокий, то читаем.
Ножка e — это ножка выбора дисплея. Перед передачей или приёмом данных мы на неё подаём низкий уровень, а после передачи мы уровень подаём высокий.
Время между опусканием и подниманием данной ножки регламентировано. Также регламентировано и время минимального нахождения ножки в высоком состоянии перед тем как записать данные и должно быть не менее 300 наносекунд. Данное время мы никак не будем программно выдерживать, так как мы ножку будем поднимать сразу после отправки данных и до следующей отправки у нас и так пройдёт. Также известно общее минимальное время для отправки данных в контроллер дисплея, то есть время всего цикла. Оно должно быть не менее 500 наносекунд. Но мы не будем выдерживать такие малые интервалы. Мы подождём побольше на всякий случай, по крайней мере так было в примере для контроллера, которые предоставила компания-производитель платы. Оставим такое же, когда будем писать функцию отправки байта в контроллер дисплея.
Так как нам потребуется небольшая задержка, то добавим для неё свою функцию, так как стандартная функция __delay_us почему-то у меня работать отказалась. Данную функцию я позавидовал в примере для платы, который нам предоставляет производитель в архиве
#define e RC6
//--------------------------------------------------------------
void LCD_delay()
{
int i;
for(i=0;i<19;i++);
}
//--------------------------------------------------------------
Добавим функцию инициализации ножек портов
//--------------------------------------------------------------
void LCD_PORT_init()
{
TRISC=0X00;
TRISD=0X00;
}
//--------------------------------------------------------------
Добавим функцию отправки байта в контроллер дисплея
//--------------------------------------------------------------
void sendbyte(unsigned char c, unsigned char mode)
{
PORTD=c;
if(mode==0) rs=0;
else rs=1;
rw=0;
e=0;
LCD_delay();
e=1;
}
//------------------------------------------------
В данной функции будет 2 параметра. Первый — это непосредственно значение отправляемого байта, а второй — это тип отправки — данные или команда.
Сначала мы сразу отправляем наш байт в регистр порта C, чтобы на его ножках выставились уровни, соответствующие значению нашего байта, так как именно ножки данного порта подключены к ножкам данных дисплея. Затем мы выставляем уровень на ножке RS в зависимости от того, команду или данные мы будем отправлять в дисплей. Далее мы устанавливаем низкий уровень на ножке RW, говоря контроллеру дисплея о том, что мы будем его использовать в режиме записи. Мы можем конечно установить данный уровень на этапе инициализации, так как читать мы из контроллера дисплея ничего не будем, но так всё-таки будет универсальнее, вдруг, когда-то будем работать в режиме чтения. Далее мы опускаем ножку E, применяем задержку, и затем поднимаем данную ножку. Данные должны будут уйти в дисплей.
Добавим функцию инициализации
//------------------------------------------------
void LCD_Init()
{
}
//------------------------------------------------
Начнём теперь писать непосредственно функцию инициализации дисплея.
Очистим дисплей
void LCD_Init()
{
sendbyte(0X01,0);//Clear Display
Используется вот такая функция
Зададим контроллеру дисплея использовать 8-битный режим, режим 2х линий (для 4-х строчного — это 4 линии) и формат 5х8
sendbyte(0X01,0);//Clear Display
sendbyte(0X38,0);//Function set: 8-bit bus mode,
//2-line display mode is set (2004 - 4-line), 5x8 dots format
Вот описание данной команды
Включим дисплей, отключим курсор и мигание последнего символа
//2-line display mode is set (2004 - 4-line), 5x8 dots format
sendbyte(0X0c,0);//Display ON, Cursor OFF, blink OFF
Описание команды:
Зададим направление написания текста влево
sendbyte(0X0c,0);//Display ON, Cursor OFF, blink OFF
sendbyte(0X06,0);//direction left to right
Описание команды
Установим курсор в начальное положение
sendbyte(0X06,0);//direction left to right
sendbyte(0X80,0);//SET POS LINE 0
}
Вот описание данной команды
Память DDRAM контроллера дисплея — это память, которая хранит коды символов, отображаемых в данный момент на дисплее. Вот мы и ставим указатель на 0 адрес данной памяти.
Эта память в дисплее 2004 распределена следующим образом по строкам
С инициализацией закончили.
Теперь добавим функцию вывода строки символов на дисплей в текущую позицию
//------------------------------------------------
void LCD_String(char* st)
{
unsigned char i=0;
while(st[i]!=0)
{
sendbyte(st[i],1);
i++;
}
}
//------------------------------------------------
Мы посылаем здесь байты с кодами символов в контроллер дисплея до тех пор, пока не встретимся с нулём. Это и есть окончание строки. Также обратите внимание, что режим мы используем уже для передачи данных, а не команд, так как пишем уже напрямую в DDRAM. Поэтому во втором аргументе функции передачи байта у нас 1, а не 0.
Выше только что написанной нами функции LCD_String добавим функцию установки указателя в требуемую позицию
//------------------------------------------------
void LCD_SetPos(unsigned char x, unsigned char y)
{
switch(y)
{
case 0:
sendbyte((unsigned char)(x|0x80),0);
break;
case 1:
sendbyte((unsigned char)((0x40+x)|0x80),0);
break;
case 2:
sendbyte((unsigned char)((0x14+x)|0x80),0);
break;
case 3:
sendbyte((unsigned char)((0x54+x)|0x80),0);
break;
}
}
//------------------------------------------------
Данная функция во входных аргументах имеет значения координат по горизонтали и вертикали.
Далее с помощью оператора вариантов мы отслеживаем координату по вертикали и затем посылаем команду для установки указателя в определенное место DDRAM контроллера дисплея, в которой в первом аргументе мы привязываемся к началу строки, используя вышедобавленную таблицу адресов DDRAM, прибавляем к началу строки координату по горизонтали и далее устанавливаем самый старший бит, который и заставит выполнить именно команду установки указателя.
Пока нам функций для работы с дисплеем хватит, поэтому перейдём в заголовочный файл lcd.h и добавим прототипы на функции, которые нам потребуется вызывать из внешних модулей
#include <xc.h>
//--------------------------------------------------------------
void LCD_PORT_init();
void LCD_Init();
void LCD_String(char* st);
void LCD_SetPos(unsigned char x, unsigned char y);
//--------------------------------------------------------------
Ну и теперь наконец-то мы можем что-то вывести на наш дисплей. Перейдём в файл main.c и добавим код в функцию main()
void main()
{
LCD_PORT_init();
LCD_Init();
LCD_String((char*)"String 1");
LCD_SetPos(2,1);
LCD_String((char*)"String 2");
LCD_SetPos(4,2);
LCD_String((char*)"String 3");
LCD_SetPos(6,3);
LCD_String((char*)"String 4");
while(1)
Мы сначала готовим порты, затем инициализируем наш дисплей. Самую первую строку мы выводим в нулевую позицию первой строки, а далее уже все остальные строки выводим на другие строки дисплея в определённые позиции, используя при этом нами написанную функцию позиционирования. Также помним, что строки и колонки считаются с 0, а не с 1.
Собираем проект, и если он нормально собрался, то попытаемся прошить наш контроллер.
Но так как из среды программирования мы прошиваем проект впервые, то давайте сначала настроим программатор, чтобы он ещё и питал нашу плату, потому что мы пока не подключали блок питания. Попробуем, справится ли программатор с питанием платы и дисплея.
Откроем свойства проекта и выберем слева наш программатор
Выберем справа вверху данного диалога пункт «Power», затем ставим галочку в квадратик, заставляя тем самым программатор питать нашу схему, напряжение оставим 5 вольт
Применим настройки и попробуем прошить проект. Для этого нажмём соответствующую кнопку в панели инструментов среды программирования MPLAB X
В процессе прошивания контроллера могут выдаваться некоторые предупреждения типа такого
С таким предупреждением мы можем смело согласиться. Здесь нас IDE предупреждает о том, чтобы мы не забывали, что иногда контроллеры питаются напряжением 3,3 вольта, и в этом случае мы рискуем его вывести из строя. Но мы знаем, что у нас плата питается напряжением 5 вольт, поэтому смело соглашаемся.
После прошивки мы должны увидеть вот такую картину
Все наши строки выведены на дисплей, правда контрастность слабовата. Возможно не хватает мощности питания от программатора.
Поэтому попробуем подключить к плате блок питания.
Только, чтобы данный процесс прошел безболезненно, сначала отключим наш программатор от порта USB, в свойствах проекта снимем галку с питания от программатора, которую мы только что установили, опять применим настройки, подключим обратно к шине USB программатор и подключим блок питания к плате.
Теперь мы увидим вот такую картину (правда, возможно, придется перепрошить контроллер)
Теперь совсем другое дело!
Итак, сегодня мы с вами сделали очень много полезного. Мы теперь можем прошивать контроллер прямо из среды программирования, также у нас появилась возможность отлаживать код в реальном контроллере. Также мы подключили новую плату с контроллером. Ну и также мы выполнили основную цель занятия: мы научились программировать символьный дисплей на контроллере HD44780. Теперь в последующих программах мы можем выводить на него некоторую информацию.
Всем спасибо за внимание!
Предыдущая часть Программирование МК PIC Следующий урок
Техническая документация на дисплей LCD2004
Купить программатор (неоригинальный) можно здесь: PICKit3
Купить программатор (оригинальный) можно здесь: PICKit3 original
Отладочную плату PIC Open18F4520-16F877A можно приобрести здесь: PIC Open18F4520-16F877A
Дисплей LCD 20×4 можно приобрести тут: Дисплей LCD 20×4</p
Смотреть ВИДЕОУРОК (нажмите на картинку)
Добавить комментарий