Точность хода часов на Atmega8
Добавлено: Пт фев 24, 2012 20:21:51
Доброго времени суток,товарищи! У меня к вам вопросик возник. Вторую неделю мучаюсь с часами, то спешат, то отстают. Так вот. Во-первых. Используется внутренний генератор на 8МГц. Недавно прочитал, что он нестабильно ведёт себя при изменении питания/температуры. Даст ли положительный результат использование внешнего кварца? Во-вторых. Какую лучше сделать программную корректировку? Кварц тоже не идеален( С использованием задержки или через определённый интервал времени добавлять секунды? Если отстают. И как "красивее" это сделать? Вот исходник:
#include <mega8.h>
#include <delay.h> // подключаем библиотеку задержки
unsigned char sek; // переменная сек.
unsigned char min; // пересенная мин.
unsigned char hour; // переменная часов
unsigned char Dig[10];
char Disp6, Disp7;
// Timer 1 output compare A interrupt service routine
interrupt [TIM1_COMPA] void timer1_compa_isr(void) // таймер выставлен на частоту 1 Гц
{
// Place your code here
TCNT1H=0;
TCNT1L=0;
sek++; // инкрементируем секунду
PORTD=128;
PORTB=253; // выводим точку
// роботаем с кнопками
if (PINC.0==0) // если нажата первая кнопка
{
hour++; // к значению часы добавляем единицу
}
if (PINC.1==0) // если нажата вторая кнопка
{
hour--; // к значению часы вычитаем единицу у
}
if (PINC.2==0) // если нажата третья кнопка
{
min++; // к значению минуты добавляем единицу
}
if (PINC.3==0) // если нажата четвертая кнопка
{
min--; // к значению минуты вычитаем единицу
}
if (PINC.4==0) // кнопка RESET
{
sek=0;
}
}
// Declare your global variables here
void Display (unsigned int Number) //Ф-ция для разложения десятичного цисла
{
unsigned char Num2, Num3;
Num2=0;
while (Number >= 10) //десятичную
{
Number -= 10;
Num2++;
}
Num3 = Number; //остаток
Disp6 = Dig[Num2];
Disp7 = Dig[Num3];
}
void Dig_init() //Массив для отображения цыфр на семисегментном индикаторе
{
Dig[0] = 95; // Сейчас у нас схема с общим катодом
Dig[1] = 24;
Dig[2] = 109;
Dig[3] = 124;
Dig[4] = 58;
Dig[5] = 118;
Dig[6] = 119;
Dig[7] = 28;
Dig[8] = 127;
Dig[9] = 126;
}
void main(void)
{
// Declare your local variables here
// Input/Output Ports initialization
// Port B initialization
// Func7=Out Func6=Out Func5=Out Func4=Out Func3=Out Func2=Out Func1=Out Func0=Out
// State7=0 State6=0 State5=0 State4=0 State3=0 State2=0 State1=0 State0=0
PORTB=0x00;
DDRB=0xFF;
// Port C initialization
// Func6=In Func5=In Func4=In Func3=In Func2=In Func1=In Func0=In
// State6=T State5=T State4=T State3=T State2=T State1=T State0=T
PORTC=0xFF;
DDRC=0x00;
// Port D initialization
// Func7=In Func6=In Func5=In Func4=In Func3=In Func2=In Func1=In Func0=In
// State7=T State6=T State5=T State4=T State3=T State2=T State1=T State0=T
PORTD=0x00;
DDRD=0xFF;
// Timer/Counter 0 initialization
// Clock source: System Clock
// Clock value: Timer 0 Stopped
TCCR0=0x00;
TCNT0=0x00;
// Timer/Counter 1 initialization
// Clock source: System Clock
// Clock value: 7,813 kHz
// Mode: Normal top=FFFFh
// OC1A output: Discon.
// OC1B output: Discon.
// Noise Canceler: Off
// Input Capture on Falling Edge
// Timer 1 Overflow Interrupt: Off
// Input Capture Interrupt: Off
// Compare A Match Interrupt: On
// Compare B Match Interrupt: Off
TCCR1A=0x00;
TCCR1B=0x05;
TCNT1H=0x00;
TCNT1L=0x00;
ICR1H=0x00;
ICR1L=0x00;
OCR1AH=0x1E;
OCR1AL=0x85;
OCR1BH=0x00;
OCR1BL=0x00;
// Timer/Counter 2 initialization
// Clock source: System Clock
// Clock value: Timer 2 Stopped
// Mode: Normal top=FFh
// OC2 output: Disconnected
ASSR=0x00;
TCCR2=0x00;
TCNT2=0x00;
OCR2=0x00;
// External Interrupt(s) initialization
// INT0: Off
// INT1: Off
MCUCR=0x00;
// Timer(s)/Counter(s) Interrupt(s) initialization
TIMSK=0x10;
// Analog Comparator initialization
// Analog Comparator: Off
// Analog Comparator Input Capture by Timer/Counter 1: Off
ACSR=0x80;
SFIOR=0x00;
// LCD module initialization
// Global enable interrupts
#asm("sei")
Dig_init(); //инициализация массива с двоичным кодом
while (1)
{///// Условия часов.
if(sek==60) // если сек = 60
{
min++; // добавляем 1 к переменной "минута"
sek=0; // зануляем переменную "секунда"
}
if(min==60) // если мин = 60
{
hour++; // добавляем 1 к переменной "час"
min=0; // зануляем переменную "минута"
sek=0;
}
if (hour==24) // так как у нас часы имеют 24 часовый формат
{ // при достыжении 24 часов, онулируем все переменные.
hour=0;
min=0;
sek=0;
}
// защита переполнения переменной, она нужна для того чтобы в моментах когда время не переходило в минус.
if (hour==255)
hour=0;
if (min==255)
min=0;
// выводим переменные (стробирование)
Display(hour); //разложили "часы" на 2 цифры и отобразили по очереди
PORTB=254; //даем лог 0 для катода 1 разряда
PORTD=Disp6; //1 цифра
delay_ms(1);
PORTB=253; //даем лог 0 для катода 2 разряда
PORTD=Disp7; //2 цифра
delay_ms(1);
Display(min); //разложили "минуты" на 2 цифры и отобразили по очереди
PORTB=251; //даем лог 0 для катода 3 разряда
PORTD=Disp6; //3 цифра
delay_ms(1);
PORTB=247; //даем лог 0 для катода 4 разряда
PORTD=Disp7; //4...
delay_ms(1);
};
}
Где взял, извините не помню(
А было бы совсем приятно, если бы кто-нибудь поделился хорошо работающей схемой) Только желательно без DS13.. Мне нужны просто часы, без всяких наворотов)
#include <mega8.h>
#include <delay.h> // подключаем библиотеку задержки
unsigned char sek; // переменная сек.
unsigned char min; // пересенная мин.
unsigned char hour; // переменная часов
unsigned char Dig[10];
char Disp6, Disp7;
// Timer 1 output compare A interrupt service routine
interrupt [TIM1_COMPA] void timer1_compa_isr(void) // таймер выставлен на частоту 1 Гц
{
// Place your code here
TCNT1H=0;
TCNT1L=0;
sek++; // инкрементируем секунду
PORTD=128;
PORTB=253; // выводим точку
// роботаем с кнопками
if (PINC.0==0) // если нажата первая кнопка
{
hour++; // к значению часы добавляем единицу
}
if (PINC.1==0) // если нажата вторая кнопка
{
hour--; // к значению часы вычитаем единицу у
}
if (PINC.2==0) // если нажата третья кнопка
{
min++; // к значению минуты добавляем единицу
}
if (PINC.3==0) // если нажата четвертая кнопка
{
min--; // к значению минуты вычитаем единицу
}
if (PINC.4==0) // кнопка RESET
{
sek=0;
}
}
// Declare your global variables here
void Display (unsigned int Number) //Ф-ция для разложения десятичного цисла
{
unsigned char Num2, Num3;
Num2=0;
while (Number >= 10) //десятичную
{
Number -= 10;
Num2++;
}
Num3 = Number; //остаток
Disp6 = Dig[Num2];
Disp7 = Dig[Num3];
}
void Dig_init() //Массив для отображения цыфр на семисегментном индикаторе
{
Dig[0] = 95; // Сейчас у нас схема с общим катодом
Dig[1] = 24;
Dig[2] = 109;
Dig[3] = 124;
Dig[4] = 58;
Dig[5] = 118;
Dig[6] = 119;
Dig[7] = 28;
Dig[8] = 127;
Dig[9] = 126;
}
void main(void)
{
// Declare your local variables here
// Input/Output Ports initialization
// Port B initialization
// Func7=Out Func6=Out Func5=Out Func4=Out Func3=Out Func2=Out Func1=Out Func0=Out
// State7=0 State6=0 State5=0 State4=0 State3=0 State2=0 State1=0 State0=0
PORTB=0x00;
DDRB=0xFF;
// Port C initialization
// Func6=In Func5=In Func4=In Func3=In Func2=In Func1=In Func0=In
// State6=T State5=T State4=T State3=T State2=T State1=T State0=T
PORTC=0xFF;
DDRC=0x00;
// Port D initialization
// Func7=In Func6=In Func5=In Func4=In Func3=In Func2=In Func1=In Func0=In
// State7=T State6=T State5=T State4=T State3=T State2=T State1=T State0=T
PORTD=0x00;
DDRD=0xFF;
// Timer/Counter 0 initialization
// Clock source: System Clock
// Clock value: Timer 0 Stopped
TCCR0=0x00;
TCNT0=0x00;
// Timer/Counter 1 initialization
// Clock source: System Clock
// Clock value: 7,813 kHz
// Mode: Normal top=FFFFh
// OC1A output: Discon.
// OC1B output: Discon.
// Noise Canceler: Off
// Input Capture on Falling Edge
// Timer 1 Overflow Interrupt: Off
// Input Capture Interrupt: Off
// Compare A Match Interrupt: On
// Compare B Match Interrupt: Off
TCCR1A=0x00;
TCCR1B=0x05;
TCNT1H=0x00;
TCNT1L=0x00;
ICR1H=0x00;
ICR1L=0x00;
OCR1AH=0x1E;
OCR1AL=0x85;
OCR1BH=0x00;
OCR1BL=0x00;
// Timer/Counter 2 initialization
// Clock source: System Clock
// Clock value: Timer 2 Stopped
// Mode: Normal top=FFh
// OC2 output: Disconnected
ASSR=0x00;
TCCR2=0x00;
TCNT2=0x00;
OCR2=0x00;
// External Interrupt(s) initialization
// INT0: Off
// INT1: Off
MCUCR=0x00;
// Timer(s)/Counter(s) Interrupt(s) initialization
TIMSK=0x10;
// Analog Comparator initialization
// Analog Comparator: Off
// Analog Comparator Input Capture by Timer/Counter 1: Off
ACSR=0x80;
SFIOR=0x00;
// LCD module initialization
// Global enable interrupts
#asm("sei")
Dig_init(); //инициализация массива с двоичным кодом
while (1)
{///// Условия часов.
if(sek==60) // если сек = 60
{
min++; // добавляем 1 к переменной "минута"
sek=0; // зануляем переменную "секунда"
}
if(min==60) // если мин = 60
{
hour++; // добавляем 1 к переменной "час"
min=0; // зануляем переменную "минута"
sek=0;
}
if (hour==24) // так как у нас часы имеют 24 часовый формат
{ // при достыжении 24 часов, онулируем все переменные.
hour=0;
min=0;
sek=0;
}
// защита переполнения переменной, она нужна для того чтобы в моментах когда время не переходило в минус.
if (hour==255)
hour=0;
if (min==255)
min=0;
// выводим переменные (стробирование)
Display(hour); //разложили "часы" на 2 цифры и отобразили по очереди
PORTB=254; //даем лог 0 для катода 1 разряда
PORTD=Disp6; //1 цифра
delay_ms(1);
PORTB=253; //даем лог 0 для катода 2 разряда
PORTD=Disp7; //2 цифра
delay_ms(1);
Display(min); //разложили "минуты" на 2 цифры и отобразили по очереди
PORTB=251; //даем лог 0 для катода 3 разряда
PORTD=Disp6; //3 цифра
delay_ms(1);
PORTB=247; //даем лог 0 для катода 4 разряда
PORTD=Disp7; //4...
delay_ms(1);
};
}
Где взял, извините не помню(
А было бы совсем приятно, если бы кто-нибудь поделился хорошо работающей схемой) Только желательно без DS13.. Мне нужны просто часы, без всяких наворотов)