This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

MSP430F1611: Timer_B Counter Issue.

Part Number: MSP430F1611


Dear All,

I am currently trying to build a counter that increments every 7.25ms.

My device is TelosB, which is MSP430F1611 with Crystal Oscilator of 32768Hz.

I set the Timer_B with ACLK which is the crystal and as time = number of counts/frequency.

To increment every 7.25ms, 328 counts are required.  Please refer to the code attached.

I have an issue, because two of capture/compare reigsters are occupied for radio capture and interval.

Here I declared

void sctimer_asncounter(void){
TBCCTL3 = CCIE;
TBCCR3 = 328;
TBCCTL3 |= CCIFG;
}


which triggers the appropriate interrupt handler.

case 0x0006: // CCR3 fires
if (TBCCTL3 & CCI){
if(sctimer_vars.asnreadcb !=NULL){
sctimer_vars.asnreadcb();
// kick the OS
return KICK_SCHEDULER;
}
}


where 

void cb_asnread(void){
app_vars.num_asn++;
uart_writeByte(app_vars.num_asn);

sctimer_asncounter();
sctimer_setCompare(sctimer_readCounter()+SCTIMER_PERIOD);

}


So it should constantly increases app_vars.numb_asn++ every 7.25ms but for somereason I can't even compile the code.

any help will be greatly appreicated.

Thank you.

sctimer.h

#include "stdint.h"
#include "string.h"
#include "board.h"
#include "debugpins.h"
#include "leds.h"
#include "sctimer.h"
#include "uart.h"


//=========================== defines =========================================

#define SCTIMER_PERIOD     32768 // @32kHz = 1s

//=========================== variables =======================================

typedef struct {
   uint16_t num_compare;
   uint16_t num_last_value;
   uint64_t num_asn;
} app_vars_t;

app_vars_t app_vars;

//=========================== prototypes ======================================

void cb_compare(void);
void cb_asnread(void);

//=========================== main ============================================

/**
\brief The program starts executing here.
*/
int mote_main(void) {  
   
   // initialize board. 
   board_init();
   
   sctimer_set_callback(cb_compare);
   sctimer_set_setasnreadcb(cb_asnread);
   sctimer_setCompare(sctimer_readCounter()+SCTIMER_PERIOD);


   while (1) {
      board_sleep();
   }
}

//=========================== callbacks =======================================

void cb_asnread(void){
  app_vars.num_asn++;
  uart_writeByte(app_vars.num_asn);

  sctimer_asncounter();
  sctimer_setCompare(sctimer_readCounter()+SCTIMER_PERIOD);

}

void cb_compare(void) {
   
   // increment counter
   app_vars.num_compare++;

   sctimer_setCompare(sctimer_readCounter()+SCTIMER_PERIOD);
}

#include "sctimer.h"
#include "msp430f1611.h"
#include "sctimer.h"
#include "board.h"
#include "leds.h"
#include "radio.h"
#include "uart.h"

// ========================== define ==========================================

#define TIMERLOOP_THRESHOLD    0x4000     // 0.5 seconds @ 32768Hz clock
#define MINIMUM_COMPAREVALE_ADVANCE  3

// ========================== variable ========================================

typedef struct {
    sctimer_cbt         cb;
    sctimer_capture_cbt startFrameCb;
    sctimer_capture_cbt endFrameCb;
    sctimer_asn_cbt     asnreadcb;
    uint8_t             f_SFDreceived;
    uint64_t            asncounter;
} sctimer_vars_t;

sctimer_vars_t sctimer_vars;

// ========================== private ==========================================

// ========================== protocol =========================================

/**
\brief Initialization sctimer.
*/
void sctimer_init(void){
    memset(&sctimer_vars, 0, sizeof(sctimer_vars_t));
   
   // radio's SFD pin connected to P4.1
   P4DIR   &= ~0x02; // input
   P4SEL   |=  0x02; // in CCI1a/B mode
      
   // CCR1 in capture mode
   TBCCTL1  =  CM_3+SCS+CAP+CCIE;
   TBCCR1   =  0;
   
   // CCR2 in compare mode (disabled for now)
   TBCCTL2  =  0;
   TBCCR2   =  0;

   // CCR3 in Count mode (disabled for now)
   TBCCTL3  =  0;
   TBCCR3   =  0;

   // start counting
   TBCTL    =  MC_2+TBSSEL_1;                    // continue mode, clocked from ACLK
}

void sctimer_set_callback(sctimer_cbt cb){
    sctimer_vars.cb = cb;
}

void sctimer_setStartFrameCb(sctimer_capture_cbt cb){
    sctimer_vars.startFrameCb = cb;
}

void sctimer_setEndFrameCb(sctimer_capture_cbt cb){
    sctimer_vars.endFrameCb = cb;
}

void sctimer_setasnreadcb(sctimer_asn_cbt cb){
    sctimer_vars.asnreadcb = cb;

}

void sctimer_asncounter(void){
    TBCCTL3 = CCIE;
    TBCCR3 = 328;
    TBCCTL3 |= CCIFG;
}
/**
\brief set compare interrupt
*/
void sctimer_setCompare(PORT_TIMER_WIDTH val){
    TBCCTL2             =  CCIE;
    if (TBR - val < TIMERLOOP_THRESHOLD){
        // the timer is already late, schedule the ISR right now manually 
        // setting the interrupt flag triggers an interrupt
        TBCCTL2          |=  CCIFG;
    } else {
        if (val-TBR<MINIMUM_COMPAREVALE_ADVANCE){
            // there is hardware limitation to schedule the timer within TIMERTHRESHOLD ticks
            // setting the interrupt flag triggers an interrupt
            TBCCTL2          |=  CCIFG;
        } else {
            // schedule the timer at val
            TBCCR2            =  val;
        }
    }
}

/*
\brief Return the current value of the timer's counter.

 \returns The current value of the timer's counter.
*/
PORT_TIMER_WIDTH sctimer_readCounter(void){
    return TBR;
}

void sctimer_enable(void){
    TBCCTL2 |=  CCIE;
}

void sctimer_disable(void){
    TBCCTL2 &= ~CCIE;
}

// ========================== private =========================================


//=========================== interrupt handlers ==============================

/**
\brief TimerB CCR1-6 interrupt service routine
*/
kick_scheduler_t sctimer_isr() {
   PORT_TIMER_WIDTH tbiv_local;
   
   // reading TBIV returns the value of the highest pending interrupt flag
   // and automatically resets that flag. We therefore copy its value to the
   // tbiv_local local variable exactly once. If there is more than one 
   // interrupt pending, we will reenter this function after having just left
   // it.
   
   tbiv_local = TBIV;
   
   switch (tbiv_local) {
      case 0x0002: // CCR1 fires
         if (TBCCTL1 & CCI) {
            // SFD pin is high: this was the start of a frame
            if (sctimer_vars.startFrameCb!=NULL) {
               sctimer_vars.startFrameCb(TBCCR1);
               sctimer_vars.f_SFDreceived = 1;
               // kick the OS
               return KICK_SCHEDULER;
            }
         } else {
            // SFD pin is low: this was the end of a frame
            if (sctimer_vars.endFrameCb!=NULL) {
               if (sctimer_vars.f_SFDreceived == 1) {
                  sctimer_vars.endFrameCb(TBCCR1);
                  sctimer_vars.f_SFDreceived = 0;
               }
               TBCCTL1 &= ~COV;
               TBCCTL1 &= ~CCIFG;
               // kick the OS
               return KICK_SCHEDULER;
            }
         }
         break;
      case 0x0004: // CCR2 fires
         if (sctimer_vars.cb!=NULL) {
            sctimer_vars.cb();
            // kick the OS
            return KICK_SCHEDULER;
         }
         break;
      case 0x0006: // CCR3 fires
          if (TBCCTL3 & CCI){
            if(sctimer_vars.asnreadcb !=NULL){
              sctimer_vars.asnreadcb();
               // kick the OS
               return KICK_SCHEDULER;
            }
          }
         break;
      case 0x0008: // CCR4 fires
         break;
      case 0x000a: // CCR5 fires
         break;
      case 0x000c: // CCR6 fires
         break;
      case 0x000e: // timer overflow
         break;
   }
   return DO_NOT_KICK_SCHEDULER;
}

  • What do you mean with "can't even compile"? Is there some error?
  • When I compile I get an error of this "

    01bsp_sctimer.c:(.text+0x6a): undefined reference to `sctimer_set_setasnreadCb'"

    #include "sctimer.h"
    #include "msp430f1611.h"
    #include "sctimer.h"
    #include "board.h"
    #include "leds.h"
    #include "radio.h"
    #include "uart.h"
    
    // ========================== define ==========================================
    
    #define TIMERLOOP_THRESHOLD    0x4000     // 0.5 seconds @ 32768Hz clock
    #define MINIMUM_COMPAREVALE_ADVANCE  3
    
    // ========================== variable ========================================
    
    typedef struct {
        sctimer_cbt         cb;
        sctimer_capture_cbt startFrameCb;
        sctimer_capture_cbt endFrameCb;
        sctimer_asn_cbt     asnreadCb;
        uint8_t             f_SFDreceived;
    } sctimer_vars_t;
    
    sctimer_vars_t sctimer_vars;
    
    // ========================== private ==========================================
    
    // ========================== protocol =========================================
    
    /**
    \brief Initialization sctimer.
    */
    void sctimer_init(void){
        memset(&sctimer_vars, 0, sizeof(sctimer_vars_t));
       
       // radio's SFD pin connected to P4.1
       P4DIR   &= ~0x02; // input
       P4SEL   |=  0x02; // in CCI1a/B mode
          
       // CCR1 in capture mode
       TBCCTL1  =  CM_3+SCS+CAP+CCIE;
       TBCCR1   =  0;
       
       // CCR2 in compare mode (disabled for now)
       TBCCTL2  =  0;
       TBCCR2   =  0;
    
       // CCR3 in Count mode (disabled for now)
       TBCCTL3  =  0;
       TBCCR3   =  0;
    
       // start counting
       TBCTL    =  MC_2+TBSSEL_1;                    // continue mode, clocked from ACLK
    }
    
    void sctimer_set_callback(sctimer_cbt cb){
        sctimer_vars.cb = cb;
    }
    
    void sctimer_setStartFrameCb(sctimer_capture_cbt cb){
        sctimer_vars.startFrameCb = cb;
    }
    
    void sctimer_setEndFrameCb(sctimer_capture_cbt cb){
        sctimer_vars.endFrameCb = cb;
    }
    
    void sctimer_setasnreadCb(sctimer_asn_cbt cb){
        sctimer_vars.asnreadCb = cb;
    
    }
    
    void sctimer_asncounter(void){
        TBCCTL3 = CCIE;
        TBCCR3 = 328;
        TBCCTL3 |= CCIFG;
    }
    /**
    \brief set compare interrupt
    */
    void sctimer_setCompare(PORT_TIMER_WIDTH val){
        TBCCTL2             =  CCIE;
        if (TBR - val < TIMERLOOP_THRESHOLD){
            // the timer is already late, schedule the ISR right now manually 
            // setting the interrupt flag triggers an interrupt
            TBCCTL2          |=  CCIFG;
        } else {
            if (val-TBR<MINIMUM_COMPAREVALE_ADVANCE){
                // there is hardware limitation to schedule the timer within TIMERTHRESHOLD ticks
                // setting the interrupt flag triggers an interrupt
                TBCCTL2          |=  CCIFG;
            } else {
                // schedule the timer at val
                TBCCR2            =  val;
            }
        }
    }
    
    /*
    \brief Return the current value of the timer's counter.
    
     \returns The current value of the timer's counter.
    */
    PORT_TIMER_WIDTH sctimer_readCounter(void){
        return TBR;
    }
    
    void sctimer_enable(void){
        TBCCTL2 |=  CCIE;
    }
    
    void sctimer_disable(void){
        TBCCTL2 &= ~CCIE;
    }
    
    // ========================== private =========================================
    
    
    //=========================== interrupt handlers ==============================
    
    /**
    \brief TimerB CCR1-6 interrupt service routine
    */
    kick_scheduler_t sctimer_isr() {
       PORT_TIMER_WIDTH tbiv_local;
       
       // reading TBIV returns the value of the highest pending interrupt flag
       // and automatically resets that flag. We therefore copy its value to the
       // tbiv_local local variable exactly once. If there is more than one 
       // interrupt pending, we will reenter this function after having just left
       // it.
       
       tbiv_local = TBIV;
       
       switch (tbiv_local) {
          case 0x0002: // CCR1 fires
             if (TBCCTL1 & CCI) {
                // SFD pin is high: this was the start of a frame
                if (sctimer_vars.startFrameCb!=NULL) {
                   sctimer_vars.startFrameCb(TBCCR1);
                   sctimer_vars.f_SFDreceived = 1;
                   // kick the OS
                   return KICK_SCHEDULER;
                }
             } else {
                // SFD pin is low: this was the end of a frame
                if (sctimer_vars.endFrameCb!=NULL) {
                   if (sctimer_vars.f_SFDreceived == 1) {
                      sctimer_vars.endFrameCb(TBCCR1);
                      sctimer_vars.f_SFDreceived = 0;
                   }
                   TBCCTL1 &= ~COV;
                   TBCCTL1 &= ~CCIFG;
                   // kick the OS
                   return KICK_SCHEDULER;
                }
             }
             break;
          case 0x0004: // CCR2 fires
             if (sctimer_vars.cb!=NULL) {
                sctimer_vars.cb();
                // kick the OS
                return KICK_SCHEDULER;
             }
             break;
          case 0x0006: // CCR3 fires
              if (TBCCTL3 & CCI){
                if(sctimer_vars.asnreadCb !=NULL){
                  sctimer_vars.asnreadCb();
                   // kick the OS
                   return KICK_SCHEDULER;
                }
              }
             break;
          case 0x0008: // CCR4 fires
             break;
          case 0x000a: // CCR5 fires
             break;
          case 0x000c: // CCR6 fires
             break;
          case 0x000e: // timer overflow
             break;
       }
       return DO_NOT_KICK_SCHEDULER;
    }
    
    5850.sctimer.h
    #include "stdint.h"
    #include "string.h"
    #include "board.h"
    #include "debugpins.h"
    #include "leds.h"
    #include "sctimer.h"
    #include "uart.h"
    
    
    //=========================== defines =========================================
    
    #define SCTIMER_PERIOD     32768 // @32kHz = 1s
    
    //=========================== variables =======================================
    
    typedef struct {
       uint16_t num_compare;
       uint16_t num_last_value;
       uint64_t num_asn;
    } app_vars_t;
    
    app_vars_t app_vars;
    
    //=========================== prototypes ======================================
    
    void cb_compare(void);
    void cb_asnread(void);
    
    //=========================== main ============================================
    
    /**
    \brief The program starts executing here.
    */
    int mote_main(void) {  
       
       // initialize board. 
       board_init();
       
       sctimer_set_callback(cb_compare);
       sctimer_set_setasnreadCb(cb_asnread);
       sctimer_setCompare(sctimer_readCounter()+SCTIMER_PERIOD);
    
    
       while (1) {
          board_sleep();
       }
    }
    
    //=========================== callbacks =======================================
    
    void cb_asnread(void){
      app_vars.num_asn++;
      uart_writeByte(app_vars.num_asn);
    
      sctimer_asncounter();
      sctimer_setCompare(sctimer_readCounter()+SCTIMER_PERIOD);
    
    }
    
    void cb_compare(void) {
       
       // increment counter
       app_vars.num_compare++;
    
       sctimer_setCompare(sctimer_readCounter()+SCTIMER_PERIOD);
    }
    

  • I managed to compile it, but it's not doing in the right frequency.
    The increment gets printed out every second

**Attention** This is a public forum