Требуется программист в Зеленограде
- обработка данных с датчиков; ColdFire; 40 тыс. e-mail:jobsmp@pochta.ru |
#define T1CompAIntEn TIMSK,OCIE1A,H
#define T1CompAIntFlag TIFR,OCF1A,H#define T1Init() TCCR1A=TCCR1C=0;TCNT1=0;TCCR1B=4;OCR1A=0x03AA;TIFR=0x10;_NOP();on(T1CompAIntEn)
#define T1SynhrLaunch() TCNT1=0;TIFR=0x10;_NOP();on(T1CompAIntEn)
Макросы on(xxx) устанавливают выбранный бит в 1. Например: on(T1CompAIntEn) устанавливает бит OCIE1A в регистре TIMSK в 1. Макрос off(xxx) - снимает бит (сбрасывает в 0).
Макрос T1Init() запускаю в начале программы для инициализации таймера 1. Я ранее уже писал, что сегодня заменил таймер2 на таймер1, чтобы найти причну или хотя бы попытаться устранить глюк, но функциональность таймера 1 в моем случае избыточна: требуется лишь отмерять постоянные временные интервалы.
Таймер настраивается таким образом, что через 0,06 секунд после его обнуления должно вызываться прерывание.
Макрос T1SynhrLaunch() перезапускает таймер, обнуляя его счетчик и, на всякий случай снимая флаг его прерывания.
МК принимает стабильный периодический сигнал с внешнего устройства частотой 50 Гц (период 0,02 сек.), и с этой частотой генерируются внешние прерывания INT7 по падающему фронту. Кратко обработчик:
#pragma vector=INT7_vect
__interrupt void INT7_interrupt(void)
{
T1SynhrLaunch(); // Перезапуск таймера ожидания импульса
................
}
Внешний сигнал обнуляет контролирующий таймер с периодичностью 0,02 сек. Таймер должен выдавать прерывание, если в течение 0,06 сек. внешних импульсов не поступало (то есть прерывание INT7 не генерировалось), но не раньше!! На контроллере стоит кварц/тактовый источник 4 МГц, источник тактирования прошит через FUSE-биты.
Кратко обработчик прерывания по компаратору А таймера 1:
#pragma vector=TIMER1_COMPA_vect
__interrupt void TIMER1_COMPA_interrupt(void)
{
TCNT1=0;
................
}
Суть: когда заканчивается обработчик прерывания INT7, немедленно запускается TIMER1_COMPA_interrupt (с предварительным возвратом в основную программу; прямой перескок в обход инструкции RETI исключен).
Внутри прерывания INT7 с таймерами ничего не делается, все прерывания запрещены (бит I в SREG сброшен). Пробовал вставлять обнуление таймера в конец обработчика INT7 - тот же результат.
Через симулятор вижу, что адресация к регистрам идет правильно и в правильном порядке. Флаги прерываний сбрасываю путем записи в них "1".
Вот и думаю-гадаю, в чем проблема. Есть подозрение, что содержимое обработчика INT7 влияет на возникновение прерывания, но доказать или опровергнуть это не могу. Там простые операции работы с памятью и элементарная логика, не связанная с периферией.