«

»

Распечатать Запись

Простые часы на микроконтроллере ATMega8

В радиолюбительской литературе и на сайтах подобной тематики схемы часов на микроконтроллере встречаются очень часто. Наверно это связано как с тем, что часы достаточно необходимый прибор в доме каждого человека, так и с тем что написание программы для микроконтроллера не есть сложной задачей. Анализируя схемы часов на микроконтроллерах семейства AVR фирмы Atmel , видим, что большинство из них имеет в наличии часовой датчик - микросхему DS1307.  Да, использование датчика значительно упрощает задачу по реализации часов на микроконтроллере. Для того чтобы сделать это поле технологической деятельности радиолюбителей и программистов более разнообразным,  я предлагаю для рассмотрения схему часов на микроконтроллере ATMega8 без использования часовой микросхемы DS1307.

Принципиальная схема часов на микроконтроллере ATMega8:

1Конечно, еще более упростить схему можно было бы применив ЖК дисплей, но мне более интересны LED дисплеи. Хотя бы с той точки зрения, что табло часов должно быть видно в темное время.

Код программы микроконтроллера:

 #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:
OLYMPUS DIGITAL CAMERAАрхив к проекту:
Чтобы скачать файл войдите или зарегистрируйтесь

Постоянная ссылка на это сообщение: http://meandr.org/archives/20266

6 комментариев

Перейти полю для комментария

  1. MuKoJIa

    какие фьюзы нужно прошить?

  2. prikol98

    Какой тип индикатора-ОА или ОК?

    1. Semistor

      Индикатор с общим анодом

  3. dorsh1234

    Где в программе и в схеме происходят изменения значения на индикаторе?

  4. wazzzilin

    можно рисунок платы, и фьюзы?

  5. vanderverken

    что бы замигала точка, нужно изменить вот это

    case 2: //show hours
    PORTC = 0x10;
    PORTD = (~segs[hour_1]);
    if (sec % 2 == 0 ){PORTD = _BV(_s_dot);} //dot is OFF
    if (sec % 2 == 1) {PORTD = ~_BV(_s_dot);} //dot is ON
    break;

Добавить комментарий