Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: Тамер B и переполнение стека.
Форум разработчиков электроники ELECTRONIX.ru > Микроконтроллеры (MCs) > MSP430
Sinoptic555
Пытаюсь добиться, чтобы таймер 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;
}
msalov
Цитата(Sinoptic555 @ Feb 19 2008, 14:24) *
Пытаюсь добиться, чтобы таймер B каждую секунду генерил прерывание.
Проблема в том, что переполняется стек и программа перестает работать.
...

Попробуйте так:
Код
TimerB_Init();
_BIS_SR(GIE); // Global interrupt enable
rezident
Во-первых, как указал 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 ограничена функцией или модулем в котором она объявлена.
Sinoptic555
Проблему вроде разрешил - напутал с инициализацией.
Взял Ваш фрагмент и ТimerB стал работать стабильно.

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

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

Огромное спасибо.
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.