Часы на AVR
Добавлено: Пт мар 29, 2013 17:17:46
Здравствуйте.
Понадобилось мне сделать часы.
Знаю,что тема заезженная и много примеров, но они все сделаны с использованием микросхем реального времени, но это не рационально, если на микроконтроллере есть асинхронный таймер, на который можно подцепить кварц.
Написал я код:
Собрал все на макетке, ну, думаю, заработает. Ан нет.
На выходе не мигает, горят только восьмерки.
Надеюсь знающие люди подскажут неисправности в коде, буду преблагодарен.
З.Ы. немного недоделан код - планирую сделать. чтоб настройки управлялись через комп.
З.З.Ы. Исправил значение предделителя у асинхронного таймера с 64 на 128
Понадобилось мне сделать часы.
Знаю,что тема заезженная и много примеров, но они все сделаны с использованием микросхем реального времени, но это не рационально, если на микроконтроллере есть асинхронный таймер, на который можно подцепить кварц.
Написал я код:
Код: Выделить всё
/*
* AVRGCC4.c
*
* Created: 09.01.2013 0:29:56
* Author: Администратор
*/
#include <avr/io.h>
#include <avr/interrupt.h>
unsigned char count_min, count_hour, count_day, count_mounth, sek, count_ind;
unsigned char dig[]={0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F, 0x6F}; //{0b00111111, 0b00000110, 0b01011011, 0b01001111, 0b01100110, 0b01101101, 0b01111101, 0b00000111, 0b01111111, 0b01101111};
unsigned char db_des, db_ed, daymonth;
unsigned char segment[8]= {0b10000000, 0b01000000, 0b00100000,0b00010000,
0b00001000, 0b00000100, 0b00000010, 0b00000001};
unsigned char year,m;
/************ Проверка на года високосность ************/
void years(void)
{
unsigned char ye;
ye=year/4;
m=year-ye*4;
}
/************ Количество дней в месяце ************/
int month_1 (unsigned char k)
{
switch(k)
{
case 2:
if (m == 0) {daymonth = 29;}
else {daymonth = 28;}
break;
case 4: daymonth = 30; break;
case 6: daymonth = 30; break;
case 9: daymonth = 30; break;
case 11:daymonth = 30; break;
default:daymonth = 31; break; //1,3,5,7,8,10,12
}
}
/************ Разделение числа на единицы и десятки. Единицы ************/
unsigned char dec_bin_ed (ed_db)
{
db_ed= ed_db%10;
}
/************ Разделение числа на единицы и десятки. Десятки ************/
unsigned char dec_bin_des (des_db)
{
db_des= des_db/10;
}
/************ Вывод инфы на дисплей ************/
unsigned char display (unsigned char data)
{
switch (data)
{
case 1: { PORTA = segment[0]; dec_bin_ed (count_min); PORTB = dig[db_ed];}; break;
case 2: { PORTA = segment[1]; dec_bin_des (count_min); PORTB = dig[db_des];}; break;
case 3: { PORTA = segment[2]; dec_bin_ed (count_hour); PORTB = dig[db_ed];}; break;
case 4: { PORTA = segment[3]; dec_bin_des (count_hour); PORTB = dig[db_des];}; break;
case 5: { PORTA = segment[4]; dec_bin_ed (count_day); PORTB = dig[db_ed];}; break;
case 6: { PORTA = segment[5]; dec_bin_des (count_day); PORTB = dig[db_des];}; break;
case 7: { PORTA = segment[6]; dec_bin_ed (count_mounth); PORTB = dig[db_ed];}; break;
case 8: { PORTA = segment[7]; dec_bin_des (count_mounth);PORTB = dig[db_des];}; break;
}
}
/************ Выбор индикатора ************/
ISR (TIMER0_OVF_vect)
{
count_ind++;
if (count_ind>8)
{count_ind = 1;
display(count_ind);}
else
display(count_ind);
}
/************ Счет времени ************/
ISR (TIMER2_OVF_vect)
{
sek++;
if (sek > 59) {count_min++; sek = 0;}
if (count_min > 59) {count_hour++ ; count_min = 0;}
if (count_hour>23) {count_day++; count_hour = 0;}
if (count_day > daymonth){count_day = 1; count_mounth++; month_1(count_mounth); count_day = 1;}
if (count_mounth > 12){count_mounth = 1; year++; years();}
}
/************ Начальные данные ************/
void begin(void)
{
year = 2013;
years();
count_mounth=3;
month_1(count_mounth);
count_day=28;
count_hour = 23;
count_min = 55;
}
int main(void)
{
DDRA=0xFF;
PORTA=0x00;
DDRB=0xFF;
PORTB=0xFF;
PORTC=0xFF;
DDRC=0x00;
PORTD=0x00;
DDRD=0x00;
TCCR0 |=((1<<COM01)|(1<<WGM01)| (1<<CS01)); //(1<<CS02)|(1<<CS00)); //101101
TCNT0=0x00;
OCR0=0x08;
/************ настройка часового таймера ************/
ASSR |=(1<<AS2); //в асинхронный режим
TCCR2 |=(1<<CS22)| (1<<CS20); //128
TCNT2=0x00;
OCR2=0x00;
while (ASSR & ((1 << TCN2UB) | (1 << OCR2UB) | (1 << TCR2UB)));
TIMSK |=(1<<TOIE2);
SFIOR=0x00;
SREG |= (1<<7); //Разрешение глобальных прерываний
begin();
while(1)
{
//TODO:: Please write your application code
}
} На выходе не мигает, горят только восьмерки.
Надеюсь знающие люди подскажут неисправности в коде, буду преблагодарен.
З.Ы. немного недоделан код - планирую сделать. чтоб настройки управлялись через комп.
З.З.Ы. Исправил значение предделителя у асинхронного таймера с 64 на 128