Отговори на тема  [ 8 мнения ] 
18F452 TMR1 LOW interrupt се изпълява само веднъж. 
Автор Съобщение
Ранг: Минаващ
Ранг: Минаващ

Регистриран на: Чет Окт 12, 2006 3:52 pm
Мнения: 21
Местоположение: Varna
Мнение 18F452 TMR1 LOW interrupt се изпълява само веднъж.
Здравейте.Немога да открия къде греша.
Имам две прекъсвания за обработка от tmr0(висок приоритет) на всеки 50us и TMR1(нисък приоритет) на всеки 10mS.

Кода е следния :
Код:
#pragma code isr_hndl=0x08
void high_isr(void)
{
   _asm goto timer_isr   _endasm
}
#pragma code

#pragma code low_vector=0x18
void interrupt_at_low_vector(void)
{
   _asm goto   low_isr_h _endasm
}   
#pragma code


Код:
   T0CON=0b01000001;
   TMR0L=0x00;
   TMR0H=0x00;
   RCONbits.IPEN=1;   //С приоритет на прекъсванията.
   INTCON=0b00100000;   //Разрешено е прекъсване само от TMR0;
   INTCON2=0b10000100;   //ТМR0 висок приоритет.

   T1CON=0b00110100;   //TMR1 1/8 delitel, registers write in 2 8-bit words
   PIR1bits.TMR1IF=0;PIE1bits.TMR1IE=1;IPR1bits.TMR1IP=0;
   TMR1H=tmr1h;TMR1L=tmr1l;

След приключване на инициализацията на контролера си пускам и двата таймера и разрешавам прекъсванията:
Код:
   T1CONbits.TMR1ON=1;
   TMR0L=tmrval;
   T0CONbits.TMR0ON=1;   //Разрешава работата на TMR0.
   INTCONbits.GIE=1;   //Разрешава прекъсванията.
   INTCONbits.PEIE=1;


Код:
#pragma interrupt timer_isr
void timer_isr(void)
{
   T0CONbits.TMR0ON=0;
   INTCONbits.TMR0IF=0;

   if(count==0)
   {
      count=62;//нулира едни променливи
   }
   else
   {
      count--;
      //Прави нещо по портовете
      TMR0L=tmrval;
      T0CONbits.TMR0ON=1;
}


Код:
#pragma interruptlow low_isr_h
void low_isr_h(void)
{
   unsigned char i;
   if(PIR1bits.TMR1IF == 1)
   {
      PIR1bits.TMR1IF=0;
      T1CONbits.TMR1ON=0;
   //вика една функция
      TMR1H=tmr1h;TMR1L=tmr1l;
      T1CONbits.TMR1ON=1;
   }
}

Проблема е, че след като един път обработено прекъсването от TMR1 никога повече не се обработва, макар, че TMR1IF = 1, брояча се препълва, т.е. таймера си работи.
Къде може да е проблема,така че при установяване на флага за прекъсване на TMR1 да не се генерира(обработва) прекъсване с нисък приоритет при условие, че всички стойности по конфигурационните му регистри остават непроменени?


Пет Яну 20, 2012 8:12 pm
Профил ICQ
Ранг: Форумен бог
Ранг: Форумен бог
Аватар

Регистриран на: Чет Фев 24, 2005 11:41 pm
Мнения: 1049
Местоположение: Pz
Мнение Re: 18F452 TMR1 LOW interrupt се изпълява само веднъж.
В void timer_isr(void), след като свърши else-то, липсва затварящата скоба. Сигурно си я сложил някъде по-нататък в сорса и става една...


Съб Яну 21, 2012 12:10 am
Профил ICQ
Ранг: Форумен бог
Ранг: Форумен бог
Аватар

Регистриран на: Пет Фев 25, 2005 1:58 pm
Мнения: 4585
Местоположение: US
Мнение Re: 18F452 TMR1 LOW interrupt се изпълява само веднъж.
Този професор е от първите версии PIC18 и има една кофа бъгове ( при прекъсванията също ). Примерно аз използвам наследника му PIC18F4580 със следния код за прекъсване ( не е точно за TMR0/TMR1 ):
Код:

#pragma code

void InterruptHandlerHigh(void);
void InterruptHandlerLow(void);

// For more information see 80202g.pdf, section 19, Interrupts.
void WorkAroundInterruptBug(void)   {
  _asm
    POP
    goto InterruptHandlerHigh
  _endasm
}

//--------------------------------------------------------------------
// High priority interrupt vector
#pragma code InterruptVectorHigh = 0x08
void InterruptVectorHigh( void )   {  _asm    CALL WorkAroundInterruptBug, 1    _endasm   }

//--------------------------------------------------------------------
// Low priority interrupt vector
#pragma code InterruptVectorLow = 0x18
void InterruptVectorLow( void )      {  _asm    goto InterruptHandlerLow      _endasm   }

//--------------------------------------------------------------------
// High priority interrupt routine
#pragma code
#pragma interrupt InterruptHandlerHigh

void InterruptHandlerHigh( void )   {
static uint8 counter = 2;
   // INT0 external interrupt come from short circuit protection built with
   // comparator TLC3702,MC74HC08ADR2,MC74VHC1G08DTT and MC74VHC1G04D
   if( INTCONbits.INT0IE ) {
      if( INTCONbits.INT0IF ) {      
         INTCONbits.INT0IF = 0;
                                  // ... Put your code here ...
      }
   }

   // PWM servo rate TMR2 interrpt
   if( PIR1bits.TMR2IF )   {      // TMR2IF is set every 300us ( TMR2Postscaler12 )
      PIR1bits.TMR2IF = 0;      // Clear TMR2 interrupt flag
      // .... Put your code here ....
   }
}


//--------------------------------------------------------------------
// Low priority interrupt routine
#pragma code
#pragma interrupt InterruptHandlerLow nosave=section("MATH_DATA"),section(".tmpdata")
void InterruptHandlerLow(void) {
// ... Put your code here ...
}




Не ми става ясно защо спираш таймерите в тялото на прекъсването. За да ги презаредиш не е нужно да ги спираш. При 16-битов TMR0/TMR1 просто спазваш правилото ( както си го направил ) 1-во зареждаш старшия байт, след което младшия. Провери какво ще стане ако не спираш TMR1, въпреки че TMR1ON = 0 не би трябвало да нулира TMR1IE бита.

_________________
Ето аз дишам, работя, живея и програми пиша тъй както умея, с проца под вежди се гледаме строго и боря се с него доколкото мога....


Съб Яну 21, 2012 12:12 am
Профил WWW
Ранг: Минаващ
Ранг: Минаващ

Регистриран на: Чет Окт 12, 2006 3:52 pm
Мнения: 21
Местоположение: Varna
Мнение Re: 18F452 TMR1 LOW interrupt се изпълява само веднъж.
¶ написа:
..Не ми става ясно защо спираш таймерите в тялото на прекъсването. За да ги презаредиш не е нужно да ги спираш. При 16-битов TMR0/TMR1 просто спазваш правилото ( както си го направил ) 1-во зареждаш старшия байт, след което младшия. Провери какво ще стане ако не спираш TMR1, въпреки че TMR1ON = 0 не би трябвало да нулира TMR1IE бита.


Пробвах и проблема е решен :rolleyes:.Без да спирам таймера всичко е ОК, само презареждам стойността му :).Мерси за бързия fix :)...
От постнатия коментар, в 80202g.pdf секция 19 има доста интересни неща :)...

@Gogo, скобата е там в кода, но като копи/паствах и съм е изтрил, мерси все пак :).


Съб Яну 21, 2012 12:16 pm
Профил ICQ
Ранг: Форумен бог
Ранг: Форумен бог
Аватар

Регистриран на: Пет Фев 25, 2005 1:58 pm
Мнения: 4585
Местоположение: US
Мнение Re: 18F452 TMR1 LOW interrupt се изпълява само веднъж.
Моят съвет е да не се занимаваш с 452 ами да използваш 4580, използва се масово в автомобилната индустрия, ако му погледнеш errata документите всички бъгове са оправени, има само един в I2C модула. 45K80/46K80 също ще са популярна серия, при тях за година оправиха повечето бъгове.


Прави ми впечатление, че за широко използваните си модели процесори Microchip се грижат да оправят бъговете, тези които не са популярни ги отсвирват, което не им пречи да продължават да ги предлагат. Така че като се спреш на някой модел отвори и разгледай errata документите, те са веднага под data sheet за съответния процесор. Най-отдолу в errata има history на корекциите по силиция, най-отгоре пък имат таблици при кои ревизии какво е коригирано. Ако с напредването на ревизиите са коригирани повечето бъгове това е сигурен индикатор, че от този модел се пазарува и затова са се погрижили да оправят бъговете. Ако има 1-2 ревизии и не са коригирано повечето бъгове, това означава стой надалеко от този модел, заебали са го защото не се търси и може би никога няма да коригират бъговете му.


На въпроса с TMR1, от това което казваш излиза, че TMR1ON = 0 явно нулира TMR1IE . Можеш ли да изпробваш да спираш TMR1 преди да го заредиш ( както ти е първата версия ), но след TMR1ON = 1 да добавиш и TMR1IE = 1 ? Просто ми е интересно що за щуротия са направили, че спирайки таймера да се променя и TMR1IE.

_________________
Ето аз дишам, работя, живея и програми пиша тъй както умея, с проца под вежди се гледаме строго и боря се с него доколкото мога....


Съб Яну 21, 2012 12:37 pm
Профил WWW
Ранг: Форумен бог
Ранг: Форумен бог
Аватар

Регистриран на: Сря Апр 20, 2005 12:02 pm
Мнения: 9119
Местоположение: Разград
Мнение Re: 18F452 TMR1 LOW interrupt се изпълява само веднъж.
Edi, тя тая ерата е за съвсем друг силикон а и е за ревизия A1 на чипа - демек първата. Ако погледнеш всички ерати, ще видиш това което ти казва Пирев - в последната ревизия е останал един единствен бъг в I2C slave mode :)

За 452 въобще и в първата ерата няма нищо по въпроса... В инетерс на истината и на мен ми е странно защо ще си забрани прекъсването сам, като го спреш ?!?!


Съб Яну 21, 2012 1:00 pm
Профил ICQ
Ранг: Минаващ
Ранг: Минаващ

Регистриран на: Чет Окт 12, 2006 3:52 pm
Мнения: 21
Местоположение: Varna
Мнение Re: 18F452 TMR1 LOW interrupt се изпълява само веднъж.
Незнам, но е факт, че нещата се оправиха когато си оставих да работи TMR1.Ползвам този процесор, защото имам доста бройки под ръка, а и оригиналния софтуер е писан за него.Може би ще го портна за 4580, но няма да е сега, т.к. скоро проекта трябва да е на линия и гледам да го направя да работи коректно предвид обстоятелствата.

Цитат:
...Можеш ли да изпробваш да спираш TMR1 преди да го заредиш ( както ти е първата версия ), но след TMR1ON = 1 да добавиш и TMR1IE = 1 ? Просто ми е интересно що за щуротия са направили, че спирайки таймера да се променя и TMR1IE.


Не се променя нищо.Пробвах го :).Един път влиза в прекъсването и това е.


Съб Яну 21, 2012 4:21 pm
Профил ICQ
Ранг: Форумен бог
Ранг: Форумен бог
Аватар

Регистриран на: Сря Апр 20, 2005 12:02 pm
Мнения: 9119
Местоположение: Разград
Мнение Re: 18F452 TMR1 LOW interrupt се изпълява само веднъж.
А я разгледай асемблера след като го компилираш - да не би компилатора да се прави на умен и да изключва прекъсването а после да не го включва. На мен на такова ми намирисва.


Съб Яну 21, 2012 8:08 pm
Профил ICQ
Покажи мненията от миналия:  Сортирай по  
Отговори на тема   [ 8 мнения ] 

Кой е на линия

Потребители разглеждащи този форум: Google [Bot] и 2 госта


Вие не можете да пускате нови теми
Вие не можете да отговаряте на теми
Вие не можете да променяте собственото си мнение
Вие не можете да изтривате собствените си мнения
Вие не можете да прикачвате файл

Търсене:
Иди на:  
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group.
Designed by ST Software for PTF.
Хостинг и Домейни