MSP430G2553 Timer Intervals [closed]

↘锁芯ラ 提交于 2019-12-20 05:38:11

问题


After reading the text about five times and googling I've decided to reach out for help. I'm currently in the process of using Timer_A interrupt to turn on/off two LEDS in intervals of 1 second/10 seconds/1 minute one at a time. The default program will turn on/off the LEDS every second but I cannot find a way to turn them off after 10 seconds and a minute. I can use __delay_cycles(xxxx) to achieve this but apparently doing so would defeat the purpose of the timer. This is my code.

#include <msp430.h>

#define RedLED BIT0
#define GreenLED BIT6

#define RedLEDToggle (P1OUT ^= RedLED)
#define GreenLEDToggle (P1OUT ^= GreenLED)

unsigned int counter = 0;


void main(void)
{
    WDTCTL = WDTPW | WDTHOLD;
    //WDTCTL = WDT_MDLY_32;

    P1DIR = RedLED | GreenLED;
    P1OUT = RedLED | GreenLED;

    TACTL = TASSEL_2 | ID_3 | MC_3 | TAIE;

    TACCR0 = 62500;

    _enable_interrupts();


    LPM1;
}

#pragma vector=TIMER0_A1_VECTOR

__interrupt void Timer_A(void)
{

if ( counter == 10)
{
switch (TAIV)
    {
    case 0x02: break;
    case 0x04: break;
    case 0x0A: RedLEDToggle | GreenLEDToggle;
        break;
    }
}
else
{
counter ++;
}       
}

回答1:


To achieve 10 second interrupt interval, you need to apply input divider to the timer. It is not possible to achieve 1 minute without peripheral support (see the other answers on how to implement that with a software counter).

The problem is that msp430 microcontrollers have 16-bit registers, not capable of holding numerical values larger than 65535. Using low-frequency oscillator running at 32768 Hz (as is typical - you don't provide any details about the hardware clock sources of your system, if they have a different frequency, please mention that) the register overflows once every 2 seconds unless an input divider is applied. The maximum value of input divider on MSP430x2xxx family MCUs is 8, so it's not possible to set a hardware timer more than 8 * 2 = 16 seconds in the future. Refer to MSP430x2xxx family user's guide for further details.

This code calls the interrupt once 10 seconds:

#include <msp430.h>

#define RedLED BIT0
#define GreenLED BIT6

#define RedLEDToggle (P1OUT ^= RedLED)
#define GreenLEDToggle (P1OUT ^= GreenLED)

// 10 seconds, assuming 32768 Hz ACLK source and divider 8
#define TIMER_PERIOD (10u * (32768 / 8))

void main(void)
{
    WDTCTL = WDTPW | WDTHOLD;

    P1DIR = RedLED | GreenLED;
    P1OUT = RedLED | GreenLED;

    // reset timer A config (not strictly needed)
    TACTL = TACLR;

    // ACLK as clock source, divider 8, continuous mode, interrupt enabled
    TACTL = TASSEL_1 | ID_3 | MC_2 | TAIE;

    // set the period
    TACCR1 = TIMER_PERIOD;

    // enable capture/compare interrupts for CCR1
    TACCTL1 = CCIE;

    _enable_interrupts();

    LPM1;
}

#pragma vector=TIMER0_A1_VECTOR

__interrupt void Timer_A(void)
{
    switch (TAIV) {
    case 0x02:
        // CCR1 interrupt
        RedLEDToggle;
        GreenLEDToggle;
        // set the time of the next interrupt
        TACCR1 += TIMER_PERIOD;
        break;
    }
}



回答2:


it is quite simple,\

You have a 1 second timer, that causes an interrupt every 1 second.

Your other times are multiples of that 1 second.

So, at the start of your program set a 10second counter to 0 and set a 1minute counter to 0.

At each 1 second interrupt, increment both counters.

Each time the 10 second counter steps from 9 to 10

  1. reset that counter to 0
  2. process the 10 second activity

Each time the 1 minute counter steps from 59 to 60

  1. reset that counter to 0
  2. process the 1 minute activity



回答3:


The header defines symbols for the TAIV values; use them.

The XxxLEDToggle defines are complete statements; you should not treat them as expressions by combining them with |.

The interrupt handler can be called from multiple sources. At the moment, your program does not enable any others, but this is likely to change, so you should run your TAIFG-specific code only when TAIFG actually was set.

Once you have reached the limit, you need to reset the counter back to zero.

When you have multiple timer intervals, you need multiple counters. Otherwise, the first reset will reset the counting for all intervals.

You need something like this:

static unsigned int counter_10 = 0;
static unsigned int counter_60 = 0;

#pragma vector=TIMER0_A1_VECTOR
static __interrupt void Timer_A0(void)
{
    switch (TA0IV) {
    case TA0IV_TACCR1: break;
    case TA0IV_TACCR2: break;
    case TA0IV_TAIFG:
        if (++counter_10 >= 10) {
            counter_10 = 0;
            RedLEDToggle;
        }
        if (++counter_60 >= 60) {
            counter_60 = 0;
            GreenLEDToggle;
        }
        break;
    }
}


来源:https://stackoverflow.com/questions/38425854/msp430g2553-timer-intervals

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!