Страница 1 из 1

Часы на AVR

Добавлено: Пт мар 29, 2013 17:17:46
Nubik
Здравствуйте.
Понадобилось мне сделать часы.
Знаю,что тема заезженная и много примеров, но они все сделаны с использованием микросхем реального времени, но это не рационально, если на микроконтроллере есть асинхронный таймер, на который можно подцепить кварц.
Написал я код:

Код: Выделить всё

 /*
 * 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

Re: Часы на AVR

Добавлено: Пт мар 29, 2013 19:44:40
uk8amk
Nubik писал(а):На выходе не мигает, горят только восьмерки.
Начните с простого - вывести на дисплей "1234". Когда оно заработает, будете двигаться дальше.
Nubik писал(а): 
ASSR |=(1<<AS2);  //в асинхронный режим   
TCCR2 |=(1<<CS22);    //64 от кварца на 8Мгц
TIM2 в ассинхронном режиме умеет только от 32768Гц часового кварца.

Re: Часы на AVR

Добавлено: Пт мар 29, 2013 22:38:47
Nubik
uk8amk писал(а): Начните с простого - вывести на дисплей "1234". Когда оно заработает, будете двигаться дальше.
Попробую завтра.
uk8amk писал(а):
Nubik писал(а): 
ASSR |=(1<<AS2);  //в асинхронный режим   
TCCR2 |=(1<<CS22);    //64 от кварца на 8Мгц
TIM2 в ассинхронном режиме умеет только от 32768Гц часового кварца.
Он тактируется от часового кварца,забыл сказать=( , это я подписал, чтоб не забыть, что тактирую МК от 8 МГц.
Но здесь я спалил ошбочку предделитель неправильно указал=) Стоит на 64, надо 128)
Спасибо, так бы не заметил :)

Кстати, думаю лишним не будет, фьзы выставляю так: Low: 0xFE, High: 0x99. и делаю на мега 16а.