Таймер 1 на PIC24F16KA102 не работает
Я хочу настроить timer1 для PIC24F16KA102 для его подсчета. Источником синхронизации должен быть внутренний тактовый генератор 8 МГц. Я настроил регистр T1CON и установил на высокий уровень бит TON для запуска таймера. Timer1 настроен на переполнение каждые 100 мкс, а затем с циклом while я увеличу счетчик переменных. Я не понимаю, потому что timer1 не работает, я заметил, что он не увеличивается. Зачем?
#include <xc.h>
#include "config.h"
int count = 0;
void main(void) {
TRISB = 0;
T1CON = 0; //TRM1 stopped, internal clock source, prescaler 1:1
_TON = 1;
TMR1 = 65135; //overflow of TM1 every 100 us (400 counts)
while (1) {
if (TMR1 == 65535) {
count++; // increase every 100 us
TMR1 = 65135;
}
}
}
1 ответ
Попробуйте установить регистр периода Таймера 1 (PR1) и использовать прерывание, а не пытаться перехватить и перезагрузить TMR1 по его окончательному счету. Вы пытаетесь поймать TMR1 на ТОЧНО 65535, и это почти никогда не сработает, потому что, как только TMR1 достигнет 65535, он просто переполнится и снова начнет считать с 0.РЕДАКТИРОВАТЬ: Конечно, это предполагает, что это имеет значение вообще. Я не знаю, каково поведение таймера, когда вы покидаете регистр периодов в 0. Он может просто сосчитать до максимума 65535, затем сброситься до 0, или он может вообще никогда не сосчитаться и постоянно загружать PRx в TMRx, так как они соответствует 0
PRx предназначен для определения периода, который вы хотите для данного таймера, в данном случае 100 мкс. PR1 = 400. Как только TMR1 = PR1, таймер автоматически перезагрузится и вызовет прерывание, чтобы предупредить вас, что таймер истек.
volatile unsigned int count = 0; //Vars that change in an ISR should be volatile
PR1 = 400; //Set Period for Timer1 (100us)
T1CON = 0x8000; //Enable Timer1
IEC0bits.T1IE = 1; //Enable Timer1 Interrupt
IPC0bits.T1IP = 0b011;
Соедините это с функцией ISR, чтобы увеличить счетчик всякий раз, когда таймер истекает:
void __attribute__ ((interrupt,no_auto_psv)) _T1Interrupt (void)
{
count++;
IFS0bits.T1IF = 0; //Make sure to clear the interrupt flag
}
Вы также можете попробовать что-то вроде этого без каких-либо прерываний:
void main(void){
unsigned int count = 0;
TMR1 = 0;
T1CON = 0x8000; //TON = 1
while(1){
if (TMR1 >= 400){
count++;
TMR1=0;
}
}
}
Однако я бы порекомендовал использовать регистр PR и ISR. Это то, что он должен делать.
РЕДАКТИРОВАТЬ: Я также рекомендовал бы прочитать Справочное руководство PIC24F на таймеры: здесь