Hello, this is my first time posting on this forums. I am using a TM4C Micro for acquiring data from a circuit with 3 analog signals. I have worked with this micro for some time now but I can't seem to get this to work properly, and I have browsed through this forum, and all the examples and documentation I could find. My first question is if the 12 shared channels of the ADC module correspond to the 12 analog input channels (PE0,PE1,PE2,PER 3tc..).
This is how I setup my ADC:
void ADCinit(void){
//Initialize ADC
SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOE); //Pin for ADC input
SysCtlPeripheralEnable(SYSCTL_PERIPH_ADC0); //ADC peripheral
//Enable Timer 0
SysCtlPeripheralEnable(SYSCTL_PERIPH_TIMER0);
//Pins used for ADC channels (3)
GPIOPinTypeADC(GPIO_PORTE_BASE, GPIO_PIN_3 | GPIO_PIN_2 | GPIO_PIN_1); //set GPIO_E3 for channel 1
//GPIOPinTypeADC(GPIO_PORTE_BASE, GPIO_PIN_2); //set GPIO_E2 for channel 2
//GPIOPinTypeADC(GPIO_PORTE_BASE, GPIO_PIN_1); //set GPIO_E1 for channel 3
ADCSequenceConfigure(ADC0_BASE, 0, ADC_TRIGGER_TIMER, 0); //sequencer 0
ADCSequenceConfigure(ADC0_BASE, 1, ADC_TRIGGER_TIMER, 1); //sequencer 1
ADCSequenceConfigure(ADC0_BASE, 2, ADC_TRIGGER_TIMER, 2); //sequencer 2
//sequencer 0
ADCSequenceStepConfigure(ADC0_BASE, 0, 0, ADC_CTL_CH1);
ADCSequenceStepConfigure(ADC0_BASE, 0, 1, ADC_CTL_CH1);
ADCSequenceStepConfigure(ADC0_BASE, 0, 2, ADC_CTL_CH1);
ADCSequenceStepConfigure(ADC0_BASE, 0, 3, ADC_CTL_CH1 | ADC_CTL_END);
//sequencer 1
ADCSequenceStepConfigure(ADC0_BASE, 1, 0, ADC_CTL_CH2);
ADCSequenceStepConfigure(ADC0_BASE, 1, 1, ADC_CTL_CH2);
ADCSequenceStepConfigure(ADC0_BASE, 1, 2, ADC_CTL_CH2);
ADCSequenceStepConfigure(ADC0_BASE, 1, 3, ADC_CTL_CH2 | ADC_CTL_END);
//sequencer 2
ADCSequenceStepConfigure(ADC0_BASE, 2, 0, ADC_CTL_CH1);
ADCSequenceStepConfigure(ADC0_BASE, 2, 1, ADC_CTL_CH1);
ADCSequenceStepConfigure(ADC0_BASE, 2, 2, ADC_CTL_CH1);
ADCSequenceStepConfigure(ADC0_BASE, 2, 3, ADC_CTL_CH1 | ADC_CTL_IE | ADC_CTL_END);
//
//Initialize Timer 0 to trigger an ADC conversion
//
TimerConfigure(TIMER0_BASE,TIMER_CFG_PERIODIC);
TimerLoadSet(TIMER0_BASE,TIMER_A,SysCtlClockGet()/1000); //5k sampling rate
TimerEnable(TIMER0_BASE, TIMER_A);
TimerControlTrigger(TIMER0_BASE,TIMER_A,true);
ADCSequenceEnable(ADC0_BASE,0);
ADCSequenceEnable(ADC0_BASE, 1);
ADCSequenceEnable(ADC0_BASE, 2);
ADCIntEnable(ADC0_BASE,2);
}
And in main()...
ADCinit();
//UARTprintf("ADC Sequence Initiated!\n");
ADCIntClear(ADC0_BASE,2);
ADCIntEnable(ADC0_BASE,2);
IntEnable(INT_ADC0SS2);
IntMasterEnable();
What Seems to happen when i try out the code is that the signal of channel1 follows channel2 (or vice-versa), and even if I don't connect the analog signal to one of the pins, they still give some value different then 0 or near 0. It seems that it is only reading one input signal, anyone of them, but I am not sure since it's pretty random behaviour. I just figure I'm doing somehting wrong, either with the ADC configuration or the interrupt.
I'm attatching my main.c
Thanks for the help!
EDIT: Added the reviewed code
// Plant Sensor ADC 3 Channels
//
// Ricardo Cabrita, ISR 2015
//****************************************************************************************************
// Includes ------------------------------------------------------------------------------------------
#include <stdint.h>
#include <stdbool.h>
#include <inttypes.h>
#include "inc/hw_ints.h"
#include "inc/hw_memmap.h"
#include "inc/hw_i2c.h"
#include "driverlib/fpu.h"
#include "driverlib/gpio.h"
#include "driverlib/interrupt.h"
#include "driverlib/i2c.h"
#include "driverlib/pin_map.h"
#include "driverlib/rom.h"
#include "driverlib/sysctl.h"
#include "driverlib/uart.h"
#include "driverlib/adc.h"
#include "driverlib/timer.h"
#include "utils/uartstdio.h"
#include "shtLib.h"
// Defines -------------------------------------------------------------------------------------------
#define LED_RED GPIO_PIN_1
#define LED_BLUE GPIO_PIN_2
#define LED_GREEN GPIO_PIN_3
//#define ch1 0001000000000000
// Variables -----------------------------------------------------------------------------------------
//uint16_t ui16ADC0Value[8] = {0,0,0,0,0,0,0,0};
uint16_t ui16Seq0Value[4] = {0,0,0,0},ui16Seq1Value[4] = {0,0,0,0}, ui16Seq2Value[4] = {0,0,0,0};
uint32_t averagedADC1,averagedADC2,averagedADC3;
uint32_t ui32Baud = 460800;
// Functions -----------------------------------------------------------------------------------------
void ADCinit(void){
//Initialize ADC
SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOE); //Pin for ADC input
SysCtlPeripheralEnable(SYSCTL_PERIPH_ADC0); //ADC peripheral
//Enable Timer 0
SysCtlPeripheralEnable(SYSCTL_PERIPH_TIMER0);
//Pins used for ADC channels (3)
GPIOPinTypeADC(GPIO_PORTE_BASE, GPIO_PIN_3 | GPIO_PIN_2 | GPIO_PIN_1); //set GPIO_E3 for channel 1
//GPIOPinTypeADC(GPIO_PORTE_BASE, GPIO_PIN_2); //set GPIO_E2 for channel 2
//GPIOPinTypeADC(GPIO_PORTE_BASE, GPIO_PIN_1); //set GPIO_E1 for channel 3
ADCSequenceConfigure(ADC0_BASE, 0, ADC_TRIGGER_TIMER, 0); //sequencer 0
ADCSequenceConfigure(ADC0_BASE, 1, ADC_TRIGGER_TIMER, 1); //sequencer 1
ADCSequenceConfigure(ADC0_BASE, 2, ADC_TRIGGER_TIMER, 2); //sequencer 2
//sequencer 0
ADCSequenceStepConfigure(ADC0_BASE, 0, 0, ADC_CTL_CH0);
ADCSequenceStepConfigure(ADC0_BASE, 0, 1, ADC_CTL_CH0);
ADCSequenceStepConfigure(ADC0_BASE, 0, 2, ADC_CTL_CH0);
ADCSequenceStepConfigure(ADC0_BASE, 0, 3, ADC_CTL_CH0 | ADC_CTL_END);
//sequencer 1
ADCSequenceStepConfigure(ADC0_BASE, 1, 0, ADC_CTL_CH1);
ADCSequenceStepConfigure(ADC0_BASE, 1, 1, ADC_CTL_CH1);
ADCSequenceStepConfigure(ADC0_BASE, 1, 2, ADC_CTL_CH1);
ADCSequenceStepConfigure(ADC0_BASE, 1, 3, ADC_CTL_CH1 | ADC_CTL_END);
//sequencer 2
ADCSequenceStepConfigure(ADC0_BASE, 2, 0, ADC_CTL_CH2);
ADCSequenceStepConfigure(ADC0_BASE, 2, 1, ADC_CTL_CH2);
ADCSequenceStepConfigure(ADC0_BASE, 2, 2, ADC_CTL_CH2);
ADCSequenceStepConfigure(ADC0_BASE, 2, 3, ADC_CTL_CH2 | ADC_CTL_IE | ADC_CTL_END);
//
//Initialize Timer 0 to trigger an ADC conversion
//
TimerConfigure(TIMER0_BASE,TIMER_CFG_PERIODIC);
TimerLoadSet(TIMER0_BASE,TIMER_A,SysCtlClockGet()/100000); // sampling rate
TimerEnable(TIMER0_BASE, TIMER_A);
TimerControlTrigger(TIMER0_BASE,TIMER_A,true);
ADCSequenceEnable(ADC0_BASE,0);
ADCSequenceEnable(ADC0_BASE, 1);
ADCSequenceEnable(ADC0_BASE, 2);
//ADCIntEnable(ADC0_BASE,0);
ADCIntEnable(ADC0_BASE,2);
//IntEnable(INT_ADC0SS1);
}
void ConfigureUART1(void){
// Enable the peripherals used by UART
SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOB);
SysCtlPeripheralEnable(SYSCTL_PERIPH_UART1);
// Set GPIO A0 and A1 as UART pins.
GPIOPinConfigure(GPIO_PB0_U1RX);
GPIOPinConfigure(GPIO_PB1_U1TX);
GPIOPinTypeUART(GPIO_PORTB_BASE, GPIO_PIN_0 | GPIO_PIN_1);
// Configure UART clock using UART utils
UARTClockSourceSet(UART1_BASE, UART_CLOCK_PIOSC);
UARTStdioConfig(1, ui32Baud, 16000000);
}
void ADC0IntHandler(void){
//short a,b;
uint32_t send1,send2;
uint32_t start = 122, checksum; // 0x00FF start byte
//Clear ADC interrupt here if interrupt is Light Cycle and small nr of instructions
//ADCIntClear(ADC0_BASE,1);
//get averaged data from the ADC
ADCSequenceDataGet(ADC0_BASE,0,ui16Seq0Value);
ADCSequenceDataGet(ADC0_BASE,1,ui16Seq1Value);
ADCSequenceDataGet(ADC0_BASE,2,ui16Seq2Value);
//Chan1 value
averagedADC1 = (ui16Seq0Value[0] + ui16Seq0Value[1] + ui16Seq0Value[2] + ui16Seq0Value[3])/4;
//Chan2 value
averagedADC2 = (ui16Seq1Value[0] + ui16Seq1Value[1] + ui16Seq1Value[2] + ui16Seq1Value[3])/4;
//Chan3 value
averagedADC3 = (ui16Seq2Value[0] + ui16Seq2Value[1] + ui16Seq2Value[2] + ui16Seq2Value[3])/4;
//Debugging sequence
/*averagedADC1 = 1122;
averagedADC2 = 1123;
averagedADC3 = 1124; //Ab4FdTF
//start = 65;
//end of Debugging sequence */
UARTprintf("0 - Chan0: %d | Chan1: %d | Chan2: %d\n", ui16Seq0Value[0], ui16Seq1Value[0],ui16Seq2Value[0]); //for debugg
UARTprintf("1 - Chan0: %d | Chan1: %d | Chan2: %d\n", ui16Seq0Value[1], ui16Seq1Value[1],ui16Seq2Value[1]);
UARTprintf("2 - Chan0: %d | Chan1: %d | Chan2: %d\n", ui16Seq0Value[2], ui16Seq1Value[2],ui16Seq2Value[2]);
UARTprintf("3 - Chan0: %d | Chan1: %d | Chan2: %d\n", ui16Seq0Value[3], ui16Seq1Value[3],ui16Seq2Value[3]);
//check sum
checksum = averagedADC1 ^ averagedADC2 ^ averagedADC3;
//prepare stream to send, 7 bytes in send1 and send2
// start byte + chan1 + chan2 + chan3 + checksum:
send1 = averagedADC2 << 20; //put chan2 in the enf of send1
send1 = send1 + (averagedADC1<<8);//add chan1 and leave room for start byte
send1 = send1 + start; //add start byte to stream
send2 = checksum << 12; //put checksum and leave space for chan3
send2 = send2 + averagedADC3; //add chan3
//UARTprintf("AV1: %d | AV2: %d | AV3: %d\n",averagedADC1,averagedADC2,averagedADC3);
//send...
/*UARTCharPut(UART1_BASE,send1); //start byte
UARTCharPut(UART1_BASE,send1 >> 8); //least sig byte of chan1
UARTCharPut(UART1_BASE,send1 >> 16); //4 most sig bits of chan1 and least sig 4 bits of chan2
UARTCharPut(UART1_BASE,send1 >> 24); //most sig byte of chan2
UARTCharPut(UART1_BASE,send2); // least sig byte of chan3
UARTCharPut(UART1_BASE,send2 >> 8); //4 most sig bits of chan3 and least sig 4 bits of checksum
UARTCharPut(UART1_BASE,send2 >> 16); //most sig byte of checksum
//UARTCharPut(UART1_BASE,10); // \n for DEBUGGG */
//otherwise clear here (might loose some data points)
//ADCIntClear(ADC0_BASE,0);
ADCIntClear(ADC0_BASE,2);
}
// Main ----------------------------------------------------------------------------------------------
int main(void){
// Enable lazy stacking
FPULazyStackingEnable();
// Set the system clock to run at 20Mhz off PLL with external crystal as reference.
SysCtlClockSet(SYSCTL_SYSDIV_10 | SYSCTL_USE_PLL | SYSCTL_XTAL_16MHZ | SYSCTL_OSC_MAIN);
// Initialize the UART and write status.
ConfigureUART1();
//UARTprintf("ADC CRASH OVERRIDE!! Using clock %d\n", SysCtlClockGet());
// Enable LEDs
//SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOF);
//GPIOPinTypeGPIOOutput(GPIO_PORTF_BASE, LED_RED|LED_BLUE|LED_GREEN);
//Initialize ADC
ADCinit();
//UARTprintf("ADC Sequence Initiated!\n");
ADCIntClear(ADC0_BASE,2);
ADCIntEnable(ADC0_BASE,2);
IntEnable(INT_ADC0SS2);
IntMasterEnable();
// Create print variables
while(1){
//forever!
}
}