This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

TM4C123G ADC using variable POT

Other Parts Discussed in Thread: TM4C123GH6PM

Hiiii all

i want to use ADC on this processor. My code is listed below. i am using Uvision keil. but code is not working. kindly help..

#include "ADCSWTrigger.h"
#include "../tm4c123gh6pm.h"
#include "PLL.h"

void DisableInterrupts(void); // Disable interrupts
void EnableInterrupts(void); // Enable interrupts
long StartCritical (void); // previous I bit, disable interrupts
void EndCritical(long sr); // restore I bit to previous value
void WaitForInterrupt(void); // low power mode

volatile unsigned long ADCvalue;
// The digital number ADCvalue is a representation of the voltage on PE4
// voltage ADCvalue
// 0.00V 0
// 0.75V 1024
// 1.50V 2048
// 2.25V 3072
// 3.00V 4095
int main(void){unsigned long volatile delay;
PLL_Init(); // 80 MHz
ADC0_InitSWTriggerSeq3_Ch1(); // ADC initialization PE2/AIN1
SYSCTL_RCGC2_R |= SYSCTL_RCGC2_GPIOF; // activate port F
delay = SYSCTL_RCGC2_R;
GPIO_PORTF_DIR_R |= 0x04; // make PF2 out (built-in LED)
GPIO_PORTF_AFSEL_R &= ~0x04; // disable alt funct on PF2
GPIO_PORTF_DEN_R |= 0x04; // enable digital I/O on PF2
// configure PF2 as GPIO
GPIO_PORTF_PCTL_R = (GPIO_PORTF_PCTL_R&0xFFFFF0FF)+0x00000000;
GPIO_PORTF_AMSEL_R = 0; // disable analog functionality on PF
while(1){
GPIO_PORTF_DATA_R |= 0x04; // profile
ADCvalue = ADC0_InSeq3();
GPIO_PORTF_DATA_R &= ~0x04;
for(delay=0; delay<100000; delay++){};
}
}

another file

#include "../tm4c123gh6pm.h"

// This initialization function sets up the ADC according to the
// following parameters. Any parameters not explicitly listed
// below are not modified:
// Max sample rate: <=125,000 samples/second
// Sequencer 0 priority: 1st (highest)
// Sequencer 1 priority: 2nd
// Sequencer 2 priority: 3rd
// Sequencer 3 priority: 4th (lowest)lab123\

// SS3 triggering event: software trigger
// SS3 1st sample source: Ain1 (PE2)
// SS3 interrupts: flag set on completion but no interrupt requested
void ADC0_InitSWTriggerSeq3_Ch1(void){ volatile unsigned long delay;
SYSCTL_RCGC2_R |= 0x00000010; // 1) activate clock for Port E
delay = SYSCTL_RCGC2_R; // allow time for clock to stabilize
GPIO_PORTE_DIR_R &= ~0x04; // 2) make PE2 input
GPIO_PORTE_AFSEL_R |= 0x04; // 3) enable alternate function on PE2
GPIO_PORTE_DEN_R &= ~0x04; // 4) disable digital I/O on PE2
GPIO_PORTE_AMSEL_R |= 0x04; // 5) enable analog function on PE2
SYSCTL_RCGC0_R |= 0x00010000; // 6) activate ADC0
delay = SYSCTL_RCGC2_R;
SYSCTL_RCGC0_R &= ~0x00000300; // 7) configure for 125K
ADC0_SSPRI_R = 0x0123; // 8) Sequencer 3 is highest priority
ADC0_ACTSS_R &= ~0x0008; // 9) disable sample sequencer 3
ADC0_EMUX_R &= ~0xF000; // 10) seq3 is software trigger
ADC0_SSMUX3_R = (ADC0_SSMUX3_R&0xFFFFFFF0)+1; // 11) channel Ain1 (PE2)
ADC0_SSCTL3_R = 0x0006; // 12) no TS0 D0, yes IE0 END0
ADC0_ACTSS_R |= 0x0008; // 13) enable sample sequencer 3
}


//------------ADC0_InSeq3------------
// Busy-wait Analog to digital conversion
// Input: none
// Output: 12-bit result of ADC conversion
unsigned long ADC0_InSeq3(void){
unsigned long result;
ADC0_PSSI_R = 0x0008; // 1) initiate SS3
while((ADC0_RIS_R&0x08)==0){}; // 2) wait for conversion done
result = ADC0_SSFIFO3_R&0xFFF; // 3) read result
ADC0_ISC_R = 0x0008; // 4) acknowledge completion
return result;
}

  • Hello Prashant,

    Can you be more descriptive as to what is not working? Also why not use TIVAWare API's (there is an example already for ADC in TivWare example folder), it would simpler and more readable.

    Regards

    Amit

  • hii amit

    i am not getting ADC output in digital format in watch window. and in CCS examples, one code is given but that is for temperature sensor. I want to give an voltage input. can you please provide the file. thank you.

    Regards

    prashant

  • One suspects that (likely) homework assignment disallows use of driverlib.  (how delightful - for those "helpers" here...)

    Does not famed, "Please provide the file" strongly signal that real, "learning" is not top priority/interest?

  • respected cb1

    my main project is not the programming. I am using launchpad just to get pwm pulses of varied duty. my main aim is to do some research on control of pmbldc motor. i think you got my point.

    regards

    prashant

  • Hello Prashant,

    I would differ on the examples given. If you check TivaWare there is an ADC example with Analog Channel.

    C:\ti\TivaWare_C_Series-2.1.0.12573\examples\peripherals\adc\single_ended.c

    Regards

    Amit

  • Prashant Surana said:
    my main project is not the programming.

    Mon ami - with that now stated - Amit's (and my, long past, and many times restated) guidance is to abandon (immediately) "Direct Register" and employ the driverlib ADC functions.  In the past - w/in StellarisWare - existed a very clear, simple yet effective file, "Single-Ended.c." 

    Use of Direct Register forces so much additional complexity upon you - and upon all, "helpers."  Driverlib - and the many examples (i.e. driverlib\examples\peripherals\adc) should well guide (and speed) your quest... 

    Many interns & new hires @ my firm "broke in" w/that - to read your pot that file should prove ideal...  (and do remember to confine the pot's output to 3V3, max.)   Bon chance...

  • hii amit,

    I am posting my code. I am unable to vary pwm duty. i am varying pot but pwm duty is fixed with initial value. kindly help.

    #include <stdint.h>
    #include <stdbool.h>
    #include "inc/hw_gpio.h"
    #include "inc/hw_types.h"
    #include "inc/hw_memmap.h"
    #include "driverlib/sysctl.h"
    #include "driverlib/pin_map.h"
    #include "driverlib/gpio.h"
    #include "driverlib/pwm.h"
    #include "driverlib/adc.h"
    #include "driverlib/sysctl.h"

    int main(void)
    {
    unsigned long ulPeriod;

    unsigned int pui32ADC0Value[1];
    pui32ADC0Value[1]=1000;
    //Set the clock
    SysCtlClockSet(SYSCTL_SYSDIV_1 | SYSCTL_USE_OSC | SYSCTL_OSC_MAIN | SYSCTL_XTAL_16MHZ);

    //Configure PWM Clock to match system
    SysCtlPWMClockSet(SYSCTL_PWMDIV_1);

    // Enable the peripherals used by this program.
    SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOF);
    SysCtlPeripheralEnable(SYSCTL_PERIPH_PWM1); //The Tiva Launchpad has two modules (0 and 1). Module 1 covers the LED pins
    ulPeriod = SysCtlClockGet() / 20000; //PWM frequency 200HZ

    //Configure PF1,PF2,PF3 Pins as PWM
    GPIOPinConfigure(GPIO_PF1_M1PWM5);
    GPIOPinConfigure(GPIO_PF2_M1PWM6);
    GPIOPinConfigure(GPIO_PF3_M1PWM7);
    GPIOPinTypePWM(GPIO_PORTF_BASE, GPIO_PIN_1 | GPIO_PIN_2 | GPIO_PIN_3);

    //Configure PWM Options
    //PWM_GEN_2 Covers M1PWM4 and M1PWM5
    //PWM_GEN_3 Covers M1PWM6 and M1PWM7 See page 207 4/11/13 DriverLib doc
    PWMGenConfigure(PWM1_BASE, PWM_GEN_2, PWM_GEN_MODE_UP_DOWN | PWM_GEN_MODE_NO_SYNC);
    PWMGenConfigure(PWM1_BASE, PWM_GEN_3, PWM_GEN_MODE_UP_DOWN | PWM_GEN_MODE_NO_SYNC);

    //Set the Period (expressed in clock ticks)
    PWMGenPeriodSet(PWM1_BASE, PWM_GEN_2, ulPeriod);
    PWMGenPeriodSet(PWM1_BASE, PWM_GEN_3, ulPeriod);

    // The ADC0 peripheral must be enabled for use.
    //
    SysCtlPeripheralEnable(SYSCTL_PERIPH_ADC0);

    //
    // For this example ADC0 is used with AIN0 on port E3.
    // The actual port and pins used may be different on your part, consult
    // the data sheet for more information. GPIO port E needs to be enabled
    // so these pins can be used.
    // TODO: change this to whichever GPIO port you are using.
    //
    SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOE);

    //
    // Select the analog ADC function for these pins.
    // Consult the data sheet to see which functions are allocated per pin.
    // TODO: change this to select the port/pin you are using.
    //
    GPIOPinTypeADC(GPIO_PORTE_BASE, GPIO_PIN_3);

    //
    // Enable sample sequence 3 with a processor signal trigger. Sequence 3
    // will do a single sample when the processor sends a signal to start the
    // conversion. Each ADC module has 4 programmable sequences, sequence 0
    // to sequence 3. This example is arbitrarily using sequence 3.
    //
    ADCSequenceConfigure(ADC0_BASE, 3, ADC_TRIGGER_PROCESSOR, 0);

    //
    // Configure step 0 on sequence 3. Sample channel 0 (ADC_CTL_CH0) in
    // single-ended mode (default) and configure the interrupt flag
    // (ADC_CTL_IE) to be set when the sample is done. Tell the ADC logic
    // that this is the last conversion on sequence 3 (ADC_CTL_END). Sequence
    // 3 has only one programmable step. Sequence 1 and 2 have 4 steps, and
    // sequence 0 has 8 programmable steps. Since we are only doing a single
    // conversion using sequence 3 we will only configure step 0. For more
    // information on the ADC sequences and steps, reference the datasheet.
    //
    ADCSequenceStepConfigure(ADC0_BASE, 3, 0, ADC_CTL_CH0 | ADC_CTL_IE |
    ADC_CTL_END);

    //
    // Since sample sequence 3 is now configured, it must be enabled.
    //
    ADCSequenceEnable(ADC0_BASE, 3);

    //
    // Clear the interrupt status flag. This is done to make sure the
    // interrupt flag is cleared before we sample.
    //
    ADCIntClear(ADC0_BASE, 3);

    //
    // Sample AIN0 forever. Display the value on the console.
    //
    while(1)
    {
    //Set PWM duty-50% (Period /2)
    PWMPulseWidthSet(PWM1_BASE, PWM_OUT_5,ulPeriod/(4095/pui32ADC0Value[1]));
    PWMPulseWidthSet(PWM1_BASE, PWM_OUT_6,ulPeriod/2);
    PWMPulseWidthSet(PWM1_BASE, PWM_OUT_7,ulPeriod/2);

    // Enable the PWM generator
    PWMGenEnable(PWM1_BASE, PWM_GEN_2);
    PWMGenEnable(PWM1_BASE, PWM_GEN_3);

    // Turn on the Output pins
    PWMOutputState(PWM1_BASE, PWM_OUT_5_BIT |PWM_OUT_6_BIT|PWM_OUT_7_BIT, true);
    //
    // Trigger the ADC conversion.
    //
    ADCProcessorTrigger(ADC0_BASE, 3);

    //
    // Wait for conversion to be completed.
    //
    while(!ADCIntStatus(ADC0_BASE, 3, false))
    {
    }

    //
    // Clear the ADC interrupt flag.
    //
    ADCIntClear(ADC0_BASE, 3);

    //
    // Read ADC Value.
    //
    ADCSequenceDataGet(ADC0_BASE, 3, pui32ADC0Value);
    }
    }

  • Hello Prashant,

    The ADC Read is declared as an array of 1 element and your code is referring to the second element       pui32ADC0Value[1] when setting the PWM Pulse width

            PWMPulseWidthSet(PWM1_BASE, PWM_OUT_5,ulPeriod/(4095/pui32ADC0Value[1]));

    Both initialization and the above API are using the wrong variable.

    I cannot test it on my EK-TM4C123 right now, but I believe this to be the root-cause of the issue.

    Regards

    Amit

  • hii amit

    When I am declaring that variable as unsigned int then i am getting error listed below

    argument of type "unsigned int" is incompatible with parameter of type "uint32_t *" main.c /try1 line 134 C/C++ Problem

    regards

    prashant

  • Hello Prashant,

    I am using the same code as yours in CCSv5.5 and it does not give any such error.

    Also I modified the code as attached... The first thing before even doing PWM DC change is to make sure that the ADC reads the correct value. Is that happening? You can add UART Console Print to see the loop running 3.3V conversion when you connect PE3 to 3.3V and 0V conversion when connected to GND.

    Regrds

    Amit

  • hii amit

    i am also not getting any error when i am declaring variable as array of one element. but with a variable without array, i am getting error. and yes adc is working correctly. but i need to use breakpoint to see the result. without breakpoint , it is giving error "identifier not found"

    regards

    prashant

  • Hello Prashant,

    That is good that ADC conversion is happening fine. Did you check that the result of the PWM conversion is then correctly getting updated in the PWM Compare registers as per the equation

    PWMPulseWidthSet(PWM1_BASE, PWM_OUT_5,ulPeriod/(4095/pui32ADC0Value[0]));

    Do note that I have not got an updated code so I am pasting the line from the previous post with modification

    Regards

    Amit

  • hii amit

    sorry for late response.

    actually here this value "(4095/pui32ADC0Value[0]" must be an integer. but from calculation, most of the time it will not be an integer. so i am not getting output pwm pulse. I have tried assigning it float but it is not accepting.

     

    regards

    prashant

  • Hello Prashant,

    Why not? If the pui32ADC0Value[0] is 4095 the operation would result in 1. If the value read is 2047 then the result would be 2, ie only integer will be maintained by the equation.

    To get the fractional part the operation has to be 4095%pui32ADC0Value[0]

    Regards

    Amit

  • hii amit

    thank you so much. finally its working. i am able to vary duty with pot. 

    #include <stdint.h>
    #include <stdbool.h>
    #include "inc/hw_gpio.h"
    #include "inc/hw_types.h"
    #include "inc/hw_memmap.h"
    #include "driverlib/sysctl.h"
    #include "driverlib/pin_map.h"
    #include "driverlib/gpio.h"
    #include "driverlib/pwm.h"
    #include "driverlib/adc.h"
    #include "driverlib/sysctl.h"

    int main(void)
    {
    unsigned long ulPeriod,a;
    uint32_t pui32ADC0Value[1];
    float d;
    pui32ADC0Value[0]=1000;

    //Set the clock
    SysCtlClockSet(SYSCTL_SYSDIV_1 | SYSCTL_USE_OSC | SYSCTL_OSC_MAIN | SYSCTL_XTAL_16MHZ);

    //Configure PWM Clock to match system
    SysCtlPWMClockSet(SYSCTL_PWMDIV_1);

    // Enable the peripherals used by this program.
    SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOF);
    SysCtlPeripheralEnable(SYSCTL_PERIPH_PWM1); //The Tiva Launchpad has two modules (0 and 1). Module 1 covers the LED pins
    ulPeriod = SysCtlClockGet() / 20000; //PWM frequency 200HZ

    //Configure PF1,PF2,PF3 Pins as PWM
    GPIOPinConfigure(GPIO_PF1_M1PWM5);
    GPIOPinConfigure(GPIO_PF2_M1PWM6);
    GPIOPinConfigure(GPIO_PF3_M1PWM7);
    GPIOPinTypePWM(GPIO_PORTF_BASE, GPIO_PIN_1 | GPIO_PIN_2 | GPIO_PIN_3);

    //Configure PWM Options
    //PWM_GEN_2 Covers M1PWM4 and M1PWM5
    //PWM_GEN_3 Covers M1PWM6 and M1PWM7 See page 207 4/11/13 DriverLib doc
    PWMGenConfigure(PWM1_BASE, PWM_GEN_2, PWM_GEN_MODE_UP_DOWN | PWM_GEN_MODE_NO_SYNC);
    PWMGenConfigure(PWM1_BASE, PWM_GEN_3, PWM_GEN_MODE_UP_DOWN | PWM_GEN_MODE_NO_SYNC);

    //Set the Period (expressed in clock ticks)
    PWMGenPeriodSet(PWM1_BASE, PWM_GEN_2, ulPeriod);
    PWMGenPeriodSet(PWM1_BASE, PWM_GEN_3, ulPeriod);
    d=pui32ADC0Value[0]/4095.0;
    a=d*ulPeriod;
    //Set PWM duty-50% (Period /2)
    PWMPulseWidthSet(PWM1_BASE, PWM_OUT_5,a);
    PWMPulseWidthSet(PWM1_BASE, PWM_OUT_6,a);
    PWMPulseWidthSet(PWM1_BASE, PWM_OUT_7,ulPeriod/2);

    // Enable the PWM generator
    PWMGenEnable(PWM1_BASE, PWM_GEN_2);
    PWMGenEnable(PWM1_BASE, PWM_GEN_3);

    // Turn on the Output pins
    PWMOutputState(PWM1_BASE, PWM_OUT_5_BIT |PWM_OUT_6_BIT|PWM_OUT_7_BIT, true);

    // The ADC0 peripheral must be enabled for use.
    //
    SysCtlPeripheralEnable(SYSCTL_PERIPH_ADC0);

    //
    // For this example ADC0 is used with AIN0 on port E3.
    // The actual port and pins used may be different on your part, consult
    // the data sheet for more information. GPIO port E needs to be enabled
    // so these pins can be used.
    // TODO: change this to whichever GPIO port you are using.
    //
    SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOE);

    //
    // Select the analog ADC function for these pins.
    // Consult the data sheet to see which functions are allocated per pin.
    // TODO: change this to select the port/pin you are using.
    //
    GPIOPinTypeADC(GPIO_PORTE_BASE, GPIO_PIN_3);

    //
    // Enable sample sequence 3 with a processor signal trigger. Sequence 3
    // will do a single sample when the processor sends a signal to start the
    // conversion. Each ADC module has 4 programmable sequences, sequence 0
    // to sequence 3. This example is arbitrarily using sequence 3.
    //
    ADCSequenceConfigure(ADC0_BASE, 3, ADC_TRIGGER_PROCESSOR, 0);

    //
    // Configure step 0 on sequence 3. Sample channel 0 (ADC_CTL_CH0) in
    // single-ended mode (default) and configure the interrupt flag
    // (ADC_CTL_IE) to be set when the sample is done. Tell the ADC logic
    // that this is the last conversion on sequence 3 (ADC_CTL_END). Sequence
    // 3 has only one programmable step. Sequence 1 and 2 have 4 steps, and
    // sequence 0 has 8 programmable steps. Since we are only doing a single
    // conversion using sequence 3 we will only configure step 0. For more
    // information on the ADC sequences and steps, reference the datasheet.
    //
    ADCSequenceStepConfigure(ADC0_BASE, 3, 0, ADC_CTL_CH0 | ADC_CTL_IE |
    ADC_CTL_END);

    //
    // Since sample sequence 3 is now configured, it must be enabled.
    //
    ADCSequenceEnable(ADC0_BASE, 3);

    //
    // Clear the interrupt status flag. This is done to make sure the
    // interrupt flag is cleared before we sample.
    //
    ADCIntClear(ADC0_BASE, 3);

    //
    // Sample AIN0 forever. Display the value on the console.
    //
    while(1)
    {
    //
    // Trigger the ADC conversion.
    //
    ADCProcessorTrigger(ADC0_BASE, 3);

    //
    // Wait for conversion to be completed.
    //
    while(!ADCIntStatus(ADC0_BASE, 3, false))
    {
    }

    //
    // Clear the ADC interrupt flag.
    //
    ADCIntClear(ADC0_BASE, 3); //put breakpoint here

    //
    // Read ADC Value.
    //
    ADCSequenceDataGet(ADC0_BASE, 3, pui32ADC0Value);


    d=pui32ADC0Value[0]/4095.0;
    a=d*ulPeriod;
    //Set PWM duty-50% (Period /2)
    PWMPulseWidthSet(PWM1_BASE, PWM_OUT_5,a);
    PWMPulseWidthSet(PWM1_BASE, PWM_OUT_6,a);

    }
    }

    regards

    prashant