Timer0 микроконтроллера и Часы

Обсуждаются темы не относящиеся к журналу "РАДИО"

Timer0 микроконтроллера и Часы

Сообщение wlf » 04 июн 2015, 20:35

Здравствуйте! В си компиляторе Hi-Tech есть пример настройки таймера контроллера на 1 сек.
#include <pic.h>

/*
* Example code for using timer0 on a 16F84
* Just sets up a 1 second interrupt and increments a variable
*/

/*
* Calculate preload value for one second timer
*/

#define PERIOD 1000000 // period in uS - one second here
#define XTAL 4000000 // crystal frequency - 4MHz

#define IPERIOD (4 * 1000000 / XTAL) // Period of instruction clock in uSeconds

#define SCALE 256 // Timer 0 prescaler
#define T0_TICKS 256 // Number of counts for interrupt

#define TICK_PERIOD (SCALE * IPERIOD) // Period (uSec) of one increment of timer 0

#define RELOADS ((PERIOD/T0_TICKS)/TICK_PERIOD)

unsigned long seconds; // second count
near char reload = 0;

/* service routine for timer 0 interrupt */
void interrupt
timer0_isr(void)
{
if(reload == 0){
// effect a change on PORTB whenever our desired period is reached.
// Note this timing will contain a margin of error.
reload = RELOADS + 1;
seconds++;
PORTB++; // effect a change on PORTB
}
reload--;
T0IF = 0;
}

main()
{
// initialize timer 0;

OPTION = 0b0111; // prescale by 256
T0CS = 0; // select internal clock
T0IE = 1; // enable timer interrupt
GIE = 1; // enable global interrupts
TRISB = 0; // output changes on LED

for(;;)
continue; // let interrupt do its job
}


Так вот, используя этот код настройки таймера, написал код для часов.


#include <pic1684.h>
#include "delay.c"


/*
* Example code for using timer0 on a 16F84
* Just sets up a 1 second interrupt and increments a variable
*/

/*
* Calculate preload value for one second timer
*/

#define SEG_1 RA0
#define SEG_2 RA1
#define SEG_3 RA2
#define SEG_4 RA3
#define PORT_IND_A PORTA
#define PORT_IND_B PORTB
#define PERIOD 1000000 // period in uS - one second here
#define XTAL 4000000 // crystal frequency - 4MHz

#define IPERIOD (4 * 1000000 / XTAL) // Period of instruction clock in uSeconds

#define SCALE 256 // Timer 0 prescaler
#define T0_TICKS 256 // Number of counts for interrupt

#define TICK_PERIOD (SCALE * IPERIOD) // Period (uSec) of one increment of timer 0

#define RELOADS ((PERIOD/T0_TICKS)/TICK_PERIOD)

unsigned char seconds = 0, minutes = 0, m_minutes = 0, hour = 0, h_hour = 0, min = 0, hou = 0; // переменные
near char reload = 0;

unsigned char number[10] =
{
0b11000000, //0
0b11111001, //1
0b10100100, //2
0b10110000, //3
0b10011001, //4
0b10010010, //5
0b10000010, //6
0b11111000, //7
0b10000000, //8
0b10010000, //9
};



void BCD_Min(void){
min = 0; //обнуляем переменную
while(m_minutes>=10){
m_minutes = m_minutes - 10; // еденицы минут
min++; // десятки минут
}
};

void BCD_Hour(void){
hou = 0; //обнуляем переменную
while(h_hour>=10){
h_hour = h_hour - 10; // еденицы часов
hou++; // десятки часов
}
};
void interrupt timer0_isr(void) /* прерывания по таймеру 1 сек */
{
if(reload == 0){
reload = RELOADS;
seconds++;
if(seconds > 59){
minutes++;
m_minutes = minutes;
seconds = 0; //обнуляем переменную
BCD_Min();

if(minutes > 59){
hour++;
h_hour = hour;
minutes = 0; //обнуляем переменную
m_minutes = 0; //обнуляем переменную
min = 0; //обнуляем переменную
BCD_Hour();

if(hour > 23){
hour = 0; //обнуляем переменную
h_hour = 0; //обнуляем переменную
hou = 0; //обнуляем переменную
}
}

}

}
reload--; // уменьшить на 1
T0IF = 0; // сбросить флаг прерывания по переполнению
};

void main(void){

//=================== инициализация мк и таймера 0 =====================

OPTION = 0b0111; // предделитель 256
T0CS = 0; // select internal clock
T0IE = 1; // разрешить прерывания по переполнению таймера 0
GIE = 1; // разрешить прерывания глобально
TRISA = 0b00000000; // все на выход
TRISB = 0b00000000; // все на выход
PORT_IND_A = 0b00000000; // очистить ПОРТ А
PORT_IND_B = 0b00000000; // очистить ПОРТ В
BCD_Min();
BCD_Hour();

while(1){

SEG_1 = 1; // включить разряд едениц минут
PORT_IND_B = number[m_minutes]; // индикация едениц минут
DelayMs(4); //задержка на индикацию
SEG_1 = 0; // выключить разряд едениц минут
SEG_2 = 1; // включить разряд десятков минут
PORT_IND_B = number[min]; // индикация десятков минут
DelayMs(4); //задержка на индикацию
SEG_1 = 1; // точки
PORT_IND_B = 0b01111111; // разделитель
DelayMs(4); //задержка на индикацию
SEG_1 = 0;
SEG_2 = 0; // выключить разряд десятков минут
SEG_3 = 1; // включить разряд едениц часов
PORT_IND_B = number[h_hour]; // индикация едениц часов
DelayMs(4); //задержка на индикацию
SEG_3 = 0; // выключить разряд едениц часов
SEG_4 = 1; // включить разряд десятков часов
PORT_IND_B = number[hou]; // индикация десятков часов
DelayMs(4); //задержка на индикацию
SEG_4 = 0; // выключить разряд десятков часов

}
}


Но часы отстают, на много, что не так не пойму?
Или эти настройки таймера не годятся для применения в часах и лучше использовать специальные микросхемы типа DS1302 или DS1307?
Индикация динамическая.
wlf
 
Сообщения: 20
Зарегистрирован: 26 апр 2009, 19:04

Re: Timer0 микроконтроллера и Часы

Сообщение Pavel » 05 июн 2015, 10:38

Здравствуйте.
Нельзя делать прерывания в 1 секунду для часов. Вам надо сделать 1000 прерываний в секунду, например. Далее уберите из процедуры прерывания счет времени и сделайте все это в иной процедуре. То есть в процедуре прерывания вы считаете количество прерываний и когда их будет 1000 вы прибавляете секунду. Мало того меняя счет от 990 до 1010 вы можете улучшить точность часов. Ну и чем больше прерываний в секунду, тем точнее можно сделать отсчет времени.
Что касается микросхемы DS1307 (и её подобных), то лучше использовать её. Точность можно не настраивать и время не сбивается при отключении питания всей схемы. Я сначала тоже делал часы при использования таймера МК, далее перешел на часовые микросхемы и доволен. :)
Pavel
 
Сообщения: 71
Зарегистрирован: 22 мар 2010, 21:46

Re: Timer0 микроконтроллера и Часы

Сообщение wlf » 05 июн 2015, 17:08

Спасибо за ответ. Попробую подругому. А то я начал уже сомневаться в настройках таймера и правильности кода.
wlf
 
Сообщения: 20
Зарегистрирован: 26 апр 2009, 19:04


Вернуться в Всё остальное

Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 16