Добрый день.
Есть МК ATmega16, есть светодиодный индикатор 4 семисегментных символа(далее дисплей), подключеный через 2 регистра КР1533ИР24(это не суть важно)
Проблема в том что хочу вывести время на дисплей не в цикле основной программы а в таймере, что бы при паузах в основной функие, дисплей продолжал выводить информацию по прерыванию таймера.
И так, вот программа: #include <mega16.h>
#include <delay.h>
unsigned i,j;
unsigned char hour,min,sek;
unsigned int msek;
unsigned char simbols[11]=
{
0b11111100, //0
0b01100000, //1
0b11011010, //2
0b11110010, //3
0b01100110, //4
0b10110110, //5
0b10111110, //6
0b11100000, //7
0b11111110, //8
0b11110110, //9
0b00000001 // точка, в зависимости от разряда верхняя или нижняя
};
unsigned char znak[4];
// Timer 1 output compare A interrupt service routine
interrupt [TIM1_COMPA] void timer1_compa_isr(void){
// Place your code here
TCNT1H=0;
TCNT1L=0;
msek++;
if (i==0)
{
znak[0]=simbols[min/10];
znak[1]=simbols[min%10];
znak[2]=simbols[sek/10];
znak[3]=simbols[sek%10];
}
PORTD.7=1;
for (j=0;j<8;j++)
{
PORTD.6=1;
if (j==(i+4))
{
PORTD.5=0;
}
else
{
PORTD.5=1;
}
PORTD.6=0;
}
for (j=0;j<8;j++)
{
PORTD.6=1;
PORTD.5=!(znak[i]&1);
znak[i]>>=1;
PORTD.6=0;
};
PORTD.6=1;
PORTD.7=0;
i++;
if (i>3) i=0;
}
// Declare your global variables here
void main(void)
{
hour=0;
min=0;
sek=0;
msek=0;
min_old=255;
PORTA=0x00;
DDRA=0xFF;
PORTB=0x07;
DDRB=0xFF;
PORTC=0x00;
DDRC=0xFF;
PORTD=0xE0;
DDRD=0xFF;
TCCR1A=0x00;
TCCR1B=0x01;
TCNT1H=0x00;
TCNT1L=0x00;
ICR1H=0x00;
ICR1L=0x00;
OCR1AH=0x2E;
OCR1AL=0xE0;
OCR1BH=0x00;
OCR1BL=0x00;
// Timer(s)/Counter(s) Interrupt(s) initialization
TIMSK=0x10;
// Global enable interrupts
#asm("sei")
while (1)
{
if (msek>1000)
{
msek=msek-1000;
sek++;
}
if (sek>59)
{
sek=sek-60;
min++;
}
if (min>59)
{
min=min-60;
hour++;
}
if (hour>23)
{
hour=hour-24;
}
if (!PINB.0)
{
hour++;
delay_ms(250);
}
if (!PINB.1)
{
min++;
delay_ms(250);
};
//если выполнять этот код, то работает нормально, но я хочу через таймер сделать
/* for (i=0;i<4;i++){
{
znak[0]=simbols[min/10];
znak[1]=simbols[min%10];
znak[2]=simbols[sek/10];
znak[3]=simbols[sek%10];
}
for (j=0;j<8;j++)
{
PORTD.6=1;
if (j==(i+4))
{
PORTD.5=0;
}
else
{
PORTD.5=1;
}
PORTD.6=0;
}
for (j=0;j<8;j++)
{
PORTD.6=1;
PORTD.5=!(znak[i]&1);
znak[i]>>=1;
PORTD.6=0;
};
PORTD.6=1;
PORTD.7=0;
delay_us(100);
PORTD.7=1;
}
*/
}
Если тестить его в VMLAB, то все идет на ура, но вот на реальном МК происходят глюки, подаю питание на МК, он отсчитывает 3 сек и после этого прибавляет минутуи 6 сек, далее считает до 1:35 и опять перескакивает на минуту с лишним.
При этом, если убрать вывод на дисплей из таймера и вписать в основную функцию, то работает нормально, не перескакивает.
Подскажите где и что не так.
З.Ы. кварц на 12М
Добавлено (29.06.2010, 14:03)
---------------------------------------------
С этой проблемой разобрался, пересадил вывод на дисплей на другой (0)таймер.
Теперь встала другая проблема, время отстает очень сильно. Думаю кменьшать делитель счетчика нет смысла, так как после каждого изменения кода, придется снова подбирать новый делитель.
Появилась идея сделать таймер1 асинхронным.
Подскажите, как правильно это организовать.