Я программирую PIC18F4520 и настроил его на использование внутренних часов 32 МГц.
Мне нужен счетчик, чтобы тикать каждую секунду, поэтому я использую TMR0
для этой цели.
Для использования TMR0
я установил следующее:
TMR0
переполнении.Чтобы настроить таймер на отсчет каждую секунду, я рассчитал его следующим образом:
TMR0 = (Required time)/(4 * Timer clock * prescale value)
= 1 / (4 * (1/32000000) * 256)
= 31250
Итак, TMR0 = 0xFFFF - 31250
.
Это верно? Если нет, то что мне не хватает? Код выглядит следующим образом:
#pragma code
void main(void)
{
//Set clock frequency
OSCCON |= 0x70; //8 Mhz clock, primary clock
OSCTUNEbits.PLLEN = 1; //4x Multiplier, thus we have 32 Mhz clock
while (!OSCCONbits.IOFS); //Wait until INTOSC is stable.
//Enable TRISA as analog input (For ADC)
TRISA = 0x2F;
//PIN Outputs
TRISB = 0; //Make PORTD as output
//Reset PORTB
PORTB = 0;
//Set ADC
OpenADC(ADC_FOSC_32 & //Fosc/32
ADC_RIGHT_JUST &
ADC_4_TAD, //4xTAD
ADC_CH0 &
ADC_REF_VDD_VSS &
ADC_INT_OFF, ADC_5ANA); //ADC CH0-CH4 Initialized
//Set Timer0
OpenTimer0( TIMER_INT_ON &
T0_16BIT &
T0_SOURCE_INT &
T0_PS_1_256);
//Write Timer
WriteTimer0(CLOCK_TICK);
INTCON2bits.TMR0IP = 1; //TMR0 has high overflow interrupt priority
RCONbits.IPEN = 1; //enable priority levels
INTCONbits.GIEH = 1; //enable high interrupts
//Begin
while (TRUE)
{
}
CloseADC(); //Closing ADC
CloseTimer0();
}
В моем векторе прерывания высокого уровня я сделал это:
#pragma code
#pragma interrupt high_priority_interrupt
void high_priority_interrupt()
{
if (INTCONbits.TMR0IF) //TIMER0 overflowed
{
//Stuff
second += 1;
if (second == 60)
{
minute += 1;
second = 0;
}
if (minute == 60)
{
measure_and_switch();
WriteTimer0(CLOCK_TICK);
minute = 0;
}
INTCONbits.TMR0IF = 0; //Clear TIMER0 overflow bit.
}
}
Итак, в основном, каждые 2 минуты я хочу, чтобы метод measure_and_switch()
выполнялся. Должен ли я следовать за ним WriteTimer0()
?
Кстати: CLOCK_TICK
есть TMR0
(расчет сверху).
Спасибо
Ответ прост. Когда происходит бит переполнения и возникает прерывание, нам нужно сначала записать счетчик TMR0
и сбросить TMR0IF
флаг.
Это решение работает:
#pragma code
#pragma interrupt high_priority_interrupt
void high_priority_interrupt()
{
if (INTCONbits.TMR0IF) //TIMER0 overflowed
{
//Stuff
second += 1;
if (second == 60)
{
minute += 1;
second = 0;
}
if (minute == 60)
{
measure_and_switch();
minute = 0;
}
WriteTimer0(CLOCK_TICK); //Write the count to TMR0.
INTCONbits.TMR0IF = 0; //Clear TIMER0 overflow bit.
}
}
Надеюсь, это кому-нибудь поможет. :-)
АндреяКо
Бухаке Синди
АндреяКо
Бухаке Синди