Jump to content
Sign in to follow this  
sheep

Tiva C PWM, interupt and UART problem

Recommended Posts

Hi all,
 
I am trying to control the PWM through UART usb serial at high speed, but the micro seems to pick up the input inconsistently(I am trying to create a 100 micro sec pulse using the PWM, but the micro sometimes does not pick up the input). So i am guessing the best way to do it is via interrupt(when the RX picks up any kind of input ), but I have no idea how to implement  one. Can someone provide an example code for such application please? Thanks in advance.
 
 
My Code:
 
 
#include <stdbool.h>
#include <stdint.h>
#include "inc/hw_memmap.h"
#include "driverlib/adc.h"
#include "driverlib/gpio.h"
#include "driverlib/sysctl.h"
#include "driverlib/adc.h"
#include "inc/hw_types.h"
#include "driverlib/debug.h"
 
//uart
#include "inc/hw_types.h"
#include "driverlib/pin_map.h"
#include "driverlib/uart.h"
 
//PWM
#include "driverlib/pwm.h"
#include "inc/hw_gpio.h"
#include "driverlib/rom.h"
#define PWM_FREQUENCY 100000// 100KHz
 
int main(void) {
 
uint32_t ui32ADC0Value[4];
volatile float ui32Avg;
volatile float ui32Voltage;
volatile char print[7];
volatile char power[1];
 
volatile uint32_t ui32Load;
volatile uint32_t ui32PWMClock;
 
//Set the clock
SysCtlClockSet(
SYSCTL_SYSDIV_64 | SYSCTL_USE_PLL | SYSCTL_OSC_MAIN
| SYSCTL_XTAL_16MHZ); //400MHz / 2 (PLL) /64 = 3.125MHZ
 
SysCtlPeripheralEnable(SYSCTL_PERIPH_ADC0); //Enable ADC0
SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOE); //Enable GPI0E
ADCReferenceSet(ADC0_BASE, ADC_REF_INT); //Set reference to the internal reference
GPIOPinTypeADC(GPIO_PORTE_BASE, GPIO_PIN_5); //Configure GPIO Port E Pin 5 as ADC
ADCSequenceDisable(ADC0_BASE, 1); //It is always a good practice to disable ADC prior                                                        //to usage ,else the ADC may not be accurate                                                               //   due to previous initializations
ADCSequenceConfigure(ADC0_BASE, 1, ADC_TRIGGER_PROCESSOR, 0); //Use the 1st Sample sequencer
ADCSequenceStepConfigure(ADC0_BASE, 1, 0, ADC_CTL_CH8);
ADCSequenceStepConfigure(ADC0_BASE, 1, 1, ADC_CTL_CH8);
ADCSequenceStepConfigure(ADC0_BASE, 1, 2, ADC_CTL_CH8);
ADCSequenceStepConfigure(ADC0_BASE, 1, 3,
ADC_CTL_CH8 | ADC_CTL_IE | ADC_CTL_END);
//Configure ADC to read from channel 8 ,trigger the interrupt to end data capture //
ADCSequenceEnable(ADC0_BASE, 1);   //Enable the ADC
 
 
//UART
SysCtlPeripheralEnable(SYSCTL_PERIPH_UART0);
SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOA);
GPIOPinConfigure(GPIO_PA0_U0RX);
GPIOPinConfigure(GPIO_PA1_U0TX);
GPIOPinTypeUART(GPIO_PORTA_BASE, GPIO_PIN_0 | GPIO_PIN_1);
UARTConfigSetExpClk(UART0_BASE, SysCtlClockGet(), 230400,
(UART_CONFIG_WLEN_8 | UART_CONFIG_STOP_ONE | UART_CONFIG_PAR_NONE));
 
//PWM
SysCtlPWMClockSet(SYSCTL_PWMDIV_1); // 3.125MHz
SysCtlPeripheralEnable(SYSCTL_PERIPH_PWM1);
SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOD);
GPIOPinTypePWM(GPIO_PORTD_BASE, GPIO_PIN_0);
GPIOPinConfigure(GPIO_PD0_M1PWM0);
ui32PWMClock = SysCtlClockGet();
ui32Load = (ui32PWMClock / PWM_FREQUENCY) - 1;
PWMGenConfigure(PWM1_BASE, PWM_GEN_0, PWM_GEN_MODE_DOWN);
PWMGenPeriodSet(PWM1_BASE, PWM_GEN_0, ui32Load);
PWMPulseWidthSet(PWM1_BASE, PWM_OUT_0, ui32Load); //100%
PWMOutputState(PWM1_BASE, PWM_OUT_0_BIT, false);
PWMGenEnable(PWM1_BASE, PWM_GEN_0);
 
while (1) {
ADCIntClear(ADC0_BASE, 1); //Clear interrupt to proceed to  data capture
ADCProcessorTrigger(ADC0_BASE, 1);   //Ask processor to trigger ADC
while (!ADCIntStatus(ADC0_BASE, 1, false)) { //Do nothing until interrupt is triggered
}
ADCSequenceDataGet(ADC0_BASE, 1, ui32ADC0Value); //pui32ADC0Value is the value read
ui32Avg = (ui32ADC0Value[0] + ui32ADC0Value[1] + ui32ADC0Value[2]
+ ui32ADC0Value[3]) / 4;
ui32Voltage = (ui32Avg / 4095) * 3.3;
sprintf(print, "%f", ui32Voltage);
UARTCharPut(UART0_BASE, print[0]);
UARTCharPut(UART0_BASE, print[1]);
UARTCharPut(UART0_BASE, print[2]);
UARTCharPut(UART0_BASE, print[3]);
UARTCharPut(UART0_BASE, print[4]);
UARTCharPut(UART0_BASE, print[5]);
UARTCharPut(UART0_BASE, print[6]);
UARTCharPut(UART0_BASE, '\n');
UARTCharPut(UART0_BASE, '\r');
//SysCtlDelay(10);
 
while (UARTCharsAvail(UART0_BASE)) {
int i = 0;
power = UARTCharGet(UART0_BASE);
i++;
if (power[0] == '1') {
PWMOutputState(PWM1_BASE, PWM_OUT_0_BIT, true);
SysCtlDelay(104);//104us pulse
PWMOutputState(PWM1_BASE, PWM_OUT_0_BIT, false);
} else {
PWMOutputState(PWM1_BASE, PWM_OUT_0_BIT, false);
}
}
}
 
}
 

 

Share this post


Link to post
Share on other sites

I got one step closer, but single pulse has turn to a train.

 

#include <stdbool.h>
#include <stdint.h>
#include "inc/hw_memmap.h"
#include "driverlib/adc.h"
#include "driverlib/gpio.h"
#include "driverlib/sysctl.h"
#include "driverlib/adc.h"
#include "inc/hw_types.h"
#include "driverlib/debug.h"
 
//uart
#include "inc/hw_types.h"
#include "driverlib/pin_map.h"
#include "driverlib/uart.h"
 
//interrupt
#include "inc/hw_ints.h"
#include "driverlib/interrupt.h"
 
//PWM
#include "driverlib/pwm.h"
#include "inc/hw_gpio.h"
#include "driverlib/rom.h"
#define PWM_FREQUENCY 100000//0 100KHz
 
void UARTIntHandler(void) {
uint32_t ui32Status;
ui32Status = UARTIntStatus(UART0_BASE, true); //get interrupt status
UARTIntClear(UART0_BASE, ui32Status); //clear the asserted interrupts
UARTCharsAvail(UART0_BASE); //loop while there are chars
PWMOutputState(PWM1_BASE, PWM_OUT_0_BIT, true);
SysCtlDelay(50); //50us
PWMOutputState(PWM1_BASE, PWM_OUT_0_BIT, false);
 
 
}
 
int main(void) {
 
uint32_t ui32ADC0Value[4];
volatile float ui32Avg;
volatile float ui32Voltage;
volatile char print[7];
volatile char power[1];
 
volatile uint32_t ui32Load;
volatile uint32_t ui32PWMClock;
 
//Set the clock
SysCtlClockSet(
SYSCTL_SYSDIV_64 | SYSCTL_USE_PLL | SYSCTL_OSC_MAIN
| SYSCTL_XTAL_16MHZ); //400MHz / 2 (PLL) /64 = 3.125MHZ
 
SysCtlPeripheralEnable(SYSCTL_PERIPH_ADC0); //Enable ADC0
SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOE); //Enable GPI0E
ADCReferenceSet(ADC0_BASE, ADC_REF_INT); //Set reference to the internal reference
GPIOPinTypeADC(GPIO_PORTE_BASE, GPIO_PIN_5); //Configure GPIO Port E Pin 5 as ADC
ADCSequenceDisable(ADC0_BASE, 1); //It is always a good practice to disable ADC prior                                                        //to usage ,else the ADC may not be accurate                                                               //   due to previous initializations
ADCSequenceConfigure(ADC0_BASE, 1, ADC_TRIGGER_PROCESSOR, 0); //Use the 1st Sample sequencer
ADCSequenceStepConfigure(ADC0_BASE, 1, 0, ADC_CTL_CH8);
ADCSequenceStepConfigure(ADC0_BASE, 1, 1, ADC_CTL_CH8);
ADCSequenceStepConfigure(ADC0_BASE, 1, 2, ADC_CTL_CH8);
ADCSequenceStepConfigure(ADC0_BASE, 1, 3,
ADC_CTL_CH8 | ADC_CTL_IE | ADC_CTL_END);
//Configure ADC to read from channel 8 ,trigger the interrupt to end data capture //
ADCSequenceEnable(ADC0_BASE, 1);   //Enable the ADC
 
//UART
SysCtlPeripheralEnable(SYSCTL_PERIPH_UART0);
SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOA);
GPIOPinConfigure(GPIO_PA0_U0RX);
GPIOPinConfigure(GPIO_PA1_U0TX);
GPIOPinTypeUART(GPIO_PORTA_BASE, GPIO_PIN_0 | GPIO_PIN_1);
UARTConfigSetExpClk(UART0_BASE, SysCtlClockGet(), 230400,
(UART_CONFIG_WLEN_8 | UART_CONFIG_STOP_ONE | UART_CONFIG_PAR_NONE));
 
//Interrupt
IntMasterEnable();
IntEnable(INT_UART0);
UARTIntEnable(UART0_BASE, UART_INT_RX | UART_INT_RT);
 
//PWM
SysCtlPWMClockSet(SYSCTL_PWMDIV_1); // 3.125MHz
SysCtlPeripheralEnable(SYSCTL_PERIPH_PWM1);
SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOD);
GPIOPinTypePWM(GPIO_PORTD_BASE, GPIO_PIN_0);
GPIOPinConfigure(GPIO_PD0_M1PWM0);
ui32PWMClock = SysCtlClockGet();
ui32Load = (ui32PWMClock / PWM_FREQUENCY) - 1;
PWMGenConfigure(PWM1_BASE, PWM_GEN_0, PWM_GEN_MODE_DOWN);
PWMGenPeriodSet(PWM1_BASE, PWM_GEN_0, ui32Load);
PWMPulseWidthSet(PWM1_BASE, PWM_OUT_0, ui32Load); //100%
PWMOutputState(PWM1_BASE, PWM_OUT_0_BIT, false);
PWMGenEnable(PWM1_BASE, PWM_GEN_0);
 
while (1) {
ADCIntClear(ADC0_BASE, 1); //Clear interrupt to proceed to  data capture
ADCProcessorTrigger(ADC0_BASE, 1);   //Ask processor to trigger ADC
while (!ADCIntStatus(ADC0_BASE, 1, false)) { //Do nothing until interrupt is triggered
}
ADCSequenceDataGet(ADC0_BASE, 1, ui32ADC0Value); //pui32ADC0Value is the value read
ui32Avg = (ui32ADC0Value[0] + ui32ADC0Value[1] + ui32ADC0Value[2]
+ ui32ADC0Value[3]) / 4;
ui32Voltage = (ui32Avg / 4095) * 3.3;
sprintf(print, "%f", ui32Voltage);
UARTCharPut(UART0_BASE, print[0]);
UARTCharPut(UART0_BASE, print[1]);
UARTCharPut(UART0_BASE, print[2]);
UARTCharPut(UART0_BASE, print[3]);
UARTCharPut(UART0_BASE, print[4]);
UARTCharPut(UART0_BASE, print[5]);
UARTCharPut(UART0_BASE, print[6]);
UARTCharPut(UART0_BASE, '\n');
UARTCharPut(UART0_BASE, '\r');
//SysCtlDelay(10);
 
}
 
}

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
Sign in to follow this  

×