Всем привет. У меня задача такая: есть меандр с изменяющейся частой и надо замерять время между фронтами. Надо сказать, что в МК я новичок так что прошу не бить). А делаю я так: вешаю сигнал на ногу с внешними прерываниями и по первому фронту обнуляю таймер, а по второму считываю сколько он натикал. И вот тут для меня возникает интересный вопрос! Если пользоваться INT7:4, то все работает замечательно, а если INT3:0, то все...приплыли (все время разные интервалы, далее описано почему). Что было сделано: вешал датчик то на INT7:4 то на INT3:0 (в первом случае все работает, во втором нет), проверил настройку прерывания (генерируется оно именно по фронту, не по уровню). Далее сделал так: закодил чтоб при первом входе в обработчик (на прерываниях INT3:0)на какой-нибудь свободной ноге выставлялась 1, а при втором входе выставлялся 0.
И вот что интересное обнаружилось на осциллографе: после прихода фронта с датчика наблюдается задержка с выставлением 1 на свободной ноге, далее лучше, эта задержка УВЕЛИЧИВАЕТСЯ, пока не "догонит" след фронт, а затем снова восстанавливается на небольшую задержку и снова начинает увеличиваться.
Мануал по настройке внешних прерываний говорит след:
для INT7:4 - Нарастающий фронт, выявленный по двум выборкам на INTn, генерирует запрос на прерывание.
для INT3:0 - Нарастающий фронт на INTn генерирует асинхронно запрос на прерывание
В чем разница? И может ли это как раз влиять на результат? Что-то подробнее про "этот" асинхронный запрос я не нашел чтоб понять суть.
И вот тут возникает вопрос: задержка в срабатывании прерывания как-то связана с типами этих прерываний? В момент задержки после прихода фронта где висит мк и что делает?
Код который работает как надо:
Код
ISR(INT7_vect)
{
if(edge_counter ==1)
{
value_timer = TCNT0;
edge_counter = 0;
}
else
{
TCNT0 = 0x00;
edge_counter++;
}
}
int main(void)
{
//ноги на которых внешние прерывания настроены на вход с подтяжкой
DDRC = 0x00;
PORTC = 0xFF;
DDRE = 0x00;
PORTE = 0xFF;
DDRD = 0b11000000;
PORTD = 0xFF;
//=======================
TCCR0 = 0b00000111; //деление таймера0 на 1024
//TCCR2 = 0b00000101;
//========================
TCCR1B = 0b00000011; //делитель на256 16 битного таймера1
TIMSK = (1<<TOIE1); //прерывание по переполнению
//========================
EICRA = 0x00;
EICRB = 0xC0; //настройка прерывания INT7 по фронту
EIMSK = 0x80; //разрешение прерывания от INT7
TWI_Master_Initialise();
_SEI();
while(1)
{
//вывод на экран
}
так не работает:
Код
ISR(INT3_vect)
{
if(edge_counter ==1)
{
value_timer = TCNT0;
edge_counter = 0;
}
else
{
TCNT0 = 0x00;
edge_counter++;
}
}
int main(void)
{
//ноги на которых внешние прерывания настроены на вход с подтяжкой
DDRC = 0x00;
PORTC = 0xFF;
DDRE = 0x00;
PORTE = 0xFF;
DDRD = 0b11000000;
PORTD = 0xFF;
//=======================
TCCR0 = 0b00000111; //деление таймера0 на 1024
//TCCR2 = 0b00000101;
//========================
TCCR1B = 0b00000011; //делитель на256 16 битного таймера1
TIMSK = (1<<TOIE1); //прерывание по переполнению
//========================
EICRA = 0b11000000; //настройка прерывания INT3 по фронту
EICRB = 0x00;
EIMSK = 0b00001000; //разрешение прерывания от INT3
TWI_Master_Initialise();
_SEI();
while(1)
{
//вывод на экран
}
отличия в пару цифр! мк - ATmega128 8MHz внутренним RC