Небольшая демо-программа, таймер для ATmega8 с дисплеем HD44780. В качестве отправной точки использовал исходник из предыдущего поста. Идея была почерпнута здесь: LCD "Bigfont" Numbers over 2 or 4 lines".
Исходник:
/* for ATmega8/168/328 display HD44780 support site: http://countzero.weebly.com avr-gcc -mmcu=atmega8 -Wall -Os -o lcd.elf lcd.c avr-objcopy -O ihex lcd.elf lcd.hex*/ #define F_CPU 16000000UL #include <avr/io.h> #include <util/delay.h> #define LCD_RS 2 #define LCD_E 3 #define LCD_D4 4 #define LCD_D5 5 #define LCD_D6 6 #define LCD_D7 7 #define LCD_PORT DDRD #define LCD PORTD #define CMD 0 // command #define DTA 1 // data #define LCD_CLEAR 0x01 #define LCD_OFF 0x08 #define LCD_ON 0x0C /10/#define LCD_ON 0x0F #define LCD_RETURN 0x02 uint8_t one[8]= { 0b11111, 0b11111, 0b11111, 0b00000, 0b00000, 0b00000, 0b00000, 0b00000, }; uint8_t two[8]= { 0b00000, 0b00000, 0b00000, 0b00000, 0b00000, 0b11111, 0b11111, 0b11111, }; uint8_t three[8]= { 0b11111, 0b11111, 0b11111, 0b00000, 0b00000, 0b00000, 0b11111, 0b11111, }; uint8_t four[8]= { 0b11111, 0b11111, 0b11111, 0b11111, 0b11111, 0b11111, 0b11111, 0b11111, }; uint8_t zero[8]={ 0b00000, 0b00000, 0b00000, 0b00000, 0b01110, 0b01110, 0b01110, 0b00000, }; // for 4bit mode static int send_lcd(uint8_t value, uint8_t mode) { LCD&=0x03; // clear LCD|=(value&0xF0)|(mode<<LCD_RS)|(1<<LCD_E); LCD&=0x03; LCD|=(value<<4)|(mode<<LCD_RS)|(1<<LCD_E); LCD&=~(1<<LCD_E); if (value == LCD_CLEAR || value == LCD_RETURN) _delay_ms(2); else _delay_us(50); return 0; } static int print_lcd(char* str) { uint8_t i; i=0; while(str[i] !=0 && i<255) { send_lcd(str[i],DTA); i++; }; return i; }; static void write_custom_char(uint8_t ch) { uint8_t i; if (ch == 1) for (i=0; i <8; i++) send_lcd(one[i],DTA); else if (ch == 2) for (i=0; i <8; i++) send_lcd(two[i],DTA); else if (ch == 3) for (i=0; i <8; i++) send_lcd(three[i],DTA); else if (ch == 4) for (i=0; i <8; i++) send_lcd(four[i],DTA); else if (ch == 0) for (i=0; i <8; i++) send_lcd(zero[i],DTA); } static void print_big_dg(uint8_t pos,uint8_t digit) { send_lcd(0x80|pos, CMD); //first line switch (digit) { case 0: print_lcd("\4\1\4");break; case 1: print_lcd("\1\4 "); break; case 2: case 3: print_lcd("\3\3\4");break; case 4: print_lcd("\4\2\4");break; case 5: case 6: print_lcd("\4\3\3");break; case 7: print_lcd("\1\1\4");break; case 8: case 9: print_lcd("\4\3\4"); } send_lcd(0xC0|pos,CMD); //second line switch (digit) { case 0: case 8: case 6: print_lcd("\4\2\4"); break; case 1: print_lcd("\2\4\2"); break; case 2: print_lcd("\4\2\2");break; case 3: case 5: case 9: print_lcd("\2\2\4"); break; case 4: print_lcd(" \4"); break; case 7: print_lcd(" \4 "); } } static int init_lcd() { LCD_PORT=0xFC; // pin 2,3,4,5,6,7 in OUTPUT mode _delay_ms(50); // 4bit mode LCD&=0b11; // clear LCD |=(1<<LCD_D5)|(1<<LCD_E); LCD&=0b11; // clear LCD |=(1<<LCD_D5); _delay_ms(5); send_lcd(0x28,CMD); // mode: 4bit, 2 lines send_lcd(LCD_OFF,CMD); send_lcd(LCD_CLEAR,CMD); send_lcd(0x06,CMD); // seek mode: right send_lcd(LCD_ON,CMD); return 0; } int main(void) { init_lcd(); send_lcd(0x40,CMD); write_custom_char(0); write_custom_char(1); write_custom_char(2); write_custom_char(3); write_custom_char(4); send_lcd(0x80,CMD); uint8_t min; min=0; uint8_t sec; sec=0; for(;;) { print_big_dg(0, min/10); print_big_dg(4, min%10); print_big_dg(9, sec/10); print_big_dg(13, sec%10); if (sec%2) { send_lcd(0x87,CMD); send_lcd(0,DTA); send_lcd(0xC7,CMD); send_lcd(0,DTA); } else { send_lcd(0x87,CMD); send_lcd(0x20,DTA); send_lcd(0xC7,CMD); send_lcd(0x20,DTA); } if (sec >= 60) { sec=0; min++;} else sec++; if (min >= 99) min=0; _delay_ms(950); }; return 0; }
Прошивка весит около 860 байт.
Результат: