µTasker Forum
µTasker Forum => Luminary Micro TM LM3SXXXX => Topic started by: mhoneywill on June 12, 2010, 06:54:24 PM
-
Hi Mark,
I want the ADC in my LM3S1968 based project to just run in the background continuously just reading the 8 ADC inputs. In fact in my application I'm just using the ADC inputs as another 8 logic input lines. I've setup a 1ms hardware timer that I'm using to sample some input lines (3 lines used to sample a 3phase mains supply so I can work out the mains sequence).
By a bit of trial and error I've got something that works in the simulator (I've no access to the hardware until Monday).
I couldn't find much info on ADC configuration on the forum or in the documentation so I'm posting here describing what I've done. So that it will be of help to other users and you can also tell me if I've done something wrong.
Firstly I setup the hardware Timer as shown below
unsigned long MSTimerTick = 0;
static void timer_int(void)
{
MSTimerTick++;
PhaseMap();
}
static void fnConfigure_Timer(void)
{
static TIMER_INTERRUPT_SETUP timer_setup = {0}; // interrupt configuration parameters
timer_setup.timer_reference = 2; // timer channel 2
timer_setup.int_type = TIMER_INTERRUPT;
timer_setup.int_priority = PRIORITY_TIMERS;
timer_setup.int_handler = timer_int; // set to 0 for no handler
timer_setup.timer_mode = (TIMER_TRIGGER_ADC | TIMER_PERIODIC | TIMER_MS_VALUE); // period timer
timer_setup.timer_value = 1; // ms delay
fnConfigureInterrupt((void *)&timer_setup); // enter interrupt for timer test
}
Am I correct in using TIMER_TRIGGER_ADC in the timer_mode setting?
Next I set-up the ADC as shown below
static void fnConfigureADC(void)
{
ADC_SETUP adc_setup; // interrupt configuration parameters
adc_setup.int_type = ADC_INTERRUPT; // identifier when configuring
adc_setup.int_handler = 0; // handling function
adc_setup.int_priority = PRIORITY_ADC; // ADC interrupt priority
adc_setup.int_adc_single_ended_inputs = (ADC_CHANNEL_0 | ADC_CHANNEL_1 | ADC_CHANNEL_2 | ADC_CHANNEL_3 | ADC_CHANNEL_4 | ADC_CHANNEL_5 | ADC_CHANNEL_6 | ADC_CHANNEL_7); // ADC channels 0..3 as single ended inputs
adc_setup.int_adc_differential_inputs = 0; // No ADC channels as differential inputs
adc_setup.int_adc_mode = (ADC_CONFIGURE_ADC | ADC_TRIGGER_TIMER); // start under timer control
adc_setup.int_adc_averaging = HW_AVERAGING_64; // basic sampling speed is 1MHz but can be averaged to improve accuracy or reduce speed
adc_setup.int_adc_result = usADC_samples; // location to save the samples to
adc_setup.int_sequence_count = ADC_SEQUENCES;
fnConfigureInterrupt((void *)&adc_setup); // configure and start sequence
}
I presume this is the correct way to set the ADC mode?
adc_setup.int_adc_mode = (ADC_CONFIGURE_ADC | ADC_TRIGGER_TIMER);
Next it is all started off in my application startup with the following lines
fnConfigureADC(); //
fnConfigure_Timer(); // Hardware timer used for Phase detection and ADC trigger
As I say this seems to work in the Simulator I just wanted to ensure I was doing the right thing.
Cheers
Martin
-
Hi Martin
It looks correct as you have done it - if the simulator works it should also work on the HW (the simulator checks things quite strictly so didn't see anything wrong - thus performing the conversions).
The ADC can be triggered from various sources (comparators, PWM, port PB4, timers). The ADC configuration flag ADC_TRIGGER_TIMER causes configuration of a trigger from any enabled timer. The timer then needs to be configured separately and is connected to ADC trigger internally when the flag TIMER_TRIGGER_ADC is used.
Note that Timer 3 doesn't seem to work as ADC trigger. There are also some errata concerning ADC triggering so check the latest errata sheet and silicon revision to see whether it could be a problem.
Regards
Mark
-
Thanks for the heads up about the Errata, looks like there are some nasty gotcha's there
Regards
Martin