Controlling LED Blink Speed MSP430FR6989 - Page 1
Forum section: electronics / general

author: Mattjd
author_rank: Regular Contributor
timestamp: October 07, 2017, 01:45:01 am
content: Code:#include <msp430.h>int button_counter;int main(void){WDTCTL = WDTPW | WDTHOLD; // stop watchdog timerPM5CTL0 &= ~LOCKLPM5; // Disable the GPIO power-on default high-impedance mode// to activate previously configured port settingsP1DIR |= BIT0; // Set P1.0 to output direction -- LEDP1DIR &= ~BIT1; // Set P1.1 to inputP1REN |= BIT1; // Enable Pull Up Resistor for pin1P1OUT |= BIT1; //SPECIFIED AS A PULLUP FOR P1.1TA0CCTL0 |= CCIE; // TACCR0 interrupt enabledTA0CCR0 = 3000; //Set value of CCR0 for comparisonTA0CTL |= TASSEL_1 + MC_1; //Pick TA0CLK & Set Counter to Up Mode_BIS_SR(LPM0_bits + GIE); // Enter LPM0 w/ interruptP1IES |= BIT1; //Have flag set on High to LowP1IFG &= ~BIT1; //Clear Pin 1.1 flag so no immediate interruptP1IE |= BIT1; //enable interrupts for Pin 1.1for(;;){while(!(BIT1 & P1IN)){button_counter++;}}}#pragma vector = TIMER0_A0_VECTOR__interrupt void TimerA0_ISR (void){P1OUT ^= BIT0;}#pragma vector = PORT1_VECTOR__interrupt void P1dot1_ISR(void){TA0CCR0 = button_counter;P1IFG &= ~BIT1; //Clear Pin 1.1 flag}I'm tasked (school) with controlling the LED blink rate on the MSP430FR6989. This has to been done using Timer A, and some kind of interrupts. My idea is to have LED1 (P1.0) every 250ms by default. This is done by entering TimerA0_ISR every time TA0R equals TA0CCR0 (which is 3000). At which point it sets XOR's P1.0 with 00000001.To control the LED blinks, I decided to have a forever loop in main.c, which upon pressing (and holding) of button S1 (Pin 1.1) it increments button_counter. On the falling edge of (ie button release) it enters P1.1_ISR and setings TA0CCR0 to the value of button_counter and resets P1.1 interrupt flag.This isn't happening though.My hypothesis are that it is either1.) TimerA is still running when I went P1.1_ISR and I am immediately being entered into TimerA0_ISR, therefore TA0CCR0 never gets set to button_counter.2.) Because the buttons are active high, I have something backwards and am never entteirng P1.1_ISR.I am unsure of #1, its just a guess, because I am so new to this.

author: Phoenix
author_rank: Frequent Contributor
timestamp: October 07, 2017, 02:52:06 am
content: I'm not sure how new you are to this, but you can use the debugger and step through or set break points in the code to see exactly whats happening.

author: Mattjd
author_rank: Regular Contributor
timestamp: October 07, 2017, 03:03:10 am
content: im extremely new

author: chicken
author_rank: Frequent Contributor
timestamp: October 07, 2017, 06:29:56 am
content: https://en.m.wikipedia.org/wiki/Volatile_(computer_programming)

author: Fred27
author_rank: Unknown
timestamp: October 07, 2017, 07:45:30 am
content: There are plenty of example that come with MSPWare - including how to use the timers. Start from a working example and adjust it one simple step at a time until it meets your requirements.

author: Mattjd
author_rank: Regular Contributor
timestamp: October 07, 2017, 06:05:19 pm
content: I realize this is trivial, but the LED blinks. What happening is that upon release of the button. Nothing happens.Just tell me, is my implementation even remotely possible? I'm trying to not rely on just copying code. Is there something completely wrong? Am I close at all?

author: Fred27
author_rank: Unknown
timestamp: October 07, 2017, 08:20:13 pm
content: Set a breakpoint on the ISR to see if it is called. (I'm assuming you're using CCS rather than that Arduino nonsense Energia.)Bear in mind that buttons bounce like crazy from a microcontroller point of view. It will open and close hundreds of times with each single press or release before it settles down.

author: Mattjd
author_rank: Regular Contributor
timestamp: October 07, 2017, 08:50:07 pm
content: Okay. So I hate to read up on breakpoints.But,I tried 1 breakpoint in my TimerA0_ISR, while in debugging and resumed, it suspended immediately, so that ISR is working. When I tried a breakpoint for P1dot1_ISR, didn't matter how many times i pressed that button, it never suspended.edit: to to be clear, I changed my code a little alsoCode:#include <msp430.h>int main(void){WDTCTL = WDTPW | WDTHOLD; // stop watchdog timerPM5CTL0 &= ~LOCKLPM5; // Disable the GPIO power-on default high-impedance mode// to activate previously configured port settingsP1DIR |= BIT0; // Set P1.0 to output direction -- LEDP1DIR &= ~BIT1; // Set P1.1 to inputP1REN |= BIT1; // Enable Pull Up Resistor for pin1P1OUT |= BIT1; //SPECIFIED AS A PULLUP FOR P1.1TA0CCTL0 |= CCIE; // TACCR0 interrupt enabledTA0CCR0 = 3000; //Set value of CCR0 for comparisonTA0CTL |= TASSEL_1 + MC_1; //Pick TA0CLK & Set Counter to Up Mode_enable_interrupt();P1IES |= BIT1; //Have flag set on High to LowP1IE &= ~BIT1; //enable interrupts for Pin 1.1P1IFG &= ~BIT1; //Clear Pin 1.1 flag so no immediate interruptfor(;;){while(!(BIT1 & P1IN)){if(TA1R == 0){TA1CTL = TASSEL_1 + MC_2;}}}}#pragma vector = TIMER0_A0_VECTOR__interrupt void TimerA0_ISR (void){P1OUT ^= BIT0;}#pragma vector = PORT1_VECTOR__interrupt void P1dot1_ISR(void){TA0CCR0 = TA1R;P1IFG &= ~BIT1; //Clear Pin 1.1 flag}I set a breakpoint for the while(button is pressed) and that caused a suspension when I pressed the button, so that is working.

author: Mattjd
author_rank: Regular Contributor
timestamp: October 07, 2017, 08:58:02 pm
content: Poo, okay. I had the interrupt for pin 1.1 disabled with this lineP1IE &= ~BIT1;I changed it toP1IE |= BIT1;I set a breakpoint for P1dot1_ISR and upon pressing the button, entered it. This means I have edge select backwards for the flag or I have a debouncing issue.Edit:And it was an edge select issue. So I had a mix up with that and how the buttons are active high.

author: Mattjd
author_rank: Regular Contributor
timestamp: October 07, 2017, 09:12:32 pm
content: Okay, so since I have gotten that working, thanks to you all.I have a question, when it comes to setting the vector of a ISRCode:#pragma vector = PORT1_VECTOR__interrupt void P1dot1_ISR(void){TA0CCR0 = button_count;P1IFG &= ~BIT1; //Clear Pin 1.1 flag}I have to use PORT1_VECTOR because I am using port 1 pin 1. The P1dod1_ISR is my choice and doesnt matter.What if I want another interrupt but for port 1 pin 2. I'm looking through the datasheet for FR6989 and am having trouble figuring out these vector names. My question is, where would I find them? Looking at the data sheet, the acronym for Port 1 Interrupt Vector is P1IV. Now the msp430.h represents that with PORT1_VECTOR.

author: Mattjd
author_rank: Regular Contributor
timestamp: October 07, 2017, 09:19:44 pm
content: Quote from: Mattjd on October 07, 2017, 09:12:32 pmTo reply to myself. I have to do them in the same ISR, but I have to differentiate them using if statements to check the status of P1IFG for the bits.

author: rsjsouza
author_rank: Super Contributor
timestamp: October 07, 2017, 11:41:07 pm
content: Just one highlight regarding your original implementation: the article linked by chicken above is extremely relevant - it helps explain why it didn't work originally.

author: Mattjd
author_rank: Regular Contributor
timestamp: October 08, 2017, 01:42:52 am
content: Code:#include <msp430.h>volatile unsigned int button_count;int main(void){WDTCTL = WDTPW | WDTHOLD; // stop watchdog timerPM5CTL0 &= ~LOCKLPM5; // Disable the GPIO power-on default high-impedance mode// to activate previously configured port settingsP1DIR |= BIT0; // Set P1.0 to output direction -- LEDP1DIR &= ~BIT1; // Set P1.1 to button inputP1REN |= BIT1; // Enable Pull Up Resistor for pin1.1P1OUT |= BIT1; //SPECIFIED AS A PULLUP FOR P1.1P1DIR &= ~BIT2; // Set P1.2 to button inputP1REN |= BIT2; // Enable Pull Up Resistor for pin1.2P1OUT |= BIT2; //SPECIFIED AS A PULLUP FOR P1.2TA0CCTL0 |= CCIE; // TACCR0 interrupt enabledTA0CCR0 = 3277; //Set value of TA0CCR0 for comparisonTA0CTL |= TASSEL_1 + MC_1; //Pick ACLK & Set Counter to Up ModeTA0CTL |= TACLR;TA1CCR1 = 512; //Set value of TA1CCR0 for comparisonP1IES |= BIT1; //Have flag set on High to LowP1IE |= BIT1; //enable interrupts for Pin 1.1P1IFG &= ~BIT1; //Clear Pin 1.1 flag so no immediate interruptP1IES |= BIT2; //Have flag set on High to LowP1IE |= BIT2; //enable interrupts for Pin 1.1P1IFG &= ~BIT2; //Clear Pin 1.1 flag so no immediate interrupt_enable_interrupt();}#pragma vector = TIMER0_A0_VECTOR__interrupt void TimerA0_ISR (void){P1OUT ^= BIT0;}#pragma vector = PORT1_VECTOR__interrupt void P1dot1_ISR(void){if(P1IFG & BIT1){if(TA1R > 0){TA0CCR0 = 3277*button_count; //slow down blink speedP1IES ^= BIT1; //Flip Edge SelectP1IFG &= ~BIT1; //Clear Pin 1.1 flag}else{TA1CTL |= TASSEL_1 + MC_1 + ID_3; //Pick ACLK & Set Counter to Up Mode & Divide ACLK by 8, so 4096TA1EX0 |= TAIDEX_7; //Divide ACLK further by 8 to 512 hzTA1CTL |= TACLR;P1IES ^= BIT1; //Flip Edge SelectP1IFG &= ~BIT1; //Clear Pin 1.1 flag}}if(P1IFG & BIT2){TA0CCR0 = 3277; //reset blink speedP1IFG &= ~BIT2; //Clear Pin 1.2 flag}}So, when I enter P1dot1_ISR, I want to start a clock and flip the edge select of port 1.1None of these are changing. I am setting a break point and viewing the registers. P1ES1 is still set to 1, despite me XOR'ing P1IES with BIT1. Timer A1 is not starting either.What I am trying to do is, upon pressing (and holding) of p1.1 (button s1), I enter p1.1_ISR, start timer A1. I then flip the edge select of P1.1. When I release the button, because I switched the edge select, I should re-enter the ISR and change the value of CCR0 to some multiple of its old self (basically for every second I hold down the button, the integer I multiply CCR0 by is increased by 1)

author: Cervisia
author_rank: Regular Contributor
timestamp: October 08, 2017, 08:39:32 am
content: QuotePORT1_VECTOR is for all pins of port 1. To find out which pin triggered the interrupt, you could check all IFG bits, but it would be easier to use the vector register:Code:#pragma vector = PORT1_VECTOR__interrupt void P1_ISR(void){switch (P1IV) { // this read also clears the corresponding P1IFG bitcase P1IV_P1IFG1:...break;case P1IV_P1IFG2:...break;}}

author: rsjsouza
author_rank: Super Contributor
timestamp: October 08, 2017, 11:38:47 am
content: Quote from: Mattjd on October 08, 2017, 01:42:52 amWhere is your while(1) or for(;at the end of main()?