Примеры CodeVisionAVR - Работа с ЖКИ HD44780.

Автор: Internet. Posted in Початківцям з CV AVR

Зміст статті

Попалась мне очень интересная информация , которой поделился пользователь Freerider (это я так дедуктивным методом догадался, так как прямого текста на автора я не нашел).

В общем я не редактируя текст провожу его полностью как изложил автор, довольно доходчиво, ну а для закрепления материала в конце этого монолога ,есть проект с протеусом.

 

Приступим!

Для начала нужно отконфигурировать подключение дисплея в мастере начального кода CVAVR. Там ничего, требующего какого-либо описания нет.

Перечень самых ходовых команд:

Очистка дисплея: lcd_clear();
Размещение надписи на дисплее задается функцией lcd_gotoxy(2,0); где цифра 2 означает что первый слева символ надписи будет выводиться в третью по счету ячейку дисплея слева, имеющую порядковый номер 1, так как счет ячеек идет с цифры 0.
Цифра 0 означает что надпись выводится в первую строчку сверху, 1 соответственно будет значить размещение надписи во второй строке, и.т.д.
Чтобы просто написать что-то на дисплее латиницей, достаточно применить следующий код;
lcd_gotoxy(1,0); // задаем положение первого символа
lcd_putsf("Radiokot");
В итоге на дисплей будет выведена надпись Radiokot

Вывод содержимого текстовых массивов

Можно создать текстовый массив в оперативной памяти контроллера или в памяти программ. В данном случае массивы, сидящие в разных типах памяти выводятся разными командами.
К примеру создадим текстовый массив в памяти программ:
flash char text_mass[] = "Radiokot.ru";
Для вывода его содержимого нужно воспользоваться функцией lcd_putsf
пример: lcd_putsf(text_mass);
На дисплей будет выведено: Radiokot.ru
Если же массив вписан в оперативную память контроллера:
char text_mass[] = "Radiokot.ru";
то его вывод осуществляется аналогично функцией lcd_puts(text_mass);
(без буквы f)
Чтобы просто вывести один символ, достаточно ввести команду:
lcd_putchar('D'); // Будет выведена просто буква D

Вывод произвольного символа из таблицы знакогенератора.

Для вывода какого-либо символа из таблицы знакогенератора дисплея, нужно посмотреть его номер в кодовой странице 0 в даташите.


Рисунок 1 Фрагмент таблицы 0 знакогенератора.

Мне захотелось вывести подряд два символа, первый символ - что помечен сиреневым цветом, и второй- тот, что помечен зеленым. Сиреневый символ имеет код в шестнадцатеричном виде xD1, зеленый символ имеет код x83, выводятся они на дисплей  следующим образом:
lcd_putsf(" xD1 x83");

Вывод русских символов.

Можно конечно, поизвращаться как указано строкой выше, а можно пойти более легким путем:
Были предложены разные варианты, такие как специальная функция-перекодировщик, и еще один вариант с прагмами.
Первый – лишнее утяжеление программы.
Второй вариант не работает во второй версии CVAVR.
Я остановился на варианте, предложенным Aheir-ом. Он поделился маленькой программкой, которая перекодирует символы кириллицы.
Вот скриншот:


                Рисунок 2 Скриншот полезной программки.

Вводим слово Радиокот, нажимаем Convert, получаем крякозабры, те что выделены в нижнем окне, копируем их в строчку для отображения, и на дисплее нормально отображается надпись на русском. По-моему это гораздо проще и легче, нежели изобретать велосипед.

А теперь самое интересное:

Работа с функцией sprintf , позволяющей в частности, отображать значения переменных вперемешку с выводом других символов. Все ниже написанное вытекло из изучения содержимого проектов в папке C: cvavr examples. Я объясню основу, то что удалось
накопать так же в просторах сети.

Для начала немного описания функции sprintf:

Функция sprintf( ) (прототип содержится в файле stdio.h) обеспечивает форматированный вывод в строку. Ее можно записать в следующем формальном виде:
sрrintf ("управляющая строка", аргумент _1, аргумент _2,...);
Управляющая строка содержит компоненты трех типов: обычные символы, которые просто копируются в стандартный выходной поток (выводятся на экран дисплея); спецификации преобразования, каждая из которых вызывает вывод на экран очередного аргумента из последующего списка; управляющие символьные константы.
Каждая спецификация преобразования начинается со знака % и заканчивается некоторым символом, задающим преобразование. Между знаком % и символом преобразования могут встречаться другие знаки в соответствии со следующим форматом:
% [признаки] [ширина_поля] [точность] [F |N |h |l |L] c_n
Все параметры в квадратных скобках не являются обязательными.
На месте параметра c_n (символ преобразования) могут быть записаны:

с - значением аргумента является символ;
d или i - значением аргумента является десятичное целое число;
е - значением аргумента является вещественное десятичное число в экспоненциальной форме вида 1.23e+2;
Е - значением аргумента является вещественное десятичное число в экспоненциальной форме вида 1.23E+2;
f - значением аргумента является вещественное десятичное число с плавающей точкой;
g (или G) - используется, как е или f, и исключает вывод незначащих нулей;
о - значением аргумента является восьмеричное целое число;
s - значением аргумента является строка символов (символы строки выводятся до тех пор, пока не встретится символ конца строки или же не будет, выведено число символов, заданное точностью);
u - значением аргумента является беззнаковое целое число;
х - значением аргумента является шестнадцатеричное целое число с цифрами 0,...,
9, а, b, с, d, е, f;
X - значением аргумента является шестнадцатеричное целое число с цифрами 0,...,
9, А, В, С, О, Е, F;
р - значением аргумента является указатель;
n - применяется в операциях форматирования.

Аргумент, соответствующий этому символу спецификации, должен быть указателем на целое. В него возвращается номер позиции строки (отображаемой на экране), в которой записана спецификация %n.

Необязательные параметры в спецификации преобразования:

· признак минус (-) указывает, что преобразованный параметр должен быть выровнен влево в своем поле;
· признак плюс (+) требует вывода результата со знаком;
· строка цифр, задающая минимальный размер поля (ширина поля). Здесь может так же использоваться символ *, который тоже позволяет задать минимальную ширину поля и точность представления выводимого числа;
· точка (.), отделяющая размер поля от последующей строки цифр;
· строка цифр, задающая максимальное число выводимых символов, или же количество цифр, выводимых справа от десятичной точки в значениях типов float или double (точность);
· символ F, определяющий указатель типа far;
· символ N, определяющий указатель типа near;
· символ h, определяющий аргумент типа short int (используется вместе с символами преобразования d, i, о, u, х, Х);
· символ l, указывающий, что соответствующий аргумент имеет тип long (в случае символов преобразования d, i, о, u, х, X) или double (в случае символов преобразования е, Е, f, g, G);
· символ L, указывающий, что соответствующий аргумент имеет тип long double (используется вместе с символами преобразований е, Е, f, g, G);
· символ #, который может встречаться перед символами преобразования g, f, е и перед символом х. В первом случае всегда будет выводиться десятичная точка, а во втором - префикс 0x перед соответствующим шестнадцатеричным числом.
Если после знака % записан не символ преобразования, то он выводится на экран. Таким образом, строка %% приводит к выводу на экран знака %.
Функция sprintf( ) использует управляющую строку, чтобы определить, сколько всего аргументов и каковы их типы. Аргументами могут быть переменные, константы, выражения, вызовы функций; главное, чтобы их значения соответствовали заданной
спецификации.
При наличии ошибок, например, в числе аргументов или типе преобразования, результаты будут неверными.
Среди управляющих символьных констант наиболее часто используются следующие:

а - для кратковременной подачи звукового сигнала;
b - для перевода курсора влево на одну позицию;
f - для подачи формата;
n - для перехода на новую строку;
r - для возврата каретки;
t - горизонтальная табуляция;
v - вертикальная табуляция;
- вывод символа ;
' - вывод символа ' ;
" - вывод символа ";
? - вывод символа ?.

Например, в результате вызова функции:
sprintf(" tComputer n%d n", i);
сначала выполняется горизонтальная табуляция ( t), т.е. курсор сместится от края экрана, затем на экран будет выведено слово Computer, после этого курсор переместится в начало следующей строки ( n), затем будет выведено целое число i по формату %d (десятичное целое), и, окончательно, курсор перейдет в начало новой строки ( n).
Напечатать строку символов можно и так: sprintf("Это строка символов");

Спецификатор формата Тип данных
%d, %i целое десятичное число
%s текстовая строка
%c один символ
%e, %E число с плавающей точкой в экспоненциальной форме
%f число с плавающей точкой в десятичной записи
%u целое десятичное число без знака
%o целое восьмеричное число без знака
%x, %X целое шестнадцатиричное число без знака
%g, %G либо %e, либо %f в зависимости от того, запись в каком формате короче
%p значение указателя
%n число символов

Много – то как всего… На практике проще:

Разберем пример THERMLCD

Я убрал "лишние детали” и получил вот что:

char lcd_buffer[33]; //создается буфер для символов, выводимых на дисплей
char sign; //объявляются переменные
int temp;
temp=245; /* зададим значение переменной, в проекте имеется ввиду что в этой переменной будет храниться значение температуры датчика, в данном случае будет отображаться температура 24,5 градуса
В переменной sign хранится знак + или – */
sprintf(lcd_buffer,"t=%c%i.%u xdfC",sign,temp/10,temp%10);

Как работает данная функция:

надпись lcd_buffer указывает куда будет помещаться результат обработки переменных.
t= так и отобразится на дисплее
%c указывает компилятору что будет выводится один символ, из переменной sign
%i указывает на то, что будет выведено целое десятичное число – результат операции temp/10 (равно просто 24)
Далее следующая точка так и будет выведена на дисплей 
%u -выводит целое десятичное число без знака, это результат операции
temp%10 (равно 5).
xdfC - выводит на дисплей значок цельсия и символ С, если заглянуть в таблицу символов знакогенератора, то значок цельсия имеет код xdf
Затем функция просто вывела символ С.


Надеюсь что этот скромный труд поможет кому-нибудь в освоении LCD.

sprintf(lcd_buffer,"PWM %3u%c%c%u",pwm,'%',y,slag); если первым идет y то slag появляеться только после изменения y(char) с 0(0- это не char) на + или -
sprintf(lcd_buffer,"PWM %u%c%u%c",pwm,'%',slag,y); так slag будет видно сразу на lcd

Code
/*****************************************************
Project : приемы работы с популярными LCD на контролере HD44780. автор : Freerider 
Date : 24.01.2012
Company : c2.at.ua 
Chip type : ATmega8
Program type : Application
Clock frequency : 2,000000 MHz
*****************************************************/
#include <mega8.h>
// Alphanumeric LCD Module functions
#asm
.equ __lcd_port=0x12 ;PORTD
#endasm
#include <lcd.h>
#include <stdio.h>
#include <delay.h>
int x; // 
long int i; 
float b;
int znak[10];
char lcd_buffer[33];
flash char text_mass[] = "Privet";
char text_mass1[] ="Zdarova";
void main(void)
{
PORTB=0x00;
DDRB=0x00;
PORTC=0x00;
DDRC=0x00;
PORTD=0x00;
DDRD=0x00;
ACSR=0x80;
SFIOR=0x00;
lcd_init(16); // LCD module initialization
while(1) // Бесконечный цикл 
{
   while(x<16) // Цикл для растановки символов на LCD в зав-сти от x
 {
lcd_gotoxy(x,0); // Функция позиция дисплея х-столбец 0-ряд
lcd_putchar('$'); // Функция отображения символа (в данном $, можно любой)
lcd_gotoxy(0,1); // Позиция 0-столбец 1 ряд
sprintf(lcd_buffer,"x=%2u",x); //Функция обеспечивает форматированный вывод в строку 
//lcd_buffer указывет куда будет помещен результат после обработки
//При x=%2u на экран вывед.x= . %-начало преобразования 2-ширина поля u-целое десят.число без знака(точность)
lcd_puts(lcd_buffer); //Выводим на экран массив lcd_buffer
delay_ms(100); // Задержка 100 мс
x++;
lcd_clear(); // Функция очистки экрана
}; 

lcd_gotoxy(0,0);
lcd_putsf("Hello"); //Функция отображение строки расположенной во FLASH (памяти программ)
delay_ms(1000);
lcd_clear(); 
lcd_putsf(text_mass); // Тоже самое только массив задан в начале flash char text_mass[] = "Privet";
delay_ms(1000);
lcd_clear(); 

lcd_putsf(" x52 x31"); // Для вывода символа из таблицы знакогенератора (в данном случае вывед.R1)
delay_ms(1000);
lcd_clear(); 
lcd_puts(text_mass1); // Ф-я для вывода массива который вписан в опер.память char text_mass1[] ="Zdarova" 
delay_ms(1000);
lcd_clear(); 

sprintf(znak,"QWERTY"); // Преобразуем QWERTY с записью в массив znak
lcd_gotoxy(0,0);
sprintf(lcd_buffer,"%s",znak); //Выводим %s-текстовую строку массива znak
lcd_puts(lcd_buffer);//
delay_ms(1000);
lcd_clear();


i=' x40'; // Можно любой символ (в данном случае x40 это @ смотри таблицу знакогенератора hd44780)
lcd_gotoxy(0,0);
sprintf(lcd_buffer,"%c",i); //Выводим %c-один символ i если i='QW' то вывод. только W
lcd_puts(lcd_buffer);//
delay_ms(1000);
lcd_clear();

b=0.2; 
lcd_gotoxy(0,0);
sprintf(lcd_buffer,"%f",b); //Выводим %f-число с плавающей точкой в десятичной записи (вывед.0.200000)
lcd_puts(lcd_buffer);//
delay_ms(1000);
lcd_clear(); 

lcd_gotoxy(0,0);
sprintf(lcd_buffer,"%.1f",b); //Выводим %f-число с плавающей точкой в десятичной записи (вывед.0.2) 
//.1 кол-во цифр выводимых справа от десят.точки в значениях типа float(можно поставить и больше) 
lcd_puts(lcd_buffer);//
delay_ms(1000);
lcd_clear(); 

i=130;
lcd_gotoxy(0,0);
sprintf(lcd_buffer,"%x",i); //Выводим %x-целое шестнадцатиричное число без знака (в данном случае вывед.82)
lcd_puts(lcd_buffer);//
delay_ms(1000); 

i=1521; 
lcd_gotoxy(0,0);
sprintf(lcd_buffer," tComp n%d n",i); // t-делаем горизонт.табуляцию выводим слово Comp после перемещаем на начало след.строки( n)
// выводим число i %d и в конце в начало новой строки ( n)
lcd_puts(lcd_buffer);//
delay_ms(1000);
lcd_clear(); 

for(i=0;i<256;i++)

lcd_gotoxy(0,0);
lcd_putchar(i); //Функция отображает символ в текущей позиции (i) знакогенератора 
lcd_gotoxy(0,1);
sprintf(lcd_buffer,"%u",i); //
lcd_puts(lcd_buffer);
delay_ms(100); 
lcd_clear();
}; 

lcd_write_byte(0b01000000,0b11111); //Запись в HD44780 символа рюмка
lcd_write_byte(0b01000001,0b10001);
lcd_write_byte(0b01000010,0b10001);
lcd_write_byte(0b01000011,0b01010);
lcd_write_byte(0b01000100,0b00100);
lcd_write_byte(0b01000101,0b00100);
lcd_write_byte(0b01000110,0b11111);
lcd_write_byte(0b01000111,0b00000); 

lcd_write_byte(0b01001000,0b11111); // запись перевернутая рюмка
lcd_write_byte(0b01001001,0b00100);
lcd_write_byte(0b01001010,0b00100);
lcd_write_byte(0b01001011,0b01010);
lcd_write_byte(0b01001100,0b10001);
lcd_write_byte(0b01001101,0b10001);
lcd_write_byte(0b01001110,0b11111);
lcd_write_byte(0b01001111,0b00000); 

lcd_gotoxy(0,0);
lcd_putchar(0); 
lcd_gotoxy(1,0);
lcd_putchar(1); 
delay_ms(1000);
};
}

Скачать проект и  proteus.

Еще пример, как вывести  на экран ЖКИ,   бегущую текстовую строку состоящей в данном случае из 500 символов . За воплощение этого примера в жизнь, большое спасибо пользователю sonata.


Исходный код.

Code
/*****************************************************
This program was produced by the
CodeWizardAVR V1.25.9 Professional
Automatic Program Generator
© Copyright 1998-2008 Pavel Haiduc, HP InfoTech s.r.l.
.hpinfotech.
Author : test 
Company : test 
Chip type : ATmega8
Clock frequency : 4,000000 MHz
External SRAM size : 0
Data Stack size : 256
*****************************************************/
#include <mega8.h>
// Alphanumeric LCD Module functions
#asm
.equ __lcd_port=0x12 ;PORTD
#endasm
#include  
#include  
unsigned char i; 
int n_sim=1,m_end=500; //m_end - общее количество символов в исходной строке;
char ish_str[] = " аіё¶yжaЗcЗ їeєcїoіaЗ cїpoєa. B гaЅЅoј ѕpёјepe ІeґyжaЗ cїpoєa іГіoгёїДcЗ іo 2-№ cїpoєe ЈKҐ, Еїoї 'єycoє' єoгa ѕo·іo»Зeї іГіoгёїД ІeґyжyЖ cїpoєy (cѕpaіa-Ѕa»eіo), і »ЖІoј јecїe ё c ёcѕo»Д·oіaЅёeј »ЖІoґo єo»ёАecїіa ·Ѕaєoјecї, і ЈKҐ ёЅгёєaїopax c єoЅїpo»»epoј HD44780 ё»ё aЅa»oґёАЅoј. HaАa»o Еїo№ ѕpoґpaјјГ, ЅaxoгёїcЗ ·гecД www.stas633.narod.ru г»ёЅЅa Еїoґo cooІжeЅёЗ 500 cёјіo»oі!!!!!! ec»ё cїpoєa cocїoёї ё· 500 cёјіo»oі, і MK гoѕo»Ѕёїe»ДЅo ·aЅёјaeї 1,4 єё»oІa№ї д»eБa. " ;
//Движущаяся текстовая строка. В данном примере бегущая строка выводиться во 2-й строке ЖКИ. Этот 'кусок' кода позволяет выводить бегущую строку (справа-налево), в любом месте и с использованием любого количества знакомест, в ЖКИ индикаторах с контроллером HD44780 или аналогичном. Начало этой программы, находится здесь www.stas633.narod.ru длинна этого сообщения 500 символов!!!!!! если строка состоит из 500 символов, в МК дополнительно занимает 1,4 килобайт флеша. 
void beg_str(void)
{
for(i=0;i<15;i++)lcd_write_byte(0xC0+i,lcd_read_byte(0xC1+i));
lcd_gotoxy(15,1); // указали место курсору во второй строке
lcd_putchar(ish_str[n_sim]);
if(++n_sim>m_end)
{n_sim=1;};
delay_ms(100);

}
void main(void)
{

PORTB=0x04;
DDRB=0x00;

PORTC=0x00;
DDRC=0x00;

PORTD=0x00;
DDRD=0x00;


ACSR=0x80;
SFIOR=0x00;

// LCD module initialization
lcd_init(16);

while (1)
{
beg_str();
 lcd_gotoxy(0,0); 
lcd_putsf("Tekstova stroka"); 

// Place your code here
};

}

Проект с исходником и  proteus, + вариант №2

Если при симуляции проекта в proteus'е некорректно отображаются символы кириллицы на ЖКИ, то для правильного отображения кириллицы на ЖК индикаторе распаковать библиотеку LCDrus.zip (приложена в архиве проекта) в папку models proteus'а.