Need help with this code, it is not creating any delay.
I tried simulating this code in Proteus.
#include <msp430.h>
#include <stdio.h>
#include <stdlib.h>
void XTL_ini();
void TimerA_ini();
void delay();
int main(void)
{
WDTCTL = WDTPW | WDTHOLD; // stop watchdog timer
XTL_ini();
TimerA_ini();
P1DIR=0XFF;
P2DIR=0XFF;
while(1)
{
P1OUT=BIT0;
delay();
}
}
void XTL_ini()
{
volatile int i=0;
BCSCTL1|=XT2OFF;
BCSCTL1&=~XTS;
BCSCTL3|=LFXT1S_0;
do{
IFG1&=~OFIFG;
for(i=5000;i;i--);
}while(IFG1 & OFIFG);
BCSCTL2|=SELM_3;
}
void TimerA_ini()
{
TA0CTL|=TASSEL_1; //32768
TA0CTL|=(ID_3+TAIE); //4096
}
void delay()
{
TA0CTL|=MC_1;
TA0CTL|=TACLR;
TA0CTL&=~TAIFG;
TA0CCR0=4.096;
if(TA0CTL&TAIFG)
{
TA0CTL|=MC_0;
TA0CTL|=TACLR;
TA0CTL&=~TAIFG;
}
}
3 Answers 3
Blink rate should be once per second with the following code. Easy to see. If you want to adjust it to run more often, change the "50" in the for-loop. This does NOT use interrupts, which I gather you do not want. No library code is called. Everything is below. (It's set for the MSP430F2013.)
/*
TIMER A2 DETAILS
It's probably best to include a diagram of how Timer A2 is being used.
The upper diagram helps show the timer counter's upward motion, over
time. The line made with text, showing peaks and valleys, represents
the timer counter, itself, as it counts upwards. The timer automatically
starts counting upwards when the counter reaches zero and automatically
resets back to zero when the counter reaches a value that is set into
TACCR0. In this application, TACCR0 is set just once and isn't adjusted
afterwards. It sets the basic cycle time for the LED pulsing.
TACCR0 ----> ..^......^......^......^......^.....
/| /| /| /| /| / Upward
/ | / | / | / | / | / Counter
/ | / | / | / | / | / Diagram
| / | / | / | / | / | /
| / | / | / | / | / | /
|/ |/ |/ |/ |/ |/
ZERO ...v......v......v......v......v......v.....
----|------|------|------|------|------|---
T T T T T T
A A A A A A Event Names
I I I I I I as Described
F F F F F F in the User's
G G G G G G Guide from TI
time ----> ----> ----> ----> ----> ----> ----> ---->
*/
int main( void ) {
WDTCTL= WDTPW | WDTHOLD;
P1DIR |= 0x01; // P1.0 is LED
BCSCTL1= CALBC1_16MHZ;
DCOCTL= CALDCO_16MHZ;
TACTL= MC_0 | TASSEL_2 | ID_3 | TACLR; // reset it, first.
TACCTL0= CM_0 | CCIS_2 | SCS | OUTMOD_1; // set the mode.
TACCR0= 19999; // 10ms intervals.
TACTL= MC_1 | TASSEL_2 | ID_3; // turn it on.
for ( ; ; ) {
P1OUT ^= 0x01; // using XOR toggles LED
for ( int i= 0; i < 50; ++i ) { // use (50)*10 ms per toggle
while ( (TACTL & TAIFG) == 0 ) // wait for the flag to set
;
TACTL &= ~TAIFG; // clear the flag now
}
}
return 0; // never reaches this point
}
See if that gets you something useful. But note that the above code does not "halt the msp430". That can be done. But it requires interrupts. And since you also wrote, "I want a delay using timer but with no interrupt i want to use a loop", I decided this is as far as I go for now.
I don't fully understand what you mean with "timer with polling condition".
Example 1: macro using a blocking delay
#include <msp430.h>
#include <intrinsics.h>
// here you have to specify the MCLK frequency in MHz
#define HWM_MCLK_FREQ_MHZ_DEF (16)
#if (HWM_MCLK_FREQ_MHZ_DEF == 1)
# define HWM_DELAY_US(x) __delay_cycles((uint32_t)(x))
#elif (HWM_MCLK_FREQ_MHZ_DEF == 2)
# define HWM_DELAY_US(x) __delay_cycles((uint32_t)(x) << 1)
#elif (HWM_MCLK_FREQ_MHZ_DEF == 4)
# define HWM_DELAY_US(x) __delay_cycles((uint32_t)(x) << 2)
#elif (HWM_MCLK_FREQ_MHZ_DEF == 8)
# define HWM_DELAY_US(x) __delay_cycles((uint32_t)(x) << 3)
#elif (HWM_MCLK_FREQ_MHZ_DEF == 16)
# define HWM_DELAY_US(x) __delay_cycles((uint32_t)(x) << 4)
#endif
#define HWM_DELAY_MS(x) HWM_DELAY_US((x) * 1000UL)
Example 2: using a timer interrupt
// here you have to specify the MCLK frequency in MHz
#define HWM_MCLK_FREQ_MHZ_DEF (16)
#define TIMER_A_INTERVAL_US (5000)
#if (HWM_MCLK_FREQ_MHZ_DEF == 1)
# define TIMER_A_CCR0 (TIMER_A_INTERVAL_US >> 3)
#elif (HWM_MCLK_FREQ_MHZ_DEF == 2)
# define TIMER_A_CCR0 (TIMER_A_INTERVAL_US >> 2)
#elif (HWM_MCLK_FREQ_MHZ_DEF == 4)
# define TIMER_A_CCR0 (TIMER_A_INTERVAL_US >> 1)
#elif (HWM_MCLK_FREQ_MHZ_DEF == 8)
# define TIMER_A_CCR0 (TIMER_A_INTERVAL_US)
#elif (HWM_MCLK_FREQ_MHZ_DEF == 16)
# define TIMER_A_CCR0 (TIMER_A_INTERVAL_US << 1)
#endif
void timer_a_init(void)
{
TA0CCTL0 |= CCIE;
TA0CTL = MC__STOP;
TA0CCR0 = TIMER_A_CCR0;
TA0CTL = TASSEL__SMCLK | MC__UP | ID__8 | TACLR; // clock source = SMCLK, counting mode = up, clock divider = 8
}
void timer_a_start(void)
{
TA0CCR0 = TIMER_A_CCR0;
TA0CTL = TASSEL__SMCLK | MC__UP | ID__8 | TACLR; // clock source = SMCLK, counting mode = up, clock divider = 8
}
/**
* The TimerA0 interrupt fires once every TIMER_A_INTERVAL_US us.
*/
#pragma vector = TIMER0_A0_VECTOR
__interrupt void TIMER0_A0_ISR(void)
{
// do stuff..
}
TA0CCR0=4.096;
This sets the register to the value 4. If you want the value 4096, write 4096
.
if(TA0CTL&TAIFG)
{
TA0CTL|=MC_0;
TA0CTL|=TACLR;
TA0CTL&=~TAIFG;
}
This code checks the interrupt bit once, and then continues execution.
If you want to wait for the interrupt bit to be set, you have to implement a wait:
while (!(TA0CTL&TAIFG))
;
TA0CTL&=~TAIFG;
...
Explore related questions
See similar questions with these tags.
delay()
function to provide any sort of delay, It should at least contain a loop (while, for). \$\endgroup\$