Part Number:TM4C123GE6PM
Hello,
I am trying to determine the PWM pulse width value on 4 pins: PF0, PF1, PF2, PF3. Right now I am using PF1 to generate PWM (works great). Originally I used 32-bit timers Timer0 and Timer1 to read pulse width on PF0 and PF2 and that worked well. Since I need a total of 4 pins I decided to split Timer0 and Timer1 into split 16-bit timers. The moment I do that my code stops working. I am not getting the proper value anymore. Testing showed that the interrupt handler works properly, ISR determines which pin caused interrupt properly, pulse width calculation is correct. I think the timers setup causes problems. I would appreciate any help, thank you.
#include <stdint.h> #include <stdbool.h> #include "inc/hw_memmap.h" #include "inc/hw_types.h" #include "inc/hw_timer.h" #include "inc/tm4c123ge6pm.h" // Definitions for the interrupt and register assignments. #include "inc/hw_gpio.h" #include "driverlib/fpu.h" #include "driverlib/sysctl.h" #include "driverlib/rom.h" #include "driverlib/pin_map.h" #include "driverlib/uart.h" #include "driverlib/gpio.h" #include "driverlib/interrupt.h" #include "driverlib/timer.h" #include "driverlib/pwm.h" #include "utils/uartstdio.h" void ConfigureUART(void); void ConfigureTimers(void); void ConfigurePWM(void); void ConfigureGPIO(void); void IntDefaultHandler(void); void InputPF0(void); void InputPF1(void); void InputPF2(void); void InputPF3(void); void print_float(double v); uint32_t systemClock; // PF0 is tied to timer 0A volatile float pulseWidth0 = 0; volatile uint32_t timer0AValue = 0; // PF1 is tied to timer 0B volatile float pulseWidth1 = 0; volatile uint32_t timer0BValue = 0; // PF2 is tied to timer 1A volatile float pulseWidth2 = 0; volatile uint32_t timer1AValue = 0; // PF3 is tied to timer 1B volatile float pulseWidth3 = 0; volatile uint32_t timer1BValue = 0; double timerPeriod; int main(void) { volatile uint32_t load; volatile uint32_t dutyCycle; volatile uint32_t pwmClock; uint32_t pwmFrequency = 1000; // sets PWM frequency to Hz // System clock, 200/10 = 20 MHz SysCtlClockSet(SYSCTL_SYSDIV_10 | SYSCTL_USE_PLL | SYSCTL_XTAL_16MHZ |SYSCTL_OSC_MAIN); systemClock = SysCtlClockGet(); timerPeriod = (double)1/systemClock; // Configuring PWM clock SysCtlPWMClockSet(SYSCTL_PWMDIV_64); pwmClock = SysCtlClockGet() / 64; load = ((pwmClock/pwmFrequency) - 1); // setting PWM period dutyCycle = load/2; // 50% duty cycle ConfigurePWM(); ConfigureUART(); ConfigureTimers(); ConfigureGPIO(); // Set PWM period PWMGenPeriodSet(PWM1_BASE, PWM_GEN_2, load); // PWM duty cycle PWMPulseWidthSet(PWM1_BASE, PWM_OUT_5_BIT, dutyCycle); while(1) { PWMPulseWidthSet(PWM1_BASE, PWM_OUT_5, dutyCycle); } } void ConfigurePWM(void) { // Enable the peripherals SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOF); SysCtlPeripheralEnable(SYSCTL_PERIPH_PWM1); // Module 1 // Configure pins as PWM GPIOPinTypePWM(GPIO_PORTF_BASE, GPIO_PIN_1); GPIOPinConfigure(GPIO_PF1_M1PWM5); // Configure the PWM generator PWMGenConfigure(PWM1_BASE, PWM_GEN_2, PWM_GEN_MODE_DOWN); // Turn on output pin PWMOutputState(PWM1_BASE, PWM_OUT_5_BIT, true); // Enable PWM generator PWMGenEnable(PWM1_BASE, PWM_GEN_2); } // Have to attach PF1 void ConfigureGPIO(void) { // Configuring PF0, PF1, PF2, PF3 as inputs and attaching interrupt to them // PF1 is removed for now since it generates PWM SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOF); // Wait for the peripheral to be ready while(!SysCtlPeripheralReady(SYSCTL_PERIPH_GPIOF)){} // Unlock the pins on port F HWREG(GPIO_PORTF_BASE + GPIO_O_LOCK) = GPIO_LOCK_KEY; HWREG(GPIO_PORTF_BASE + GPIO_O_CR) = 0xFF; GPIOIntRegister(GPIO_PORTF_BASE, IntDefaultHandler); GPIOPinTypeGPIOInput(GPIO_PORTF_BASE, GPIO_PIN_0 | GPIO_PIN_2 | GPIO_PIN_3); GPIOIntTypeSet(GPIO_PORTF_BASE, GPIO_PIN_0 | GPIO_PIN_2 | GPIO_PIN_3, GPIO_BOTH_EDGES); GPIOIntEnable(GPIO_PORTF_BASE, GPIO_INT_PIN_0 | GPIO_INT_PIN_2 | GPIO_INT_PIN_3); } void ConfigureUART(void) { // Enable the GPIO Peripheral used by the UART. SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOA); // Enable UART0 SysCtlPeripheralEnable(SYSCTL_PERIPH_UART0); // Configure GPIO Pins for UART mode. GPIOPinConfigure(GPIO_PA0_U0RX); GPIOPinConfigure(GPIO_PA1_U0TX); GPIOPinTypeUART(GPIO_PORTA_BASE, GPIO_PIN_0 | GPIO_PIN_1); // Use the internal 16MHz oscillator as the UART clock source. UARTClockSourceSet(UART0_BASE, UART_CLOCK_PIOSC); // Initialize the UART for console I/O. UARTStdioConfig(0, 115200, 16000000); } void ConfigureTimers(void) { // Timer 0 is 32-bits split into 16-bit timer A and 16-bit timer B SysCtlPeripheralEnable(SYSCTL_PERIPH_TIMER0); while(!SysCtlPeripheralReady(SYSCTL_PERIPH_TIMER0)){} TimerConfigure(TIMER0_BASE, (TIMER_CFG_SPLIT_PAIR | TIMER_CFG_A_PERIODIC_UP | TIMER_CFG_B_PERIODIC_UP)); // Timer 1 is 32-bits split into 16-bit timer A and 16-bit timer B SysCtlPeripheralEnable(SYSCTL_PERIPH_TIMER1); while(!SysCtlPeripheralReady(SYSCTL_PERIPH_TIMER1)){} TimerConfigure(TIMER1_BASE, (TIMER_CFG_SPLIT_PAIR | TIMER_CFG_A_PERIODIC_UP | TIMER_CFG_B_PERIODIC_UP)); } void IntDefaultHandler(void) { uint32_t status = 0; status = GPIOIntStatus(GPIO_PORTF_BASE, true); // Clear interrupt flag GPIOIntClear(GPIO_PORTF_BASE,status); // Check which pin triggered the interrupt if((status & GPIO_INT_PIN_0) == GPIO_INT_PIN_0) { InputPF0(); } if((status & GPIO_INT_PIN_1) == GPIO_INT_PIN_1) { InputPF1(); } if((status & GPIO_INT_PIN_2) == GPIO_INT_PIN_2) { InputPF2(); } if((status & GPIO_INT_PIN_3) == GPIO_INT_PIN_3) { InputPF3(); } } void InputPF0(void) { // Check the input pin state if ( GPIOPinRead(GPIO_PORTF_BASE, GPIO_PIN_0) == GPIO_PIN_0) // rising edge { HWREG(TIMER0_BASE + TIMER_O_TAV) = 0; // load 0 to the timer TimerEnable(TIMER0_BASE,TIMER_A); //start timer to record } else // falling edge { TimerDisable(TIMER0_BASE,TIMER_A); //stop timer timer0AValue = TimerValueGet(TIMER0_BASE,TIMER_A); //record value pulseWidth0 = (double)(timerPeriod*timer0AValue*1000000); // PWM width in us } UARTprintf("\nTimer PF0 = %d\n", timer0AValue); print_float(pulseWidth0); } void InputPF1(void) { // Check the input pin state if ( GPIOPinRead(GPIO_PORTF_BASE, GPIO_PIN_1) == GPIO_PIN_1) // rising edge { HWREG(TIMER0_BASE + TIMER_O_TBV) = 0; // load 0 to the timer TimerEnable(TIMER0_BASE,TIMER_B); //start timer to record } else // falling edge { TimerDisable(TIMER0_BASE,TIMER_B); //stop timer timer0BValue = TimerValueGet(TIMER0_BASE,TIMER_B); //record value pulseWidth1 = (double)(timerPeriod*timer0BValue*1000000); // PWM width in us } UARTprintf("\nTimer PF1 = %d\n", timer0BValue); print_float(pulseWidth1); } void InputPF2(void) { // Check the input pin state if ( GPIOPinRead(GPIO_PORTF_BASE, GPIO_PIN_2) == GPIO_PIN_2) // rising edge { HWREG(TIMER1_BASE + TIMER_O_TAV) = 0; // load 0 to the timer TimerEnable(TIMER1_BASE,TIMER_A); //start timer to record } else // falling edge { TimerDisable(TIMER1_BASE,TIMER_A); //stop timer timer1AValue = TimerValueGet(TIMER1_BASE,TIMER_A); //record value pulseWidth2 = (double)(timerPeriod*timer1AValue*1000000); // PWM width in us } UARTprintf("\nTimer PF2 = %d\n", timer1AValue); print_float(pulseWidth2); } void InputPF3(void) { // Check the input pin state if ( GPIOPinRead(GPIO_PORTF_BASE, GPIO_PIN_3) == GPIO_PIN_3) // rising edge { HWREG(TIMER1_BASE + TIMER_O_TBV) = 0; // load 0 to the timer TimerEnable(TIMER1_BASE,TIMER_B); //start timer to record } else // falling edge { TimerDisable(TIMER1_BASE,TIMER_B); //stop timer timer1BValue = TimerValueGet(TIMER1_BASE,TIMER_B); //record value pulseWidth3 = (double)(timerPeriod*timer1BValue*1000000); // PWM width in us } UARTprintf("\nTimer PF3 = %d\n", timer1BValue); print_float(pulseWidth3); } void print_float(double v) { int decimal = 2; int i = 1; int intPart, fractPart; for (;decimal!=0; i*=10, decimal--); intPart = (int)v; fractPart = (int)((v-(double)(int)v)*i); if(fractPart < 0) fractPart *= -1; UARTprintf("%i.%i us\n\r", intPart, fractPart); }