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.

MSP-EXP430F5529LP: How to program the Timer0_B7 CC0 interrupt

Part Number: MSP-EXP430F5529LP
Other Parts Discussed in Thread: MSP430F5529,

OK - and trying to run an interrupt on the Timer B CC0 channel, so when TBxR wraps. I've stripped down my code to a simple test program, that is designed to have the interrupt just flash the LED. So question is what have I missed.

The only slightly unusual thing in my code, is rather than the usual hidden function to write registers, I've just done a direct write to the memory mapped address of the register. Sh ould be able to read my code though because I should have kep standard names

Fullscreen
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
#include <msp430.h>
#include <stdint.h>
#include "timerb.h"
volatile uint32_t count=0;
int main(void)
{
// Stop WDT
HWREGW( WDT_A_BASE | WDTCTL ) = WDTPW|WDTHOLD;
// Now set up Timer B
// note do this with "+" rather than "|" as TBxEX0 is too far out!
// first disable before programming
HWREGW( TIMER_B0_BASE + TBxCTL )&=0xffcf;
// all Timer B latch updates not tied together (But
// 16 bit
// SMCLK is the clock
// divide by 1
// keep disabled
// Time clear - here we clear just be sure, but will do again when start
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

and in case you need the header file its:

Fullscreen
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
#include <stdint.h>
#define HWREGB(x) (*((volatile uint8_t *)(x)))
#define HWREGW(x) (*((volatile uint16_t *)(x)))
#define HWREGQ(x) (*((volatile uint32_t *)(x)))
// clocks to PWM cycle, and hence interupt in clocks
#define Period 1000
#define PxIN 0x00
#define PxOUT 0x02
#define PxDIR 0x04
#define PxREN 0x06
#define PxDS 0x08
#define PxSEL 0x0a
#define PxIES 0x18
#define PxIE 0x1a
#define PxIFG 0x1c
#define PxIV 0x0e
#define PxSEL 0x0a
// this is the whole wtdctl address as coun't find the 0xc offset documented
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

  • >  HWREGW( TIMER_B0_BASE + TBxCTL )= MC__UP | TBCLR ;

    You need to supply a clock; a good first guess is SMCLK (1MHz). Try instead:

    >  HWREGW( TIMER_B0_BASE + TBxCTL )= TBSSEL_2 |  MC__UP | TBCLR ; // TBSSEL__SMCLK

    ----------------

    >  if ( (count++)%100000 == 0) HWREGB( P1_BASE | PxOUT ) ^= BIT0;

    It looks like this will interrupt at 1kHz, so you'll only see an effect after 100 seconds. 

    Unsolicited: The "|" here is a bit jarring. Maybe it will (accidentally) work but I would suggest "+" instead.

  • OOps - yes original code I brought up XT2 and switched SMCLK to XT2:

    Fullscreen
    1
    2
    HWREGW( UCS_BASE | UCSCTL4 ) =
    SELM__XT2CLK | SELS__XT2CLK | SELA__REFOCLK;
    XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

    backed that out to simplify what was going on.

    My header file (msp430f5529.h) says that TBSSEL_2 is SMCLK which is also what TBSSEL__SMCLK, e.g. 0x0200. So should be the same. Yes decreased the count, originally with CPU at 4MHz was doing Period=400 cycles, equals 100kHz - and hence the number to see the flashing light.

    Anyway your changes made no difference, I'll keep digging.

  • Oh, right I missed this: You need to enable interrupts (GIE):

    >  __enable_interrupt();  // GIE=1

  • Well, there are competing statements that do "TBxCTL =" but the second only sets MC_UP and TBCLR. Wiping out the settings from the first.

  • No - that didn't help. So I now backed out my direct writing to memory registers - and makes no difference. Code still doesn't work. Currently:

    Fullscreen
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    #include <msp430.h>
    #include <stdint.h>
    //#include "timerb.h"
    volatile uint32_t count=0;
    int main(void)
    {
    // Stop WDT
    WDTCTL = WDTPW + WDTHOLD;
    __disable_interrupt();
    // Now set up Timer B
    // first disable before programming
    TB0CTL &=0xffcf;
    // and set TBIDEX to divide by 1 as well
    TB0EX0 = TAIDEX_0;
    // latch when TB0R counts to zero - and CCR0 sets period
    // and CCR0 is the interupt
    TB0CCTL0 = CLLD_1 | CCIE;
    XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

    Oh yes I used "|" rather than "+" as it forces me to align everything. So Registers for devices are aligned so "|" usually works, and the same with the bit masks inside the registers - its bits that need setting and resetting, so if I use bit operations to my mind it should be safer ...

  • OK when I remove CLLD_1 from TBCCTL0 it works. Now my problem is I want to Latch CC1-4 only when The counter wraps, which is what I understand CLLD_1 does ...

    So any ideas how I do both?

    OK - looks like I have to set CLLD_1 on CC1-4 but not set it on CC0 ...

  • Hm. I had never tried using CLLD>0 for CCR0 (in Up mode). My first guess is that TB0CL0 is (initially) 0, so the counter can't count (wrap) to 0 in order to load it with the new value (999) you gave it.

    Do you need to set CLLD>0 for CCR0? I suppose there could be some application, but I've never encountered one. One possibility might be to reverse the order: set CCR0 (with CLLD=0), then set CCTL0 (with CLLD=1).

  • No I think I don't need CLLD for CCR0 - CCR1-4 are PWM and go out to pins, and want all synchronised, and loading values set in the previous cycle. CCR0 though is just for timing.

    Wasn't sure though when coding, if all CCR needed the CCLD. ALas not easy for me to test, on the MSP-EXP430F5529LP only one of the four Timer B Pins I using actually go out to headers ,,,

  • It looks like TB0.5/.6 (P3.5/.6) are pinned out. Could you use those, at least until you get to your final board?

  • You could also use the port-mapping mechanism: Assign TB0CCR1-4 to P4.0-3 (all pinned out). [Ref User Guide (SLAU208Q) Chap 13, datasheet (SLAS590P) Table 9-7.

    There's a relevant example in MSP430F55xx_PortMap_01.c here:

    https://dev.ti.com/tirex/explore/node?node=AIUr0Ozgnda2pccZ0g-U1w__IOGqZri__LATEST

  • How did I miss P3.5/6! Yes I just looked at the run of CPU pins from 55 to 59 giving TB0.0 to TB0.4 - and never went on to find TB0.5 and 6! I may well use that, I've 100Hz sine waves coming out on all of these pins, but with subtle phase relations between some, and it would be good to be test!

    This said, more worried about timing right now; the target for operation is the pwm period, and interrupt to 100kHz, now the development board is an order of magnitude slower - so only aiming for a 10kHz interrupt. But even doing that needs *very* careful timing - and I think I'm just missing right now ...

    I'll have to look into port mapping, how its implemented (e.g. is it in hardware), and any effects on timing.

    Thanks for the help and suggestions though.

**Attention** This is a public forum