Код: Выделить всё
ISR(TIMER1_OVF_vect)
{
Ovr++;
}
ISR(TIMER1_CAPT_vect)
{
if (Count==0)
{
Time1L = ICR1L; // Сохраняю регистр захвата
Time1H = ICR1H;
Count++; // Увеличиваю число прерываний по захвату
} else
{
Time2L = ICR1L; // Сохраняю регистр захвата
Time2H = ICR1H;
TIMSK &= ~(1<<TICIE1); // Запрещаю прерывание по захвату
TIMSK &= ~(1<<TOIE1); // Запрещаю по переполнению
Rez = ((Time2H<<8)+Time2L)-((Time1H<<8)+Time1L)+(Ovr*0xFFFF); // Подсчет длительности сигнала в тактах таймера
CaptFlag = 0;
}
}
long int TCS3200Start(char color)
{
Count = 0; // Обнуление счетчика прерываний
Ovr = 0; // Обнуление счетчика переполнений
CaptFlag = 1; // Ставлю флаг, что начался захват сигнала
TIMSK |= 1<<TICIE1; // Разрешаю прерывание по захвату
TIMSK |= 1<<TOIE1; // Прерывание по переполнению
while (CaptFlag==1) {};
return Rez; // Возвращаю значение, которое должно было обновится до снятия флага захвата
}
int main(void)
{
// =======T1======
TCCR1B |= 1<<ICNC1 | 1<<ICES1 | 0b1<<CS10;
// ===============
sei();
while(1)
{
_delay_ms(2000);
long int buff = TCS3200Start('R');
}
}Вопрос 1: Если цикл ожидания пустой, то МК из него не выходит. Но после того, как я туда добавил задержку в 1мкс (while (CaptFlag==1) {_delay_us(1);};) все стало нормально работать. Почему так?
Вопрос 2: Изначально я хотел вместе с разрешение на прерывания отключать предделитель, что бы таймер полностью останавливался и заметил, что из-за этого появился разброс в показаниях датчика. Вообще датчик сам шумит немного, но когда я заменяю прошивку МК на ту, что с отключением предделителя, шум этот очень сильно увеличивается. Почему отключение предделителя на это влияет? Можно ли предделители таймера вообще отключать?
Ладно, датчик в любом случае шумит немного, решил измерять по другому. А именно считать прерываний по совпадению за определенный промежуток времени. Обнуляю таймер, ставлю флаг и в цикле жду когда наступит прерывание по совпадению, где сбросится флаг и отключатся прерывания по захвату и совпадению.
Код: Выделить всё
ISR(TIMER1_COMPA_vect)
{
HzFlag = 0;
// Тут потом добавил отправку регистра TCNT1 по ЮАРТ для отладки
TIMSK &= ~(1<<TICIE1); // Запрещаю прерывание по захвату
TIMSK &= ~(1<<OCIE1A); // Запрещаю прерывание по совпадению
}
ISR(TIMER1_CAPT_vect)
{
Count++;
}
long int TCS3200Start(char color)
{
Count = 0; // Обнуление счетчика прерываний
HzFlag = 1;
TCNT1 = 0; // Очищаю то, что насчитал таймер
TIMSK |= 1<<OCIE1A; // Разрешаю прерывание по совпадению
TIMSK |= 1<<TICIE1; // Разрешаю прерывание по захвату
while (1) {if (HzFlag==0) {break;} } // Жду когда флаг сбросится
return Count; // Возвращаю колличество прерываний по захвату
}
int main(void)
{
// =======T1======
TCCR1B |= 1<<ICNC1 | 1<<ICES1 | 0b1<<CS10;
OCR1A = 0x1F40; // При делителе 1 должна получится задержка в 1мс
// ===============
sei();
while(1)
{
_delay_ms(1000);
long int buff = TCS3200Start('R');
}
}После того, как я добавил небольшую задержку перед разрешением прерываний по захвату, двойное срабатывание прекратилось. Прерывание наступало на 0x00F2, но данные с МК приходили не каждую секунду, как должны были, а почти через 2 секунды. Из-за чего?
Попробовал убрать эту задержку и закоментировать строку с разрешением прерывание по захвату и МК не смог выйти из цикла при ожидании снятия моего флага. Стоило добавить задержку в 1 мкс прям перед циклом или внутри цикла и МК стал выходить из этого цикла, но прерывание по совпадению так же наступало при 0x00F2.
Вернул изначальны код (второй код в этом сообщении) и вынес запрет прерываний из прерывания по совпадению за цикл ожидания сброса флага. Вместо двойного срабатывания опять просто одно при 0x00F2. Все остальные проблемы осталось такими же.
Вопрос 3: Что не так с кодом? Почему при прерывание в TCNT1 постоянно какое-то 0x00F2?



