Jump to content
    

Тамер B и переполнение стека.

Пытаюсь добиться, чтобы таймер B каждую секунду генерил прерывание.

Проблема в том, что переполняется стек и программа перестает работать.

 

Таймер запускаю в режиме "вверх" MCx=01 и TBCCR0=0x7FFF;

Таймер тактирую от часового кварца от ACLK.

 

 

В общем 1, может 2 раза оба прерывания отрабатываются: TIMERB0_VECTOR и

переполнение таймера по TBIV=0E.

Однако, если ставится большой период в TBCCR0 то вообще ничего не отрабатывается, стек переполняется и все.

Сложных функций нет, рекурсий нет, да и программы как таковой нет

откуда переполнение ума не приложу.

 

 

Скажите, это нормально что при переполнении таймера и установке TBIFG=1 во всех

регистрах TBCCTLx (кроме нулевого) CCIFG устанавливается в 1?

 

Всю голову уже сломал что не так, но понять не могу что не так.

Подскажите может кто то с переполнениями стека уже сталкивался.

 

Внизу привожу код - в общем то все по книжке.

 

void TimerB_Init(void){
  
  //Register Clearing 
  TBCTL|=TBCLR; //Clear timer [TAR] value
  TBCTL|=CNTL_0; // Set counter lenght: 16 bit
  TBCTL|=TBSSEL_1; //select ACLK (32768) input 
  TBCTL|=TBCLGRP_0; //Timer B Group: 0 - individually
  TBCTL&=0xFF0F; //IDx=00b, MCx=00xx
  TBCTL|=TBIE; //  Timer B interrupt enable =ON
  TBCTL&=~TBIFG; // Timer B interrupt flag =OFF
  
  TBCCTL0=0x000; TBCCTL0|=CLLD_0+CCIE;
  TBCCTL1=0x000; 
  TBCCTL2=0x000;
  TBCCTL3=0x000;
  TBCCTL4=0x000;
  TBCCTL5=0x000;
  TBCCTL6=0x000;
  
  //Set start conditions
  TBCCR0=0x7FFF; //Interrupt every 1 sec.
  //TBCCR0=0x100;
  TBCCR1=0x0000;
  TBCCR2=0x0000;
  TBCCR3=0x0000;
  TBCCR4=0x0000;
  TBCCR5=0x0000;
  TBCCR6=0x0000;
  
  TBCTL&=0xFFCF; //MCx=00
  TBCTL|=0x10; // Start timer UP in continious mode
}



#pragma vector=TIMERB0_VECTOR
__interrupt void TimerB0(void){
  int a=0;
    a++;
}


#pragma vector=TIMERB1_VECTOR
__interrupt void TimerB1(void){
int b=0; 

  switch(TBIV){
    case 0x02:
    break;
    
    case 0x04:
    break;
    
    case 0x0E: // Timer overflow
       b++;
    break;
  }
}



int main( void )
{
  int a=0;

   WDTCTL = WDTPW + WDTHOLD; // Stop watchdog timer
  
   FLL_CTL0&=0xF; // Reset high 4 bits
   SCFI0 &=0x3F;  // Clear FLLDx
   SCFI0 |= FN_2; // x2 DCO, 4MHz nominal DCO
   SCFQCTL = 74;  // (74+1) x 32768 = 2.45Mhz
  
   _BIS_SR(GIE); // Global interrupt enable
   
   TimerB_Init();


  // Wait for interrupts 
  while(1){
    a=a+1;
    if(a>500)
      a=0;
  }
  
  return 0;
}

Edited by Sinoptic555

Share this post


Link to post
Share on other sites

Пытаюсь добиться, чтобы таймер B каждую секунду генерил прерывание.

Проблема в том, что переполняется стек и программа перестает работать.

...

Попробуйте так:

TimerB_Init();
_BIS_SR(GIE); // Global interrupt enable

Edited by gotty

Share this post


Link to post
Share on other sites

Во-первых, как указал gotty, поменяйте очередность установки глобального флага разрешения прерываний и инициализации таймера. Инициализация должна быть проведена до разрешения прерываний.

Во-вторых, процедуру инициализации таймера можно описать проще.

unsigned int timeCntr, ovfCntr;

void TimerB_Init(void)
{ TBCTL=TBCLGRP_0|CNTL_0|TBSSEL_1|ID_0|TBCLR|TBIE;
  
  TBCCR0=32767;

  TBCCTL0=CCIE;
  TBCCTL1=0;
  TBCCTL2=0;
  TBCCTL3=0;
  TBCCTL4=0;
  TBCCTL5=0;
  TBCCTL6=0;

  TBCTL|=MC_1;
}

#pragma vector=TIMERB0_VECTOR
#pragma type_attribute=__interrupt
void TimerB0_ISR(void)
{ timeCntr++;
}

#pragma vector=TIMERB1_VECTOR
#pragma type_attribute=__interrupt
void TimerB1_ISR(void)
{ switch(TBIV)
  { case 0x0E:
      ovfCntr++;
      break;
    default:
      break;
  }
}

В-третьих, вам видимо нужно разобраться с типами данных, применяемых в Си. У вас используются только локальные (автоматические) переменные, но, как я понимаю, вы пытаетесь работаете с ними как с глобальными переменными? Переменная a в main это не та же самая переменная что и a в обработчике прерывания TimerB0. К тому же обе переменные a и b в обработчиках прерываний никогда не превысят величины 1. Т.к. вложенные прерывания у вас не разрешены, переменные обе локальные и между вызовами прерываний их значение не сохраняется. Если хотите, чтобы их значения сохранялись между вызовами обработчиков перываний, то переменные должны быть либо глобальными (объявлены вне функции, как в моем примере), либо статическими, объявленными внутри функции, но с квалификатором static). Но следует опять же учитывать, что область "видимости" переменной типа static ограничена функцией или модулем в котором она объявлена.

Share this post


Link to post
Share on other sites

Проблему вроде разрешил - напутал с инициализацией.

Взял Ваш фрагмент и ТimerB стал работать стабильно.

 

Также, нашел ошибку - поперли необработанные прерывания от портов,

вот все и уходило в никуда с переполнением стека.

 

Сейчас все заработало как часики. :cheers:

 

Огромное спасибо.

Share this post


Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...