Tool/software: TI C/C++ Compiler
Hi all. I was trying to build this simple program where a user would press and hold a button interfaced with pin PD2 for as long as he wants the interval to be between a toggle of the built-in LED. PD2 is configured as WTIMER2B and the built-in LED (PF3) is toggled by TIMER0A timeout interrupt.
The button is attached to a pull-down resistor. So I am confident it is not floating.
The full program is below:
/* * blinky.c * * Created on: Nov 30, 2017 * Author: Solomon Tan * * Connections required: * None * * What this code does: Toggle the built-in LED using GPTM input edge timer to toggle the light for interval as long as how long the button is pressed. * */ #include <stdint.h> #include <stdbool.h> #include "inc/hw_memmap.h" #include "driverlib/gpio.h" #include "driverlib/sysctl.h" #include "driverlib/timer.h" #include "driverlib/interrupt.h" #include "inc/hw_ints.h" #include "driverlib/pin_map.h" #define PART_TM4C123GH6PM 1 uint32_t timeMeasured; _Bool isTimeMeasured = false; _Bool test = false; //************************************************************ // This WTIMER2B interrupt measures how long the PD2 was high. // The measured time is stored in variable timeMeasured. //************************************************************ void edgeInputTimerInt(void){ TimerIntClear(WTIMER2_BASE, TIMER_CAPB_EVENT); //acknowledge the signal edge interrupt uint32_t pinStatus = GPIOPinRead(GPIO_PORTD_BASE, GPIO_PIN_1) & 0x2; if(pinStatus){ GPIOPinWrite(GPIO_PORTF_BASE, GPIO_PIN_3, GPIO_PIN_3); } else { //read from timer and store in var timeEnd timeMeasured = TimerValueGet(WTIMER2_BASE, TIMER_B); isTimeMeasured = true; GPIOPinWrite(GPIO_PORTF_BASE, GPIO_PIN_3, 0x0); } } //************************************************************ // This TIMER0A interrupt toggles the built-in LED upon timeout. // Timeout depends on the value set by timeMeasured. //************************************************************ void timer0A_timeout (void){ TimerIntClear(TIMER0_BASE, TIMER_TIMA_TIMEOUT); GPIOPinWrite(GPIO_PORTF_BASE, GPIO_PIN_3, 0x8^(GPIOPinRead(GPIO_PORTF_BASE, GPIO_PIN_3) & 0x8)); TimerEnable(TIMER0_BASE, TIMER_A); } int main(void){ SysCtlClockSet(SYSCTL_SYSDIV_5 | SYSCTL_USE_PLL | SYSCTL_XTAL_16MHZ | SYSCTL_OSC_MAIN); //set the clock to 40MHz SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOF); while(!SysCtlPeripheralReady(SYSCTL_PERIPH_GPIOF)); GPIOPinTypeGPIOOutput(GPIO_PORTF_BASE, GPIO_PIN_3 | GPIO_PIN_1); //set PF1 and PF3 to output. (Actually only PF3 is needed as our LED) SysCtlPeripheralEnable(SYSCTL_PERIPH_TIMER0); while(!SysCtlPeripheralReady(SYSCTL_PERIPH_TIMER0)); TimerConfigure(TIMER0_BASE, TIMER_CFG_PERIODIC); //configure as a full-width periodic timer. One-shot only counts once and automatically disables the timer. TimerIntRegister(TIMER0_BASE, TIMER_A, timer0A_timeout); SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOD); while(!SysCtlPeripheralReady(SYSCTL_PERIPH_GPIOD)); SysCtlPeripheralEnable(SYSCTL_PERIPH_WTIMER2); while(!SysCtlPeripheralReady(SYSCTL_PERIPH_WTIMER2)); GPIOPinConfigure(GPIO_PD1_WT2CCP1); //Configure PD1 as wide GPTM GPIOPinTypeTimer(GPIO_PORTD_BASE, GPIO_PIN_1); //configure PD1 as echo pin - it triggers the timer module. GPIOPinTypeGPIOOutput(GPIO_PORTD_BASE, GPIO_PIN_2); //configure PD2 as output to be Trigger. TimerDisable(WTIMER2_BASE, TIMER_B); //disable timer before configuration TimerConfigure(WTIMER2_BASE, TIMER_CFG_SPLIT_PAIR | TIMER_CFG_B_CAP_TIME_UP); //Timer B is an input event timer. TimerControlEvent(WTIMER2_BASE, TIMER_B, TIMER_EVENT_BOTH_EDGES); // Configure the timer (TimerB) to time both edges. TimerIntClear(WTIMER2_BASE, TIMER_CAPB_EVENT); //clear any stray interrupt from the last run TimerIntEnable(WTIMER2_BASE, TIMER_CAPB_EVENT); //Generate interrupt upon signal edge TimerIntRegister(WTIMER2_BASE, TIMER_B, edgeInputTimerInt); //register echoPinTimerInt() as the ISR for WTimer 2B TimerEnable(WTIMER2_BASE, TIMER_B); //Enable the timer IntEnable(INT_WTIMER2B); //enable NVIC interrupt for WTimer 2B IntMasterEnable(); while(1){ if(isTimeMeasured){ //after the WTIMER2B interrupt successfully measures the time the PD2 pin was high for, we enable TIMER0 and disable WTIMER2B so the LED just toggles periodically. We do not change the timing anymore afterwards. isTimeMeasured = false; TimerLoadSet(TIMER0_BASE, TIMER_A, timeMeasured); TimerEnable(TIMER0_BASE, TIMER_A); TimerIntEnable(TIMER0_BASE, TIMER_TIMA_TIMEOUT); IntEnable(INT_TIMER0A); GPIOPinWrite(GPIO_PORTF_BASE, GPIO_PIN_1, GPIO_PIN_1); TimerDisable(WTIMER2_BASE, TIMER_B); } else { //This block of code is useless. But my program only worked after I added in this else block. Without it, even when isTimeMeasured is set to true by the WTIMER2B interrupt, if(isTimeMeasured){...} never gets run. GPIOPinWrite(GPIO_PORTF_BASE, GPIO_PIN_1, 0x0); } } } // Color LED(s) PortF // dark --- 0 // red R-- 0x02 // blue --B 0x04 // green -G- 0x08 // yellow RG- 0x0A // sky blue -GB 0x0C // white RGB 0x0E // pink R-B 0x06 // sky blue -GB 0x0C // white RGB 0x0E // pink R-B 0x06
The problem i am facing is at this section of code.
while(1){ if(isTimeMeasured){ //after the WTIMER2B interrupt successfully measures the time the PD2 pin was high for, we enable TIMER0 and disable WTIMER2B so the LED just toggles periodically. We do not change the timing anymore afterwards. isTimeMeasured = false; TimerLoadSet(TIMER0_BASE, TIMER_A, timeMeasured); TimerEnable(TIMER0_BASE, TIMER_A); TimerIntEnable(TIMER0_BASE, TIMER_TIMA_TIMEOUT); IntEnable(INT_TIMER0A); GPIOPinWrite(GPIO_PORTF_BASE, GPIO_PIN_1, GPIO_PIN_1); TimerDisable(WTIMER2_BASE, TIMER_B); } else { //This block of code is useless. But my program only worked after I added in this else block. Without it, even when isTimeMeasured is set to true by the WTIMER2B interrupt, if(isTimeMeasured){...} never gets run. GPIOPinWrite(GPIO_PORTF_BASE, GPIO_PIN_1, 0x0); } }
The block of code in if(isTimeMeasured){...} will not get executed i(not even once) f I do not include the else{...}. I do not understand why. My WTIMER2B interrupt runs fine. isTimeMeasured will therefore become true after the falling edge of the PD2 pin.
As long as isTimeMeasured becomes true, then if(isTimeMeasured){...} should get executed, no? I wrapped that block with while(1){...} so the program would wait for the WTIMER2B interrupt to set isTimeMeasured to true.
Could someone, maybe someone who had the same experience, share with me why this is so?
If the information I gave is incomplete, kindly let me know what others you need. Thank you.