Здравствуйте! В си компиляторе 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?
Индикация динамическая.