В радиолюбительской литературе и на сайтах подобной тематики схемы часов на микроконтроллере встречаются очень часто. Наверно это связано как с тем, что часы достаточно необходимый прибор в доме каждого человека, так и с тем что написание программы для микроконтроллера не есть сложной задачей. Анализируя схемы часов на микроконтроллерах семейства AVR фирмы Atmel , видим, что большинство из них имеет в наличии часовой датчик — микросхему DS1307. Да, использование датчика значительно упрощает задачу по реализации часов на микроконтроллере. Для того чтобы сделать это поле технологической деятельности радиолюбителей и программистов более разнообразным, я предлагаю для рассмотрения схему часов на микроконтроллере ATMega8 без использования часовой микросхемы DS1307.
Принципиальная схема часов на микроконтроллере ATMega8:
Код программы микроконтроллера:
#include <avr/io.h> #include <avr/interrupt.h> #include <avr/wdt.h> #include <stdio.h> #define _s_A 2 #define _s_B 0 #define _s_C 6 #define _s_D 4 #define _s_E 3 #define _s_F 1 #define _s_G 7 #define _s_dot 5 const unsigned char segs[] = { _BV(_s_A) | _BV(_s_B) | _BV(_s_C) | _BV(_s_D) | _BV(_s_E) | _BV(_s_F), //0 _BV(_s_B) | _BV(_s_C), //1 _BV(_s_A) | _BV(_s_B) | _BV(_s_D) | _BV(_s_E) | _BV(_s_G), //2 _BV(_s_A) | _BV(_s_B) | _BV(_s_C) | _BV(_s_D) | _BV(_s_G), //3 _BV(_s_B) | _BV(_s_C) | _BV(_s_F) | _BV(_s_G), //4 _BV(_s_A) | _BV(_s_C) | _BV(_s_D) | _BV(_s_F) | _BV(_s_G), //5 _BV(_s_A) | _BV(_s_C) | _BV(_s_D) | _BV(_s_E) | _BV(_s_F) | _BV(_s_G), //6 _BV(_s_A) | _BV(_s_B) | _BV(_s_C), //7 _BV(_s_A) | _BV(_s_B) | _BV(_s_C) | _BV(_s_D) | _BV(_s_E) | _BV(_s_F) | _BV(_s_G),//8 _BV(_s_A) | _BV(_s_B) | _BV(_s_C) | _BV(_s_F) | _BV(_s_G),//9 _BV(_s_A) | _BV(_s_B) | _BV(_s_C) | _BV(_s_E) | _BV(_s_F) | _BV(_s_G), //A _BV(_s_C) | _BV(_s_D) | _BV(_s_E) | _BV(_s_F) | _BV(_s_G), //B _BV(_s_A) | _BV(_s_D) | _BV(_s_E) | _BV(_s_F), //C _BV(_s_B) | _BV(_s_C) | _BV(_s_D) | _BV(_s_E) | _BV(_s_G), //D _BV(_s_A) | _BV(_s_D) | _BV(_s_E) | _BV(_s_F) | _BV(_s_G), //E _BV(_s_A) | _BV(_s_E) | _BV(_s_F) | _BV(_s_G) //F }; #define _ms(n) (17*n) void wait(unsigned int a) //basic wait { volatile unsigned int b,c; for(b=0;b!= a; b++)for(c=0;c!= 50;c++); return; } volatile unsigned char prescale=0; volatile unsigned char sec=0; volatile unsigned char min_1=0; volatile unsigned char min_10=0; volatile unsigned char hour_1=0; volatile unsigned char hour_10=0; volatile unsigned char show_t=0; ISR(TIMER1_OVF_vect) { if(++prescale == 225){prescale = 0;sec++;}; if(sec>59){min_1++;sec=0;}; if(min_1>9){min_1=0;min_10++;}; if(min_10>5){min_10=0;hour_1++;}; if(hour_1>9){hour_1=0;hour_10++;}; if(hour_10>1 && hour_1>3){hour_1=0;hour_10=0;}; if(++show_t==4) show_t=0; switch(show_t) { case 0: //show minutes PORTC = 0x04; PORTD = (~segs[min_1]); break; case 1: //show 10 minutes PORTC = 0x08; PORTD = (~segs[min_10]); break; case 2: //show hours PORTC = 0x10; PORTD = (~segs[hour_1]) & ~_BV(_s_dot); break; case 3: //show 10hours PORTC = 0x20; PORTD = (~segs[hour_10]); break; default: show_t = 0; break; } return; } #define B1() (bit_is_clear(PINB,3)) #define B2() (bit_is_clear(PINB,4)) #define B_WAIT 300 #define nop() asm volatile ("nop;") int main(void) { TIMSK = 0x04; TCCR1B = 0x01; DDRD = 0xFF; DDRC = 0x3F; DDRB = 0x00; PORTB = 0xFF; sei(); while(1) { if(B1()) { wait(_ms(B_WAIT)); min_1++; sec=0; } if(B2()) { wait(_ms(B_WAIT)); hour_1++; sec=0; } } } |
Фото часов на микроконтроллере ATMega8:
[hidepost] Скачать [/hidepost]