Part Number: EK-TM4C1294XL
Hi to all.
I am developing a 2MSps ADC application and I am having some problems with the configuration of the system.
I thought that following the excellent explanations I found in this thread in e2e forum (https://e2e.ti.com/support/microcontrollers/arm-based-microcontrollers-group/arm-based-microcontrollers/f/arm-based-microcontrollers-forum/690227/ccs-ek-tm4c1294xl-adc-not-running-at-2msps-capped-at-1msps/2545036#2545036) I would solve my problem, but my surprise was that the g_ui32SysClock variable which is where the master clock frequency number is saved, show a 80000000Hz clock when I set it to 120MHz. I use the next piece of code:
g_ui32SysClock = SysCtlClockFreqSet((SYSCTL_XTAL_25MHZ |
SYSCTL_OSC_MAIN |
SYSCTL_USE_PLL |
SYSCTL_CFG_VCO_320),
120000000);
I attach you my full code in the post.
Could you help me to understand why is this happening and kindly explain me how to solve it?
Thank you very much
Enric Puigvert
.
//*****************************************************************************
//
// blinky.c - Simple example to blink the on-board LED.
//
// Copyright (c) 2013-2020 Texas Instruments Incorporated. All rights reserved.
// Software License Agreement
//
// Texas Instruments (TI) is supplying this software for use solely and
// exclusively on TI's microcontroller products. The software is owned by
// TI and/or its suppliers, and is protected under applicable copyright
// laws. You may not combine this software with "viral" open-source
// software in order to form a larger program.
//
// THIS SOFTWARE IS PROVIDED "AS IS" AND WITH ALL FAULTS.
// NO WARRANTIES, WHETHER EXPRESS, IMPLIED OR STATUTORY, INCLUDING, BUT
// NOT LIMITED TO, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE. TI SHALL NOT, UNDER ANY
// CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL, OR CONSEQUENTIAL
// DAMAGES, FOR ANY REASON WHATSOEVER.
//
// This is part of revision 2.2.0.295 of the EK-TM4C1294XL Firmware Package.
//
//*****************************************************************************
/*
* ====== Includes ============================================================
*/
#include <stdbool.h>
#include <stdint.h>
#include "inc/hw_types.h"
#include "inc/hw_ints.h"
#include "inc/hw_memmap.h"
#include "inc/hw_adc.h"
#include "inc/hw_gpio.h"
#include "driverlib/adc.h"
#include "driverlib/debug.h"
#include "driverlib/gpio.h"
#include "driverlib/interrupt.h"
#include "driverlib/pin_map.h"
#include "driverlib/rom.h"
#include "driverlib/rom_map.h"
#include "driverlib/sysctl.h"
#include "driverlib/systick.h"
#include "driverlib/timer.h"
#include "driverlib/uart.h"
#include "utils/uartstdio.h"
/*
* ====== Defines =============================================================
*/
#define USER_LED1 GPIO_PIN_0
#define USER_LED2 GPIO_PIN_1
#define ADC0_ISC_R (*((volatile uint32_t *)0x4003800C))
#define ADC0_STEPS 1 //number of conversions in one ADC interruption
//(Permited: 1 to 8).
#define MSTR_CLK 120000000 //Master Clock frequency (Hz)
#define TIMERA0_FREQ 2000000 //Timer A0 frequency (Hz)
/*
* ====== Global Variables ====================================================
*/
uint32_t g_ui32SysClock; //clock system
uint32_t ui32Value[ADC0_STEPS]; //buffer to save data from ADC
uint32_t lost_measurements = 0; //lost measurements control variable
uint8_t adc_flag = 0; //new ADC0 data flag
uint8_t dbg_flag = 0; //debug pin flag
/*
* ====== Function Definition =================================================
*/
/*
*
* ====== void ADCSeq0Handler(void) ======
* Interrupt handler for ADC0 Sequence Zero. Interrupt function for ADC0
* sequencer 0 step finish. It will clear the interrupt flags and get ADC
* conversion results to its buffer.
*
*/
void ADCSeq0Handler(void)
{
// GPIOPinWrite(GPIO_PORTF_BASE, GPIO_PIN_1, dbg_flag+1);
// ADCIntClear(ADC0_BASE, 0); //Clear the Interrupt Flag.
HWREG(GPIO_PORTF_BASE +(GPIO_O_DATA + (GPIO_PIN_1<<2))) = dbg_flag+1;
HWREG(ADC0_BASE + ADC_ISC_IN0 ) = 1;
adc_flag = 1;
if(dbg_flag){
dbg_flag = 0;
}
else{
dbg_flag = 2;
}
}
/*
*
* ====== void ConfigureUART (void) ======
* Configure the UART and its pins to enable a printf clone through UART
* This must be called before UARTprintf().
*
*/
void ConfigureUART(void)
{
//
// Enable the GPIO Peripheral used by the UART.
//
SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOA);
//
// Enable UART0.
//
SysCtlPeripheralEnable(SYSCTL_PERIPH_UART0);
//
// Configure GPIO Pins for UART mode.
//
GPIOPinConfigure(GPIO_PA0_U0RX);
GPIOPinConfigure(GPIO_PA1_U0TX);
GPIOPinTypeUART(GPIO_PORTA_BASE, GPIO_PIN_0 | GPIO_PIN_1);
//
// Initialize the UART for console I/O.
//
UARTStdioConfig(0, 115200, g_ui32SysClock);
}
/*
*
* ====== void init_ADC0 (void) ======
* Initialization and configuration of the ADC0
*
*/
void init_ADC0(void)
{
/************************ Peripheral enabling ****************************/
//
// Enable ADC0 Peripheral for analog readings.
// Enable PORT E for ADC0 input.
//
SysCtlPeripheralEnable(SYSCTL_PERIPH_ADC0);
while (!SysCtlPeripheralReady(SYSCTL_PERIPH_ADC0))
{
UARTprintf("Error! ADC0 not initialized.\n");
}
SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOE);
while (!SysCtlPeripheralReady(SYSCTL_PERIPH_GPIOE))
{
UARTprintf("Error! PORT E not initialized.\n");
}
/************************* GPIO Port E config ****************************/
//
// Initialize GPIO E0 for ADC input
//
GPIOPinTypeADC(GPIO_PORTE_BASE, GPIO_PIN_0);
SysCtlDelay(80); //delay to wait for config
GPIOPadConfigSet(GPIO_PORTE_BASE, GPIO_PIN_0,
GPIO_STRENGTH_2MA,
GPIO_PIN_TYPE_ANALOG); //TODO: This may be unnecessary
/************************** ADC clock config *****************************/
//
// Configure the ADC clock to use PLL VCO clock (configured in
// SysCtlClockFreqSet() at 320MHz) at full rate (means that is predivided
// by 2), and divided by 5 by us:
// -----------------------------------
// | F_adc = F_pll_vco/5 = (F_pll/2)/5 |
// -----------------------------------
// -> Remember: To use 2MSps function, we need to set F_adc to 32MHz as
// datasheet says. For other sampling options read datasheet.
//
ADCClockConfigSet(ADC0_BASE, ADC_CLOCK_SRC_PLL | ADC_CLOCK_RATE_FULL, 5);
//
// Wait for the clock configuration to set.
//
SysCtlDelay(10);
/************** Disable all Interruptions for configuration **************/
//
// Disable the ADC0 sequence 0 interrupt on the processor (NVIC).
//
IntDisable(INT_ADC0SS0);
//
// Disable interrupts for ADC0 sample sequence 0 to configure it.
//
ADCIntDisable(ADC0_BASE, 0);
/********************** Sequencer0 configuration *************************/
//
// Disable ADC0 sample sequence 0. With the sequence disabled, it is now
// safe to load the new configuration parameters.
//
ADCSequenceDisable(ADC0_BASE, 0);
// //
// // Enable sample sequence 0 with a processor signal trigger. Sequence 0
// // will do a single sample when the processor sends a signal to start the
// // conversion. The trigger is generated by ADCProcessorTrigger() function.
// //
// ADCSequenceConfigure(ADC0_BASE, 0, ADC_TRIGGER_PROCESSOR, 0);
//
// Enable sample sequence 0 with a timer signal trigger. Sequence 0
// will do a single sample when the TimerA0 sends a signal to start the
// conversion.
//
ADCSequenceConfigure(ADC0_BASE, 0, ADC_TRIGGER_TIMER, 0);
//
// Configure step 0 on sequence 0. Sample channel 3 (ADC_CTL_CH3) which is
// AIN3 that corresponds to PB0 pin as datasheet says. Single-ended mode
// (default) and configure the interrupt flag (ADC_CTL_IE)define to be set when
// the sample is done. Tell the ADC logic that this is the last conversion
// on sequence 0 (ADC_CTL_END).
// Sequence 0 has 8 programmable steps (from 0 to 7). Since we are only
// doing a single conversion using sequence 0 we will only
// configure step 0. For more information on the ADC sequences and steps,
// reference the datasheet.
//
ADCSequenceStepConfigure(ADC0_BASE, 0, ADC0_STEPS - 1,
ADC_CTL_CH3 | ADC_CTL_END | ADC_CTL_IE);
//
// Since sample sequence 0 is now configured, it must be enabled.
//
ADCSequenceEnable(ADC0_BASE, 0);
/******************* Interrupt enable -************************************/
//
// Clear the interrupt status flag. This is done to make sure the
// interrupt flag is cleared before we sample.
//
ADCIntClear(ADC0_BASE, 0);
//
// Enable the ADC 0 sample sequence 0 interrupt.
//
ADCIntEnable(ADC0_BASE, 0);
//
// Enable the interrupt for ADC0 sequence 0 on the processor (NVIC).
//
IntEnable(INT_ADC0SS0);
}
/*
*
* ====== void init_timerA0(void) ======
* Initialization and configuration of the TimerA0 to trigger the ADC0
*
*/
void init_timerA0(void)
{
//
// Enable the timerA0 peripheral
//
SysCtlPeripheralEnable(SYSCTL_PERIPH_TIMER0);
//
// Configure a 32-bit periodic timer. We use a pair of two counters
// to reach the capacity of the desired counter:
//
// --------------------------------------------------
// | 16 bit counter + 16 bit counter = 32 bit counter |
// --------------------------------------------------
//
TimerConfigure(TIMER0_BASE, TIMER_CFG_SPLIT_PAIR | TIMER_CFG_A_PERIODIC);
//
// Set ADC sampling frequency to be TIMERA0_FREQ Hz.
//
TimerLoadSet(TIMER0_BASE, TIMER_A, (g_ui32SysClock / TIMERA0_FREQ) - 1);
//
// Enable the ADC trigger output for Timer A.
//
TimerControlTrigger(TIMER0_BASE, TIMER_A, true);
/**************************** DEBUG ***************************************/
//
// Enable the timer stall for debugging purposes. It halts the timer
// when the debugger stops the program.
//
TimerControlStall(TIMER0_BASE, TIMER_A, true);
}
/*******************************************************************************
*
* ====== int main(void) ======
* Main runtime function
*
******************************************************************************/
int main(void)
{
//
// Run from the PLL at 120 MHz.
// Note: SYSCTL_CFG_VCO_240 is a new setting provided in TivaWare 2.2.x and
// later to better reflect the actual VCO speed due to SYSCTL#22.
//
// @formatter:off
g_ui32SysClock = SysCtlClockFreqSet((SYSCTL_XTAL_25MHZ |
SYSCTL_OSC_MAIN |
SYSCTL_USE_PLL |
SYSCTL_CFG_VCO_320),
120000000);
// @formatter:on
//
// Initialize UART0 and write initial status.
//
ConfigureUART();
UARTprintf("Initializing system...\n");
//
// Enable PORT N Peripheral for debugging and config led1 as output
//
SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOF);
while (!SysCtlPeripheralReady(SYSCTL_PERIPH_GPIOF))
{
UARTprintf("Error! GPION not initialized.\n");
}
GPIOPinTypeGPIOOutput(GPIO_PORTF_BASE, GPIO_PIN_1);
GPIOPinWrite(GPIO_PORTF_BASE, GPIO_PIN_1, GPIO_PIN_1);
//
// Initilize ADC0 with all configurations
//
init_ADC0();
//
// Initialize TimerA0 with all configurations
//
init_timerA0();
//
// Enable processor interrupts
//
IntMasterEnable();
//
// Start timerA0
//
TimerEnable(TIMER0_BASE, TIMER_A);
//
//Header print
//
UARTprintf("ADC Value: \n\r");
//
// Loop forever
//
while (1)
{
if(adc_flag)
{
//
//Read the value from the ADC
//
ADCSequenceDataGet(ADC0_BASE, 0, ui32Value);
// UARTprintf("%d\r", ui32Value); //print it
adc_flag = 0;
}
}
}