Доброго времени суток!
Я новичек и сейчас работаю над первым своим устройством на МК. Отлаживая в протеусе схему, столкнулся со странным поведением. В общих чертах: делаю код в CodeVisionAVR 3.12 Evaluation, пишу на С. Задача - разработать простенький электронный таймер, до 99 мин. Методом исключения выяснилось, что при разрешении прерываний командой sei программа начинает выполнятся сначала. Пошел по пути наименьшего сопротивления, просто разрешил прерывания в самом начале программы. В таком случае глобальная переменная time_sec, в которой хранится оставшееся время или недоступна, или сбрасывается в ноль при нажатии на любую кнопку. Нагугленые варианты решения проблемы не помогли, поэтому я вернулся к исходному варианту (код которого привел). Проект в протеусе и кодвижине прикрепил в архиве timer.rar, код также под спойлером. Я конечно понимаю, что возможно допустил какой-то банальный косяк, но найти не могу, нужен "свежий взгляд". Прошу вашей помощи!
Примечание: я закомментировал кусок кода, так что выводиться только один разряд (минуты). Это связано с тем, что у меня протеус не успевает корректно отрисовывать зажигание разрядов семисегментника по-очереди.
Spoiler
Раздел: AVR
Я новичек и сейчас работаю над первым своим устройством на МК. Отлаживая в протеусе схему, столкнулся со странным поведением. В общих чертах: делаю код в CodeVisionAVR 3.12 Evaluation, пишу на С. Задача - разработать простенький электронный таймер, до 99 мин. Методом исключения выяснилось, что при разрешении прерываний командой sei программа начинает выполнятся сначала. Пошел по пути наименьшего сопротивления, просто разрешил прерывания в самом начале программы. В таком случае глобальная переменная time_sec, в которой хранится оставшееся время или недоступна, или сбрасывается в ноль при нажатии на любую кнопку. Нагугленые варианты решения проблемы не помогли, поэтому я вернулся к исходному варианту (код которого привел). Проект в протеусе и кодвижине прикрепил в архиве timer.rar, код также под спойлером. Я конечно понимаю, что возможно допустил какой-то банальный косяк, но найти не могу, нужен "свежий взгляд". Прошу вашей помощи!
Примечание: я закомментировал кусок кода, так что выводиться только один разряд (минуты). Это связано с тем, что у меня протеус не успевает корректно отрисовывать зажигание разрядов семисегментника по-очереди.
Spoiler
#include <io.h>
#include <mega8.h>
#include <math.h>
#include <delay.h>
#define btn_start PINC.1
#define btn_inc PINC.2
#define btn_dec PINC.3
#define btn_res PINC.0
void start_stop();
void display_7seg();
volatile unsigned int time_sec = 0;
_Bool run = 0;
void main(void)
{
PORTC = 0xEF;
TCCR2|=(1<<CS20)|(1<<CS21)|(1<<WGM21)|(0<<COM21)| (0<<COM20); //предделитель на 32+режим сравнения
OCR2 = 0xFA; //сравниваемое число (250)
TIMSK |= ( 1<<OCIE2 ); //разрешаем прерывания по сравнению
DDRC = 0xF0;
DDRB = 0xff;
DDRD = 0xff;
while(1)
{
if ( ~btn_start )
{
start_stop();
delay_ms(400);
}
if ( ~btn_inc )
{
if ( time_sec < 5940 )
time_sec+= 60;
delay_ms(400);
}
if ( ~btn_dec )
{
if ( time_sec >= 60 )
time_sec-=60;
delay_ms(400);
}
if ( ~btn_res )
{
time_sec = 0;
run = 0;
delay_ms(400);
}
display_7seg();
}
}
void start_stop( void )
{
if ( run == 0 )
{
TCNT2 = 0x0; //обнуляем таймер
#asm("sei");
run = 1;
}
else
{
run = 0;
#asm("cli");
};
}
void display_7seg( void )
{
unsigned char bcd,low,high;
bcd = ceil(time_sec/60);
low = bcd % 10;
high = bcd/10;
/*switch (high)
{
case 0: { PORTB = 0b10110001; PORTD = 0b11100111; break;}
case 1: { PORTB = 0b11110111; PORTD = 0b11110111; break;}
case 2: { PORTB = 0b01111001; PORTD = 0b11100111; break;}
case 3: { PORTB = 0b01110011; PORTD = 0b11100111; break;}
case 4: { PORTB = 0b00110111; PORTD = 0b11110111; break;}
case 5: { PORTB = 0b00110011; PORTD = 0b11101111; break;}
case 6: { PORTB = 0b00110001; PORTD = 0b11101111; break;}
case 7: { PORTB = 0b11110111; PORTD = 0b11100111; break;}
case 8: { PORTB = 0b00110001; PORTD = 0b11100111; break;}
case 9: { PORTB = 0b00110011; PORTD = 0b11100111; break;}
}*/
switch(low)
{
case 0: { PORTB = 0b11011110; PORTD = 0b10111000; break;}
case 1: { PORTB = 0b11111111; PORTD = 0b10111110; break;}
case 2: { PORTB = 0b11011110; PORTD = 0b01111100; break;}
case 3: { PORTB = 0b11111110; PORTD = 0b00111100; break;}
case 4: { PORTB = 0b11111111; PORTD = 0b00111010; break;}
case 5: { PORTB = 0b11111110; PORTD = 0b00111001; break;}
case 6: { PORTB = 0b11011110; PORTD = 0b00111001; break;}
case 7: { PORTB = 0b11111111; PORTD = 0b10111100; break;}
case 8: { PORTB = 0b11011110; PORTD = 0b00111000; break;}
case 9: { PORTB = 0b11111110; PORTD = 0b00111000; break;}
}
}
interrupt [TIM1_COMPA] void timer1_compa_isr(void)
{
unsigned char i =0;
if(run == 1)
{
time_sec--;
}
if( time_sec == 0)
{
run = 0;
#asm("cli");
PORTC.4 = 1;
for( i = 0; 8; i++)
{
PORTD = 0xFF; PORTC = 0xFF;
delay_ms(700);
PORTD = 0x0; PORTC = 0x0;
}
}
}
Прикрепленные файлы:
Раздел: AVR