Sinoptic555 0 February 19, 2008 Posted February 19, 2008 (edited) · Report post Пытаюсь добиться, чтобы таймер 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 February 19, 2008 by Sinoptic555 Quote Share this post Link to post Share on other sites More sharing options...
msalov 0 February 19, 2008 Posted February 19, 2008 (edited) · Report post Пытаюсь добиться, чтобы таймер B каждую секунду генерил прерывание. Проблема в том, что переполняется стек и программа перестает работать. ... Попробуйте так: TimerB_Init(); _BIS_SR(GIE); // Global interrupt enable Edited February 19, 2008 by gotty Quote Share this post Link to post Share on other sites More sharing options...
rezident 0 February 19, 2008 Posted February 19, 2008 · Report post Во-первых, как указал 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 ограничена функцией или модулем в котором она объявлена. Quote Share this post Link to post Share on other sites More sharing options...
Sinoptic555 0 February 20, 2008 Posted February 20, 2008 · Report post Проблему вроде разрешил - напутал с инициализацией. Взял Ваш фрагмент и ТimerB стал работать стабильно. Также, нашел ошибку - поперли необработанные прерывания от портов, вот все и уходило в никуда с переполнением стека. Сейчас все заработало как часики. :cheers: Огромное спасибо. Quote Share this post Link to post Share on other sites More sharing options...