Hello,
can anyone help me,how can I program the AD-Converter of the MCB4300. The program works with one channel (AD0 - Channel 1), but I need 2 channels (AD0 - Channel 1 and AD0 Channel 0).
int main(void) { int adcVal;
ADC_Initialize(); ADC_StartConversion();
while(ADC_ConversionDone () < 0);
adcVal = ADC_GetValue(); }
/* This is the program code from the Example of Keil for the MCB4300 */ #include "LPC43xx.h" #include "SCU_LPC43xx.h" #include "Board_ADC.h"
#define ADC_RESOLUTION 10 /* Number of A/D converter bits */
/* Clock Control Unit register bits */ #define CCU_CLK_CFG_RUN (1 << 0) #define CCU_CLK_CFG_AUTO (1 << 1) #define CCU_CLK_STAT_RUN (1 << 0)
static volatile uint16_t AD_last; /* Last converted value */ static volatile uint8_t AD_done; /* AD conversion done flag */
int32_t ADC_Initialize (void) {
/* Enable ADC0 clock */ LPC_CCU1->CLK_APB3_ADC0_CFG = CCU_CLK_CFG_AUTO | CCU_CLK_CFG_RUN; while (!(LPC_CCU1->CLK_APB3_ADC0_STAT & CCU_CLK_STAT_RUN));
/* Configure ADC0_1 */ LPC_ADC0->CR = (1 << 1) | /* Select ADC0_1 pin for conversion */ (2 << 8) | /* 12MHz / (2+1) = 4MHz */ (1 << 21) ; /* ADC is operational */
/* Enable ADC0 Channel 1 interrupt */ LPC_ADC0->INTEN |= (1 << 1); NVIC_EnableIRQ (ADC0_IRQn);
return 0; }
int32_t ADC_Uninitialize (void) {
/* Disable ADC0 Channel 1 interrupt */ NVIC_DisableIRQ (ADC0_IRQn); LPC_ADC0->INTEN &= ~(1 << 1);
/* Disable ADC0 clock */ LPC_CCU1->CLK_APB3_ADC0_CFG = 0;
int32_t ADC_StartConversion (void) {
LPC_ADC0->CR |= (1 << 24); /* Start conversion */
int32_t ADC_ConversionDone (void) { return (AD_done ? 0 : -1); }
int32_t ADC_GetValue (void) {
if (AD_done) { AD_done = 0; return AD_last; } return -1; }
uint32_t ADC_GetResolution (void) { return ADC_RESOLUTION; }
void ADC0_IRQHandler (void) {
LPC_ADC0->GDR; /* Clear IRQ request flag */ AD_last = (LPC_ADC0->DR[1] >> 6) & 0x3FF; /* Read value and clear IRQ */ AD_done = 1; }
-----> LPC_ADC0->CR = (1 << 1) | (2 << 8) | (1 << 21) ; <-----
It says in the datasheet that for ADC0-CR where I can select the Channel for the AD0: "In software-controlled mode, only one of these bits should be 1. In hardware scan mode, any value containing 1 t0 8 ones is allowed"
My problem is, if I want to use Channel 0 and 1 of the ADC0 at the same time, how can I do this.
Thank you in advance for your help.
Okey thanks! I will look in other NXP examples. I hope I will find a similar programm.
Similar program? Why? It's enough to find an example that makes use of a timer to generate a periodic timer interrupt. There you can insert your own single instruction to start an ADC conversion.
The world has seen billions of different programs written. You don't get anywhere by expecting to always find examples doing the exact same thing. You use examples to view concepts. Then you adapt these concepts to your own requirements. So it's irrelevant if the timer example contains any use of any ADC or not. And it's irrelevant if any ADC sample contains any timer code or not. You are the one who must merge the concepts from different examples into a single program adapted to your specific needs. By reading and understanding the examples - after having cross-referenced the example code with the datasheet documentation.
Yes of course you are right, I meant, I hope I will find a similar program which use a timer.
Now I found in the demo programm of MCB4300 an timer:
/* Periodic timer definition */ void Timer_Callback (void const *arg); osTimerDef (PeriodicTimer, Timer_Callback); osTimerId TimerId;
void Timer_Callback (void const *arg) { static uint8_t TickLed, TickBtn, TickTh;
switch (TickLed++) { case 1: LEDOn = 1; break; case 6: LEDOff = 1; break; case 10: TickLed = 0; break; }
if (BtnTick == 0) { TickBtn++; if (TickBtn == 50) { BtnTick = 1; TickBtn = 0; } } else TickBtn = 0;
TickTh++; if (TickTh > 200) { TickTh = 0; Measure = 1; } }
int main (void) { TimerId = osTimerCreate (osTimer(PeriodicTimer), osTimerPeriodic, NULL);
if (TimerId) { osTimerStart (TimerId, 10); } }
But I can't understand how I can use it for my AD-Converter. I understand the main program. At first an TimerId wil created and then the timer starts with 10ms.
But what must I do in the Timer_Callback function. Have you any idea?
By the way, sorry for my english!
In the timer interrupt, you must do exactly what I have already suggested. Start the AD conversion. If you don't start any AD conversion, you will not get any ADC interrupt on conversion completion.
So, my program works. At first thank you for your help.
The timer works, and I see on the LCD periodic the adc-values. But when the timer expire, normally it has to start again. But it does not. Why? Do I need a while-loop?
void Timer_Callback (void const *arg); osTimerDef (Timer, Timer_Callback); osTimerId TimerId;
uint32_t exec; uint32_t timerDelay;
void Timer_Callback (void const *arg) {
int adcVal[3];
ADC_Initialize();
ADC_StartConversion();
while(ADC_ConversionDone() < 0);
adcVal[0] = ADC_GetValue(); }
int main(void) { int adcVal[3];
exec = 2; TimerId = osTimerCreate (osTimer(Timer), osTimerPeriodic, &exec);
if (TimerId != NULL) { timerDelay = 1000; osTimerStart (TimerId, timerDelay); } }
I have debug the program and the problem is caused by: os_idle_demon
But how can I solve this problem?
"It is running when no other task is ready to run (idle situation)"
/*--------------------------- os_idle_demon ---------------------------------*/
__task void os_idle_demon (void) { /* The idle demon is a system task. It is running when no other task is */ /* ready to run (idle situation). It must not terminate. Therefore it */ /* should contain at least an endless loop. */
for (;;) { _idle_(); /* enter low-power mode */ } } /* end of os_idle_demon */
Ok I have solve the problem. It had nothing to do with the timer.
Why do you initialize the ADC again and again?
It's enough that you initialize it once and then just start a new conversion when the timer ticks.
By the way - if you take a closer look at the information directly above the message input box when you are about to make new posts, there are clear instructions how to post source code.
It's much easier to read code problerly tagged:
#include <stdio.h> void main(void) { printf("Hello world!\n"); while (1) ; }
Sorry, with the source code, i will do it next time.
Yes you're right, I can initialize the ADC only once in the main-function. I will correct it.
By the way, I have an 10-Bit ADC. If I get the converted value from my ADC, I have to convert this value in voltage. The formula is below:
Voltage = (ADC-Value * Uref) / 1024
But where can I get the value of the reference voltage Uref (in datasheet?)? Or rather, which means Uref?
Have you taken a closer look at the pins on your processor? And the schematics how your processor is interfaced on the board?
Or looked closer at the datasheet information?
Just identifying all processor pins relevant for the ADC should represent a significant hint how to figure ut that Uref.