Quantcast
Channel: Forums - Recent Threads
Viewing all articles
Browse latest Browse all 262198

TM4C123GE6PM: Reading PWM pulse width

$
0
0

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);
}


Viewing all articles
Browse latest Browse all 262198

Trending Articles