ADC on MSP430 stuck on either timer delay or cunable to take ADC unless I remove all timer and push button interrupt - timer

I have used MSP430 to write a custom blinking code with adjustable frequency. I use an ADC to adjust the frequency but I have been having issues with the ADC portion of the code being stuck while I use it with timer 0 interrupts and a Port 1 interrupt. But if I remove them from the program the ADDC works fine. Could anyone help me point out my error or help me understand the mechanism with which I could have the ADC running again? Attached below is a portion of my code:
float updatealphaFreq(){
int af_update = 0;
if(p_count>0)
{
WDTCTL = WDTPW | WDTHOLD; // stop watchdog timer
BCSCTL1= CALBC1_1MHZ;
DCOCTL = CALDCO_1MHZ;
ADC12CTL0 = SHT0_2 + ADC12ON; // Set sampling time, turn on ADC12
ADC12CTL1 = SHP + SHS0; // Use sampling timer
ADC12IE = 0x01; // Enable interrupt
ADC12CTL0 |= ENC; // Conversion enabled
P6DIR &= ~0x01; // P6.0, i/p
P6SEL |= 0x01; // P6.0-ADC option select
P1DIR |= 0x01; // P1.0 output-LED
//lcdInit();// Initialize LCD
//lcdSetText("Select Frequency ", 0, 0);
//lcdClear();
while(1){
//__enable_interrupt();
ADC12CTL0 |= ADC12SC ;
//delayMS(1000);
//lcdSetText("Value of a_freq: ", 0, 0);
float i = 0;
af_update = ADC12MEM0/100;
i = af_update *0.325;
//lcdSetInt(i*100, 0,1);
//delay_ms(10000);
//lcdSetText(" ", 0, 1);
}
ADC12CTL0 &=~ENC;
ADC12CTL0 &=~(REFON + ADC12ON);
ADC12CTL0 =0;
}
p_count = 0;
while((P1IN & BIT3)!=BIT3);
return af_update;
}
#pragma vector=PORT1_VECTOR
__interrupt void Port_1(void)
{
switch (P1IFG & BUTTON) {
case BUTTON:
P1IFG = P1IFG & ~BUTTON;
// flip the LED output
P1OUT ^= LED1;
P1OUT ^= LED2;
break;
default:
break;
}
return;
}
//Timer ISR
#pragma vector = TIMER0_A0_VECTOR
__interrupt void Timer_A_CCR0_ISR(void)
{
OFCount++; //Increment Over-Flow Counter
}

Related

Can I enable a button toggle interrupt to pause my timer? MSP432 -- Code Composer Studio

Hello! I am working on a project where I have to enable a timer that counts up every tenth of a second and outputs my times in binary. Independently, the timer itself works perfectly. However, I want to add a function to use my internal board switches (P1.4 and P1.1) to stop and start my timer, respectively. In any case, I am working on a MSP432P401R board. Thank you beforehand! My code:
#include "msp.h"
int sec = 0, tensec = 0, min = 0; //time stuff
int A = 1;
void Initiate(){
//internal switches -- negative logic, lazy to do outside stuff
//1.1 -- start related stuff
//1.4 -- stop relted stuff
P1->DIR &= ~0x12;
P1->REN |= 0x12;
P1->OUT |= 0x12;
//asking for start LED
P1->DIR |= BIT0;
P1->OUT &= ~BIT0;
//lights for status -- onboard
P2->DIR |= 0x07;
P2->OUT &= ~0x07;
//minute lights
P5->DIR |= 0x03;
P5->OUT &= ~0x03;
//seconds lights -- 6 LEDs
P4->DIR |= 0x3F;
P4->OUT &= ~0x3F;
//tens of sec
P6->DIR |= BIT0;
P6->OUT &= ~BIT0;
}
int main(void) {
WDT_A->CTL = WDT_A_CTL_PW | WDT_A_CTL_HOLD; // Stop WDT
// Configure GPIO
Initiate();
// Enable & configure the SysTick Timer Module
SysTick->CTRL |= SysTick_CTRL_CLKSOURCE_Msk | SysTick_CTRL_ENABLE_Msk;
// SysTick->LOAD = 0x60000 - 1; // Period = 0x60000
SysTick->LOAD = 300000; // Period = tenth of a second
SysTick->VAL = 0x01; // Clear value by writing any value
SysTick->CTRL |= SysTick_CTRL_TICKINT_Msk; // Enable interrupt
// Enable global interrupt
__enable_irq();
SCB->SCR |= SCB_SCR_SLEEPONEXIT_Msk; // Sleep on exit from ISR
__DSB(); // Ensure SLEEPONEXIT takes effect immediately
while (1)
__sleep();
} // End of main
// Interrupt service routine (ISR) invoked when SysTick down counter reaches 0.
void SysTick_Handler(void)
{
A = P1->IN & BIT1;
if((!A)){ //pressing the switch will make it pause
}else{
P6->OUT ^= BIT0; // Toggle tens of sec light
tensec++;
if(tensec == 10){
sec++;
P4->OUT &=~0x3F; //refresh seconds
P4->OUT |= sec;
tensec = 0; //restart it
if(sec == 60){
sec = 0; //restart secs
min++;
P5->OUT &= ~0x3F; //refresh
P5->OUT |= min;
}
}
}
}

TM4C1294XL blink LED's in binary pattern

i am trying to produce the series of binary patterns corresponding to rising
unsigned integers using four LEDs in ports N anf F of the microcontroller. the LED pattern should display as follows:
0x00: (LLLL)
0x01: (LLLH)
0x02: (LLHL)
…
0x0F: (HHHH)
0x10: (LLLL)
0x11: (LLLH)
...
i cant seem to get the LED's to blink in this order in my while loop using a counter, how can i make this work? the microcontroller is a TM4C1294XL texas instruments and the program is in c code.
int main(void)
{
/**
* GPIO initialization
*/
SYSCTL_RCGCGPIO_R |= 0x00001020 ; // enable port N & F
while((SYSCTL_RCGCGPIO_R & 0x00001020) == 0); // wait until the port is available
GPIO_PORTN_DEN_R = 0x03; // PN(0,1) enable
GPIO_PORTN_DIR_R = 0x03; // PN(0,1) output
GPIO_PORTF_AHB_DEN_R = 0x11; // PF(0,4) enable
GPIO_PORTF_AHB_DIR_R = 0x11; // PF(0,4) output
/**
* TIMER initialization: compare mode
*/
SYSCTL_RCGCTIMER_R |= (1<<1);
while (!(SYSCTL_PRTIMER_R & (1<<1)) == 0);
TIMER1_CTL_R &= ~(1<<0); // stop timer
TIMER1_CFG_R = 0x4; // 16-bit
TIMER1_TAMR_R |= 0x12; // periodic, upwards counting
TIMER1_TAPR_R = 245-1; // prescalar value: timeout=1s, f(cpu)=16MHz
TIMER1_TAILR_R = 65307-1; // interval load value: timeout=1s, f(cpu)=16MHz
TIMER1_CTL_R |= (1<<0); // start timer
unsigned int counter = 0;
while(1)
{
counter++;
while (GPIO_PORTN_DATA_R & counter == 0);
GPIO_PORTN_DATA_R = counter;
while (GPIO_PORTF_AHB_DATA_R & counter == 0);
GPIO_PORTF_AHB_DATA_R = counter;
while((TIMER1_RIS_R & (1<<0))==0);
TIMER1_ICR_R |= (1<<0);
GPIO_PORTN_DATA_R = 0x00;
GPIO_PORTF_AHB_DATA_R = 0x00;
}
return 0;
}

msp430 timer interrupts for wirting a delay method

What is wrong with the following code, as it does not work as expected
#include <msp430.h>
void initTimer_A(void);
void delayMS(int msecs);
unsigned int OFCount;
int main(void)
{
WDTCTL = WDTPW + WDTHOLD; //Stop watchdog timer
P1DIR |= BIT0; //Configure P1.0 as Output
//Set MCLK = SMCLK = 1MHz
BCSCTL1 = CALBC1_1MHZ;
DCOCTL = CALDCO_1MHZ;
initTimer_A();
_enable_interrupt();
while(1)
{
P1OUT |= BIT0; //Drive P1.0 HIGH - LED1 ON
delayMS(500); //Wait 0.5 Secs
P1OUT &= ~BIT0; //Drive P1.0 LOW - LED1 OFF
delayMS(500); //Wait 0.5 Secs
}
}
initializing the inittimer_A A, seems to be not functioning according to my knowledge
void initTimer_A(void)
{
//Timer0_A3 Configuration
TACCR0 = 0; //Initially, Stop the Timer
TACCTL0 |= CCIE; //Enable interrupt for CCR0.
TACTL = TASSEL_2 + ID_0 + MC_1; //Select SMCLK, SMCLK/1, Up Mode
}
void delayMS(int msecs)
{
OFCount = 0; //Reset Over-Flow counter
TACCR0 = 1000-1; //Start Timer, Compare value for Up Mode to get 1ms delay per loop
//Total count = TACCR0 + 1. Hence we need to subtract 1.
while(i<=msecs);
TACCR0 = 0; //Stop Timer
}
//Timer ISR
#pragma vector = TIMER0_A0_VECTOR
__interrupt void Timer_A_CCR0_ISR(void)
{
OFCount++; //Increment Over-Flow Counter
}
Once the delays are introduced as normal way as delay_cycle() program work without any error, very much appreciated if someone can correct the code..…….

C - button pressed once registered twice - MSP430

I wanted to create a game where a player has to repeat a random pattern of flashing lights with the keys on the MSP430. The random pattern is created with an ADC - 0 represents the red light on P1.0 blinking and 1 the green light on P4.7.
After playing it myself I noticed that sometimes when I press a button once it is registered as pressed twice.
For example: The pattern is red/red/red/green (0/0/0/1) then pressing the left button twice and the right button once is enough because the first push of the left button is registered as two pushes.
I reduced the code of the game to a smaller program in which it's only necessary to repeate the pattern of the example above:
#include <msp430.h>
int pattern[4];
unsigned int index = 0;
unsigned int button;
unsigned int buttonPressed = 0;
void Initialize_LED(void)
{
P4DIR = P4DIR | 0x80;
P4OUT &= ~0x80;
P1DIR = P1DIR | 0x01;
P1OUT &=~0x01;
pattern[0] = 0;
pattern[1] = 0;
pattern[2] = 0;
pattern[3] = 1;
}
void Initialize_Buttons(void){
P1REN |= 0x02;
P1OUT |= 0x02;
P2REN |= 0x02;
P2OUT |= 0x02;
P1IFG &= ~0x02;
P2IFG &= ~0x02;
P1IE |= 0x02;
P2IE |= 0x02;
//Timer:----------------------------
TA1CTL = TASSEL_1+ID_0+MC_2+TACLR; //
TA1R = 40000; //
// ----------------
_BIS_SR(GIE);
}
void main(void)
{
WDTCTL = WDTPW + WDTHOLD;
Initialize_LED();
Initialize_Buttons();
int done = 0;
while(done == 0){
if(buttonPressed == 1){
if(pattern[index] != button){
P1OUT ^= 0x01;
done++; //wrong button --> green light on
} else {
index++;
buttonPressed = 0;
if (index == 4){
done++;
}
}
}
}
P1OUT ^= 0x01; // correct pattern --> both lights on
P4OUT ^= 0x80;
}
#pragma vector=PORT1_VECTOR // ----------- Interrupt Service Routine -----------
__interrupt void Port1_Interrupt (void) {
buttonPressed = 1;
if (P1IFG&0x02){
button = 1;
P1IE &= ~0x02;
TA1CTL |= TAIE;
TA1R = 50000;
}
}
#pragma vector=PORT2_VECTOR // ----------- Interrupt Service Routine -----------
__interrupt void Port2_Interrupt (void) {
buttonPressed = 1;
if (P2IFG&0x02){
button = 0;
P2IE &= ~0x02;
TA1CTL |= TAIE;
TA1R = 50000;
}
}
#pragma vector=TIMER1_A1_VECTOR // Timer1_A3 Interrupt Vector(TAIV) handler
__interrupt void TIMER1_A1_ISR(void)
{
switch (__even_in_range(TA1IV, 14))
{
case 0: break;
case 2: break;
case 4: break;
case 6: break;
case 8: break;
case 10: break;
case 12: break;
case 14:
P1IFG &= ~0x02;
P1IE |= 0x02;
P2IFG &= ~0x02;
P2IE |= 0x02;
TA1CTL &= ~TAIE;
break;
default: break;
}
}
I went through the code with the debugger but can't find the reason why this keeps happening. Is someone able to help me? Thanks for your time!
Every mechanical contact generate pulses - bounces during switch ON and also OFF. You need create an debouncing filter for this.
My proposals is for you to completely avoid interrupts for reading status of buttons.
Best way to debounce buttons by SW is to sample it with sampling time longer than button generate bounce pulses (it is generally about 1-10ms).
You can do it by reading actual status of buttons every 10ms and compare it with previous status. Then you will have completely debounced button(s).
I use this method in many projects, where I don't need HW filter and same principle is used for example in any PC keyboard, where HW filter is not possible to add, because all the buttons are multiplexed, but this is better to discus on https://electronics.stackexchange.com

AVR Butterfly - Timer reuse after internal oscillator calibration

I am calibrating the AVR Butterfly internal oscillator for being able to use USART, based on the sample code provided by AVR (see code below). As I also wanted to use two timer-controlled servo motors, I am wondering whether it is possible to reuse 16-bit timer 1 after the calibration process - I tried resetting the TCCR1A/B but it did not work out (code also below). I hope you can help me out with this.
void OSCCAL_Calibrate(void){
unsigned char calibrate = 0;
int temp;
unsigned char tempL;
CLKPR = (1<<CLKPCE); // set Clock Prescaler Change Enable
// set prescaler = 8, Inter RC 8Mhz / 8 = 1Mhz
CLKPR = (1<<CLKPS1) | (1<<CLKPS0);
TIMSK2 = 0; //disable OCIE2A and TOIE2
ASSR = (1<<AS2); //select asynchronous operation of timer2 (32,768kHz)
OCR2A = 200; // set timer2 compare value
TIMSK0 = 0; // delete any interrupt sources
TCCR1B = (1<<CS10); // start timer1 with no prescaling
TCCR2A = (1<<CS20); // start timer2 with no prescaling
while((ASSR & 0x01) | (ASSR & 0x04)); //wait for TCN2UB and TCR2UB to be cleared
delayMs(1000); // wait for external crystal to stabilise
while(!calibrate)
{
cli(); // disable global interrupt
TIFR1 = 0xFF; // delete TIFR1 flags
TIFR2 = 0xFF; // delete TIFR2 flags
TCNT1H = 0; // clear timer1 counter
TCNT1L = 0;
TCNT2 = 0; // clear timer2 counter
while ( !(TIFR2 & (1<<OCF2A)) ); // wait for timer2 compareflag
TCCR1B = 0; // stop timer1
sei(); // enable global interrupt
if ( (TIFR1 & (1<<TOV1)) )
{
temp = 0xFFFF; // if timer1 overflows, set the temp to 0xFFFF
}else
{ // read out the timer1 counter value
tempL = TCNT1L;
temp = TCNT1H;
temp = (temp << 8);
temp += tempL;
}
if (temp > 6250)
OSCCAL--; // the internRC oscillator runs to fast, decrease the OSCCAL
else if (temp < 6120)
OSCCAL++; // the internRC oscillator runs to slow, increase the OSCCAL
else
calibrate = 1; // the interRC is correct
TCCR1B = (1<<CS10); // start timer1
}
}
void motorInit(){
// reset timer 1
TCCR1A = 0;
TCCR1B = 0;
// initialize Servo Pins
DDRB |= (1<<PB5) | (1<<PB6);
ICR1H = ICR_VALUE >> 8;
ICR1L = ICR_VALUE & (TOP_VALUE);
// reset OCRs
setServoSpeed(0, 0);
setServoSpeed(1, 0);
// Set Timer mode (PWM Phase & Freq. correct, clear on compare match)
// and prescaler (8)
TCCR1A = ((1<<COM1A1) | (1<<COM1B1));
TCCR1B = ((1<<WGM13) | (0<<CS12) | (1<<CS11) | (0<<CS10));
}
Maybe you can check code which I used for a project while ago, but you should take care that I decreased the system frequency to 7.3768 MHz for 56700 baudrate, which maybe you need to adjust.
void OSCCAL_Calibrate(void)
{
uint8_t LoopCount = (0x7F / 2);
ATOMIC_BLOCK(ATOMIC_RESTORESTATE)
{
// Make sure all clock division is turned off (8MHz RC clock)
CLKPR = (1 << CLKPCE);
CLKPR = 0x00;
// Inital OSCCAL of half its maximum
OSCCAL = (0x7F / 2);
// Disable timer interrupts
TIMSK1 = 0;
TIMSK2 = 0;
// Set timer 2 to asyncronous mode (32.768KHz crystal)
ASSR = (1 << AS2);
// Ensure timer 1 control register A is cleared
TCCR1A = 0;
// Start both counters with no prescaling
TCCR1B = (1 << CS10);
TCCR2A = (1 << CS20);
// Wait until timer 2's external 32.768KHz crystal is stable
while (ASSR & ((1 << TCN2UB) | (1 << TCR2UB) | (1 << OCR2UB)));
// Clear the timer values
TCNT1 = 0;
TCNT2 = 0;
while (LoopCount--)
{
// Wait until timer 2 overflows
while (!(TIFR2 & (1 << TOV2)));
// Stop timer 1 so it can be read
TCCR1B = 0x00;
// Check timer value against ideal constant
if (TCNT1 > OSCCAL_TARGETCOUNT) // Clock is running too fast
OSCCAL--;
else if (TCNT1 < OSCCAL_TARGETCOUNT) // Clock is running too slow
OSCCAL++;
// Clear timer 2 overflow flag
TIFR2 |= (1 << TOV2);
Check this out!

Resources