#include <avr/io.h>
#define F_CPU 10000000UL
#include <util/delay.h>
/* Установка лог. "1" на линии E */
#define LCD_E_SET PORTA |= 0b01000000
/* Установка лог. "0" на линии E */
#define LCD_E_CLR PORTA &= 0b10111111
/* Установка лог. "1" на линии RS */
#define LCD_RS_SET PORTA |= 0b00010000
/* Установка лог. "0" на линии RS */
#define LCD_RS_CLR PORTA &= 0b11101111
/* Установка лог. "1" на линии RW */
#define LCD_RW_SET PORTA |= 0b00100000
/* Установка лог. "0" на линии RW */
#define LCD_RW_CLR PORTA &= 0b11011111
/* Макрос, указывающий функции, что
передаются команды */
#define LCD_COMMAND 0
/* Макрос, указывающий функции, что
передаются данные */
#define LCD_DATA 1
/* Макрос, указывающий функции, что
производится запуск LCD, при котором не требуется
проверка флага занятости */
#define LCD_STRT 0
/* Макрос, указывающий функции, что
LCD находится в рабочем режиме */
#define LCD_WRK 1
//putcc - помещает байт в регистр комманд
#define putcc(x) lcd_put_byte(x, LCD_COMMAND, LCD_WRK)
//putcd - помещает байт в регистр данных
#define putcd(s) lcd_put_byte(s, LCD_DATA, LCD_WRK)
void init_port_a_out() {
DDRA = 0b01110000;
PORTA = 0x00;
}
//Функция установки 7, 6, 5, 4 ножек порта С на вывод информации
|
|
void init_port_c_out() {
DDRC |= 0xF0;
PORTC = 0x00;
}
/*Функция установки порта С на считывание информации с установкой подтягивающих резисторов
на 7, 6, 5, 4 ножках*/
void init_port_c_in() {
DDRC &= 0x00;
PORTC = 0xF0;
}
//Функция считывания флага занятости
unsigned char lcd_check() {
//unsigned char data - переменная, для хранения старшей тетрады регистра комманд
unsigned char data;
init_port_c_in();
LCD_RW_SET;
LCD_RS_CLR;
LCD_E_SET;
_delay_us(50);
//Считывание 7-го бита старшей тетрады из регистра комманд
data = PINC & 0x80;
LCD_E_CLR;
//Вывод младшей тетрады
LCD_E_SET;
_delay_us(50);
LCD_E_CLR;
LCD_RW_CLR;
//Если data!= 0, функция возвращает 1(контроллер жки занят). Если 0, то свободен.
if (data!= 0)
return 1;
else
return 0;
}
/* Функция перемещения курсора в заданную позицию
char col - номер знакоместа по горизонтальной оси
char row - номер строки (0 или 1) */
void lcd_gotoxy(char col, char row) {
//char adr - адрес ячейки жки
char adr;
//расчет адреса ячейки жки
adr = 0x40 * row + col;
adr |= 0x80;
//передача адреса ячейки жки в регистр команд с проверкой флага занятости
lcd_put_byte(adr, LCD_COMMAND, LCD_WRK);
}
/* функция передачи тетрады в контроллер жки
char tetr - тетрада */
void lcd_put_tetr(char tetr) {
tetr &= 0x0F;
tetr <<= 4;
LCD_E_SET;
_delay_us(50);
PORTC &= 0x0F;
PORTC |= tetr;
LCD_E_CLR;
}
/* Функция передачи байта в контроллер жки
char b - байт
char rs - переменная, указывающая что передается:
rs = 0 - команда (устанавливается линия RS)
rs = 1 - данные (сбрасывается линия RS)
char st - переменная, указывающая режим работы LCD:
st = 0 - стартовый, без проверки флага занятости контроллера жки
st = 1 - рабочий, с проверкой флага занятости*/
void lcd_put_byte(char b, char rs, char st) {
//char hb - старшая тетрада байта
//При условии, что дисплей в рабочем режиме
if (st == LCD_WRK)
//Проверка флага занятости
while(lcd_check());
init_port_c_out();
|
|
char hb = 0;
hb = b >> 4;
//Условие выбора регистра
if(rs == LCD_COMMAND)
LCD_RS_CLR;
else
LCD_RS_SET;
lcd_put_tetr(hb);
lcd_put_tetr(b);
}
/*Функция передачи строки в контроллер жки
char *str - указатель на первый элемент строки.*/
void lcd_put_str(char *str) {
//char a, b - переменные для счетчика адреса
char d = *str, a = 0x00, b = 0x00;
do {
d = *(str++);
lcd_gotoxy(a, b);
lcd_put_byte(d, LCD_DATA, LCD_WRK);
//Счетчик адреса
a++;
if (a > 0x10) {
b++;
a = 0x00;
}
} while(d!= 0x00);
}
/*Функция инициализации дисплея в 4-х битном двухстрочном режиме
работы. Размер матрицы символов 5х8 точек. Курсор не отображается.*/
void lcd_init() {
//Рекомендованный порядок установки жки
_delay_ms(15);
lcd_put_byte(0x33, LCD_COMMAND, LCD_STRT);
_delay_ms(4);
lcd_put_byte(0x32, LCD_COMMAND, LCD_STRT);
_delay_ms(5);
//4 бит, 2 строки, матрица 5х8
lcd_put_byte(0x28, LCD_COMMAND, LCD_STRT);
_delay_ms(5);
lcd_put_byte(0x28, LCD_COMMAND, LCD_STRT);
_delay_ms(5);
//Дисплей вкл, курсор откл, мигание откл
lcd_put_byte(0b00001100, LCD_COMMAND, LCD_WRK);
//Направление сдвига курсора слева направо
lcd_put_byte(0x06, LCD_COMMAND, LCD_WRK);
}
//Функция сдвига экрана слева направо и справа налево
void lcd_repeat() {
while(1) {
_delay_ms(250);
putcc(0b00011000);
_delay_ms(250);
putcc(0b00011100);
}
}
//Функция очистки экрана
void lcd_clear() {
lcd_put_byte(0x01, LCD_COMMAND, LCD_WRK);
}