| Статистика |
Онлайн всего: 1 Гостей: 1 Пользователей: 0 |
|
| Микроконтроллеры - это просто! |
 |
Рисуем свои символы на LCD (HD44780)
Дисплеи на основе контроллера HD44780 хороши собой и очень удобны в использовании, но имеют один недостаток - ограниченный набор символов. Может возникнуть ситуация, когда нужного для нашего проекта символа в стандартном наборе просто не окажется и что же тогда делать. Выход из этой ситуации есть. Производители контроллеров HD44780 предусмотрели возможность такой ситуации, поэтому в памяти контроллера есть специальные символы по адресам 0х00 - 0х07 - это переопределяеемые символы, графическое изображение которых может назначить сам пользователь. а значит что мы в контроллер можем записать до 8 необходимых нам символов. Разберемся как же это сделать. Ответ я нашел в одном из примеров, который шел вместе с CodeVisionAVR (кстати это не единственный полезны и интересный пример, они располагаются Папка с программой\examples\). И так для записи одного символа в контроллер дисплея нам необходимо сделать следующее:
typedef unsigned char byte; \\ Объявляем новый тип переменной
\\ Определяем непосредственно сам символ (имеет 5 точек в ширину и 7 в высоту) flash byte char0[8]={ 0b10000000, 0b10001111, 0b10000011, 0b10000101, 0b10001001, 0b10010000, 0b10100000, 0b11000000};
Единичками на дисплее будут закрашенные точки, все что оставлено нулями будет пустым. \\ Определяем функцию записи нашего символа в экран void define_char(byte flash *pc,byte char_code) { byte i,a; a=(char_code<<3)|0x40; for (i=0; i<8; i++) lcd_write_byte(a++,*pc++); }
Это была предварительная подготовка. Теперь в основном теле функции main необходимо произвести запись символа в контроллер дисплея, что делаем командой define_char(char0,0); в скобках указываем название символа, которые мы задали выше и его адрес в контроллере, т.е. символ char0 будет доступен по адресу 0х00. Запись символа производится строго только после инициализации дисплея, никак не до ( то есть после lcd_init(16);).
Все основное для записи у нас есть, теперь используем на примере.
Пример 1
В прошлой статье я рассматривал способ создания прогрессбара на стандартном символе 0xFF. Прогрессбар состоял из 16 прямоугольников и заполнялся скажем так несколько грубовато, добавив несколько своих символов в экран мы можем сделать его плавным. Подготовим коды новых символов, так как символ состоит из 5 столбцов то можно нарисовать пять этих столбцов и постепенно закрашивать символ целиком:
flash byte char0[8]={ 0b0010000, 0b0010000, 0b0010000, 0b0010000, 0b0010000, 0b0010000, 0b0010000, 0b0000000};
flash byte char1[8]={ 0b0011000, 0b0011000, 0b0011000, 0b0011000, 0b0011000, 0b0011000, 0b0011000, 0b0000000};
flash byte char2[8]={ 0b0011100, 0b0011100, 0b0011100, 0b0011100, 0b0011100, 0b0011100, 0b0011100, 0b0000000};
flash byte char3[8]={ 0b0011110, 0b0011110, 0b0011110, 0b0011110, 0b0011110, 0b0011110, 0b0011110, 0b0000000};
flash byte char4[8]={ 0b0011111, 0b0011111, 0b0011111, 0b0011111, 0b0011111, 0b0011111, 0b0011111, 0b0000000};
Последний символ есть среди стандартных, но я его решил тоже записать для упрощения кода анимации, потому как символы находящиеся друг за другом перебирать проще чем разбросанные.
Код программы: #include <mega16.h> // Подключаем библиотеку микроконтроллера #asm .equ __lcd_port=0x15 ;PORTC #endasm #include <lcd.h> // Подключаем библиотеку дисплея #include <delay.h> // Подключаем библиотеку реализации задержек #define pause delay_ms(100) // Объявляем переменную pause, которая будет осуществлять задержку char i; // Переменная для счетчика для анимации char j; // Переменная для счетчика для анимации typedef unsigned char byte; // Новый тип переменной для наших символов // Побитное изображение нашего символа для записи в контроллер дисплея flash byte char0[8]={ 0b0010000, 0b0010000, 0b0010000, 0b0010000, 0b0010000, 0b0010000, 0b0010000, 0b0000000};
flash byte char1[8]={ 0b0011000, 0b0011000, 0b0011000, 0b0011000, 0b0011000, 0b0011000, 0b0011000, 0b0000000};
flash byte char2[8]={ 0b0011100, 0b0011100, 0b0011100, 0b0011100, 0b0011100, 0b0011100, 0b0011100, 0b0000000};
flash byte char3[8]={ 0b0011110, 0b0011110, 0b0011110, 0b0011110, 0b0011110, 0b0011110, 0b0011110, 0b0000000};
flash byte char4[8]={ 0b0011111, 0b0011111, 0b0011111, 0b0011111, 0b0011111, 0b0011111, 0b0011111, 0b0000000}; // Функция записи символа в контроллер дисплея void define_char(byte flash *pc,byte char_code) { byte i,a; a=(char_code<<3)|0x40; for (i=0; i<8; i++) lcd_write_byte(a++,*pc++); } // Функция инициализации микроконтроллера void avr_init(void) { PORTA=0x00; DDRA=0x00; PORTB=0x00; DDRB=0x00; PORTC=0x00; DDRC=0x00; PORTD=0x00; DDRD=0x00; TCCR0=0x00; TCNT0=0x00; OCR0=0x00; TCCR1A=0x00; TCCR1B=0x00; TCNT1H=0x00; TCNT1L=0x00; ICR1H=0x00; ICR1L=0x00; OCR1AH=0x00; OCR1AL=0x00; OCR1BH=0x00; OCR1BL=0x00; ASSR=0x00; TCCR2=0x00; TCNT2=0x00; OCR2=0x00; MCUCR=0x00; MCUCSR=0x00; TIMSK=0x00; ACSR=0x80; SFIOR=0x00;
} // Основная программа void main(void) { avr_init(); lcd_init(16); // Инициализация экрана // Запись символов char0 - char4 по адресам 0х00 - 0х04 соответственноdefine_char(char0,0); define_char(char1,1); define_char(char2,2); define_char(char3,3); define_char(char4,4); lcd_clear(); // Очищаем экран while (1) {i=0; // код вывода анимации из новых символов на дисплей lcd_clear(); j=0; while(j<16){ i=0; while(i<5){ lcd_gotoxy(j,0); lcd_putchar(i); i++; pause; }; j++; }; }; }
выполнения будет прогрессбар, плавно заполняющий первую строку дисплея:
Пример 2
Индикатор заряда аккумулятора или батареи.
Каждый из нас регулярно наблюдает такой индикатор на своем мобильном телефоне. Обычно это изображение батарейки, которая по мере разряда аккумулятора пустеет. Допустим ваше устройство использует в своей работе аккумулятор или питается от него и вы хотите себе индикатор заряда как на своем мобильном - легко. сейчас я не буду разбирать как работать с АЦП микроконтроллера и делать измерения, а в продолжение темы просто приведу пример такого индикатора.
Нам понадобятся новые символы:
flash byte char0[8]={ 0b0001110, 0b0010001, 0b0010001, 0b0010001, 0b0010001, 0b0010001, 0b0011111, 0b0000000};
flash byte char0[8]={ 0b0001110, 0b0010001, 0b0010001, 0b0010001, 0b0010001, 0b0011111, 0b0011111, 0b0000000};
flash byte char0[8]={ 0b0001110, 0b0010001, 0b0010001, 0b0010001, 0b0011111, 0b0011111, 0b0011111, 0b0000000}; flash byte char0[8]={ 0b0001110, 0b0010001, 0b0010001, 0b0011111, 0b0011111, 0b0011111, 0b0011111, 0b0000000};
flash byte char0[8]={ 0b0001110, 0b0010001, 0b0010001, 0b0010001, 0b0010001, 0b0010001, 0b0011111, 0b0000000};
flash byte char0[8]={ 0b0001110, 0b0011111, 0b0011111, 0b0011111, 0b0011111, 0b0011111, 0b0011111, 0b0000000};
Ниже приведен код анимации разряда аккумулятора: #include <mega16.h> // Подключаем библиотеку микроконтроллера #asm .equ __lcd_port=0x15 ;PORTC #endasm #include <lcd.h> // Подключаем библиотеку дисплея #include <delay.h> // Подключаем библиотеку реализации задержек #define pause delay_ms(100) // Объявляем переменную pause, которая будет осуществлять задержку char i; // Переменная для счетчика для анимации typedef unsigned char byte; // Новый тип переменной для наших символов // Побитное изображение нашего символа для записи в контроллер дисплея flash byte char0[8]={ 0b0001110, 0b0010001, 0b0010001, 0b0010001, 0b0010001, 0b0010001, 0b0011111, 0b0000000};
flash byte char1[8]={ 0b0001110, 0b0010001, 0b0010001, 0b0010001, 0b0010001, 0b0011111, 0b0011111, 0b0000000};
flash byte char2[8]={ 0b0001110, 0b0010001, 0b0010001, 0b0010001, 0b0011111, 0b0011111, 0b0011111, 0b0000000};
flash byte char3[8]={ 0b0001110, 0b0010001, 0b0010001, 0b0011111, 0b0011111, 0b0011111, 0b0011111, 0b0000000};
flash byte char4[8]={ 0b0001110, 0b0010001, 0b0011111, 0b0011111, 0b0011111, 0b0011111, 0b0011111, 0b0000000};
flash byte char5[8]={ 0b0001110, 0b0011111, 0b0011111, 0b0011111, 0b0011111, 0b0011111, 0b0011111, 0b0000000}; // Функция записи символа в контроллер дисплея void define_char(byte flash *pc,byte char_code) { byte i,a; a=(char_code<<3)|0x40; for (i=0; i<8; i++) lcd_write_byte(a++,*pc++); } // Функция инициализации микроконтроллера void avr_init(void) { PORTA=0x00; DDRA=0x00; PORTB=0x00; DDRB=0x00; PORTC=0x00; DDRC=0x00; PORTD=0x00; DDRD=0x00; TCCR0=0x00; TCNT0=0x00; OCR0=0x00; TCCR1A=0x00; TCCR1B=0x00; TCNT1H=0x00; TCNT1L=0x00; ICR1H=0x00; ICR1L=0x00; OCR1AH=0x00; OCR1AL=0x00; OCR1BH=0x00; OCR1BL=0x00; ASSR=0x00; TCCR2=0x00; TCNT2=0x00; OCR2=0x00; MCUCR=0x00; MCUCSR=0x00; TIMSK=0x00; ACSR=0x80; SFIOR=0x00;
} // Основная программа void main(void) { avr_init(); lcd_init(16); // Инициализация экрана // Запись символов char0 - char4 по адресам 0х00 - 0х04 соответственноdefine_char(char0,0); define_char(char1,1); define_char(char2,2); define_char(char3,3); define_char(char4,4); define_char(char5,5); lcd_clear(); // Очищаем экран while (1) { // код вывода анимации из новых символов на дисплей i=5; while(i>0){ lcd_gotoxy(0,1); lcd_putchar(i); pause; i--; }; }; }
Результат выполнения:
Все изложенное выше это не прямая инструкция к применению, а просто идеи и попытки изучения стандартных возможностей экрана. Это лишь несколько примеров, но рассмотренны все основные принципы, а вариантов использованиия может быть очень много.
|
| Категория: Изучаем AVR | Добавил: Alex (09.02.2014)
|
| Просмотров: 5654
| Рейтинг: 5.0/1 |
Добавлять комментарии могут только зарегистрированные пользователи. [ Регистрация | Вход ]
|
|