Jump to content
43oh

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

 

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);
 
}
 
}
Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...