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.

TM4C123GXL: ADC and UART help

I am trying to sample a signal coming in at 33 kHz, and then send it to the PC using UART so that I can see a plot of my signal. How do I configure my ADC to sample at the minimum sample rate(66 kHz) and then send the data over the UART.

#include <stdint.h>
#include <stdbool.h>
#include "inc/tm4c123gh6pm.h"
#include "inc/hw_memmap.h"
#include "inc/hw_types.h"
#include "driverlib/sysctl.h"
#include "driverlib/gpio.h"
#include "driverlib/interrupt.h"
#include "driverlib/timer.h"
#include "driverlib/uart.h"
#include "driverlib/adc.h"
#include "driverlib/debug.h"
#include "driverlib/fpu.h"
#include "inc/hw_uart.h"
#include "utils/uartstdio.h"



int ADCvalue;
float Voltage;

void PLL_Init(void){
  // 0) Use RCC2
  SYSCTL_RCC2_R |=  0x80000000;  // USERCC2
  // 1) bypass PLL while initializing
  SYSCTL_RCC2_R |=  0x00000800;  // BYPASS2, PLL bypass
  // 2) select the crystal value and oscillator source
  SYSCTL_RCC_R = (SYSCTL_RCC_R &~0x000007C0)   // clear XTAL field, bits 10-6
                 + 0x00000540;   // 10101, configure for 16 MHz crystal
  SYSCTL_RCC2_R &= ~0x00000070;  // configure for main oscillator source
  // 3) activate PLL by clearing PWRDN
  SYSCTL_RCC2_R &= ~0x00002000;
  // 4) set the desired system divider
  SYSCTL_RCC2_R |= 0x40000000;   // use 400 MHz PLL
  SYSCTL_RCC2_R = (SYSCTL_RCC2_R&~ 0x1FC00000)  // clear system clock divider
                  + (4<<22);      // configure for 80 MHz clock
  // 5) wait for the PLL to lock by polling PLLLRIS
  while((SYSCTL_RIS_R&0x00000040)==0){};  // wait for PLLRIS bit
  // 6) enable use of PLL by clearing BYPASS
  SYSCTL_RCC2_R &= ~0x00000800;
}

void ADC0_InitSWTriggerSeq3_Ch9(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 PE4 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 &= ~0x000F;       // 11) clear SS3 field
  ADC0_SSMUX3_R += 9;             //    set channel Ain9 (PE4)
  ADC0_SSCTL3_R = 0x0006;         // 12) no TS0 D0, yes IE0 END0
  ADC0_ACTSS_R |= 0x0008;         // 13) enable sample sequencer 3
}

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

void UART_Init(void){            // should be called only once
  SYSCTL_RCGC1_R |= 0x00000002;  // activate UART1
  SYSCTL_RCGC2_R |= 0x00000004;  // activate port C
  UART1_CTL_R &= ~0x00000001;    // disable UART
  UART1_IBRD_R = 43;     // IBRD = int(80,000,000/(16*115,200)) = int(43.40278)
  UART1_FBRD_R = 26;     // FBRD = round(0.40278 * 64) = 26
  UART1_LCRH_R = 0x00000070;  // 8 bit, no parity bits, one stop, FIFOs
  UART1_CTL_R |= 0x00000001;     // enable UART
  GPIO_PORTC_AFSEL_R |= 0x30;    // enable alt funct on PC5-4
  GPIO_PORTC_DEN_R |= 0x30;      // configure PC5-4 as UART1
  GPIO_PORTC_PCTL_R = (GPIO_PORTC_PCTL_R&0xFF00FFFF)+0x00220000;
  GPIO_PORTC_AMSEL_R &= ~0x30;   // disable analog on PC5-4
}

void UART_OutChar(unsigned int data){
  while((UART1_FR_R&0x0020) != 0);      // wait until TXFF is 0
  UART1_DR_R = data;
}

/*void OutVolt(unsigned long n){  // each integer means 0.01V
  UART_OutChar(0x30�+n/100);      // digit to the left of the decimal
  n = n%100;                     // 0 to 99
  UART_OutChar('.');             // decimal point
  UART_OutChar(0x30�+n/10);       // tenths digit
  n = n%10;                      // 0 to 9
  UART_OutChar(0x30�+n);          // hundredths digit
  UART_OutChar('V');}            // units
*/
int main(void){
	PLL_Init(); //Set up system clock

	ADC0_InitSWTriggerSeq3_Ch9(); // Initialize ADC

	UART_Init(); // Initialize UART

	//UARTprintf("Hello");


while(1){
	ADCvalue= ADC0_InSeq3(); //Store ADC conversion into ADCvalue
	Voltage= ADCvalue*3.3/4096; //Convert to voltage
	//UARTprintf("Hello");
	//UART_OutChar(ADCvalue);
	//OutVolt(Voltage);

}
}

  • Wilson,

    this is a very broad question. Have you had a look at the examples that come with TivaWare? For general familiarity with TM4C there are some tutorials on the TI Wiki pages. Assuming you are using the lowest cost launchpad, there are some tutorials/training located here: processors.wiki.ti.com/.../Getting_Started_with_the_TIVA™_C_Series_TM4C123G_LaunchPad

    You may want to consider using the forum search utility as well. There is a broad spectrum of information in older posts that forum members have posted while working through issues. In some cases, they simply post their solutions for the benefit of others. The wealth of knowledge in here is priceless and comes from many with years and years of years of experience in the embedded processing business.

    Also, can you confirm which board are you using? and what environment are you using for development? All of this needs to be included when you make a post so that we can get a picture of what you are doing.

    With all of that said I would recommend you implement your project in steps.

    1.) Get the UART interface working by communicating with a com window on the PC (use putty, telnet, or other serial com capable program). There is a UART Echo example included with TivaWare.

    2.) Get your ADC conversion working and convert the data to ASCII for transmit over UART to the PC, or send as hex so the values can be displayed in the serial window. The data format depends highly on what utiility you are going to use to display the data? Are you going to store in a file as CSV data then use Excel to plot the data or will you write a customer app on the PC?

    3.) Once you can successfully send the ADC data to the PC, work on the periodic sampling. I assume you will use a timer from the timer module as a trigger for the ADC so that you get a good amount of predictability int he time between samples for plotting. If not, you could just loop and do as many conversions as you need within the loop using a delay routine to control the timing of the conversions. The latter would work if you don't need the timing precision.

    Note that if you are sampling a 33KHz signal, you will probably want a significantly higher frequency on your sampling in order to get a good approximation of the wave form. 66KHz will only get you 2 samples per cycle.
  • It also depends on whether you are going to sample continuously or capture and transmit later. Also what format of data you are going to send. Many other details but that's a start.

    Robert