I am currently working on the ADC1 on the STM32F4 discovery board. The goal is to get the temp info of the board on ADC1 and also connect some infrared telemeters (Sharp GP2D12).
For this I want to use the ADC1 : PC1 for the internal temp sensor and PC2, PC3, PC4 for the telemeters.
For test purpose, I want to put the RED led "ON" when the value on these pins is greater than 1500mV.
The problem is when I put 3V on the pins PC2, PC3 or PC4, it doesn't put the RED led "ON".
I send also the values on the Uart, but have some random values of the order of 40mV. (even if the pins are connected or not to 3V)
I tried different solutions from different examples, but still without success :
https://github.com/mabl/ChibiOS/blob/master/demos/ARMCM4-STM32F407-DISCOVERY/main.c
https://github.com/Mathias-L/STM32F4-Discovery-example-code/blob/master/myADC.c
https://github.com/nt4t/Chibios-STM32F051-DISCOVERY-adc-shell-example/blob/master/main.c
Could you tell me if my configuration is correct ?
My Eclipse project is modified compared to the ChibiOS project from the Demo. I have 2 files for the ADC config :
adc_cfg.c :
Code: Select all
adcsample_t ADC1_Samples[ADC_GRP1_NUM_CHANNELS * ADC_GRP1_BUF_DEPTH];
const ADCConversionGroup ADC1_grpcfg =
{
FALSE, // set to TRUE if need circular buffer, set FALSE otherwise
ADC_GRP1_NUM_CHANNELS, // number of channels
ADC1_Cbk, // callback function
NULL, // CR1 register content
// HW dependent part
0, // CR2 register content
ADC_CR2_SWSTART, // SMRP1 register content
ADC_SMPR1_SMP_SENSOR(ADC_SAMPLE_56) | ADC_SMPR1_SMP_AN12(ADC_SAMPLE_56) | ADC_SMPR1_SMP_AN13(ADC_SAMPLE_56) | ADC_SMPR1_SMP_AN14(ADC_SAMPLE_56),
ADC_SQR1_NUM_CH(ADC_GRP1_NUM_CHANNELS), // SQR1 register content. Set channel sequence length
0, // SQR2 register content
ADC_SQR3_SQ1_N(ADC_CHANNEL_SENSOR) | ADC_SQR3_SQ2_N(ADC_CHANNEL_IN12) | ADC_SQR3_SQ3_N(ADC_CHANNEL_IN13) | ADC_SQR3_SQ4_N(ADC_CHANNEL_IN14)
};
adc_cfg.h :
Code: Select all
/****************************************************************************************************
* DEFINES
****************************************************************************************************/
// Total number of channels to be sampled by a single ADC operation.
#define ADC_GRP1_NUM_CHANNELS 4
// Depth of the conversion buffer : channels are sampled four times each.
#define ADC_GRP1_BUF_DEPTH 4
/****************************************************************************************************
* EXTERN
****************************************************************************************************/
extern const ADCConversionGroup ADC1_grpcfg;
extern adcsample_t ADC1_Samples[];
/****************************************************************************************************
* PROTOTYPES
****************************************************************************************************/
void ADC1_Cbk(ADCDriver *adcp, adcsample_t *buffer, size_t n);
Then I have an initialization function called at the beginning of the main :
init.c :
Code: Select all
void Init_Drivers(void)
{
halInit();
chSysInit();
/****************************************************************************************************
* Initializes the ADC driver 1 for pins PC1,2,3,4 and enable the thermal sensor.
****************************************************************************************************/
adcStart(&ADCD1, NULL);
adcSTM32EnableTSVREFE();
palSetPadMode(GPIOC, 1, PAL_MODE_INPUT_ANALOG); // IN11 [PC1]
palSetPadMode(GPIOC, 2, PAL_MODE_INPUT_ANALOG); // IN12 [PC2]
palSetPadMode(GPIOC, 3, PAL_MODE_INPUT_ANALOG); // IN13 [PC3]
palSetPadMode(GPIOC, 4, PAL_MODE_INPUT_ANALOG); // IN14 [PC4]
}
main.c :
Code: Select all
int main(void)
{
Init_Drivers();
/***** Threads Creation *************************************************************************/
chThdCreateStatic(wa_OSRunning, sizeof(wa_OSRunning), NORMALPRIO, Thread_OSRunning, NULL);
chThdCreateStatic(wa_Accelerometer, sizeof(wa_Accelerometer), NORMALPRIO, Thread_Accelerometer, NULL);
chThdCreateStatic(wa_ADC1, sizeof(wa_ADC1), NORMALPRIO, Thread_ADC1, NULL);
/************************************************************************************************
}
For the ADC acquisition I use a thread and then the ADC callback function to handle the ADC samples (in main.c) :
Code: Select all
static WORKING_AREA(wa_ADC1, 128);
static msg_t Thread_ADC1(void *arg)
{
UNUSED(arg);
chRegSetThreadName("ADC1");
while (TRUE)
{
chSysLockFromIsr();
adcConvert(&ADCD1, &ADC1_grpcfg, ADC1_Samples, ADC_GRP1_BUF_DEPTH);
chSysUnlockFromIsr();
chprintf((BaseSequentialStream*) &SD3, "PC1 value : %d mV \r\n", ADC1_Samples[0]);
chprintf((BaseSequentialStream*) &SD3, "PC2 value : %d mV \r\n", ADC1_Samples[1]);
chprintf((BaseSequentialStream*) &SD3, "PC3 value : %d mV \r\n", ADC1_Samples[2]);
chprintf((BaseSequentialStream*) &SD3, "PC4 value : %d mV \r\n", ADC1_Samples[3]);
}
return 0;
}
void ADC1_Cbk(ADCDriver *adcp, adcsample_t *buffer, size_t n)
{
UNUSED(buffer);
UNUSED(n);
adcsample_t avg_PC1, avg_PC2, avg_PC3, avg_PC4;
adcsample_t PC1_mV, PC2_mV, PC3_mV, PC4_mV;
/* Note, only in the ADC_COMPLETE state because the ADC driver fires an intermediate callback when the buffer is half full.*/
if (adcp->state == ADC_COMPLETE)
{
// Calculates the average values from the ADC samples
avg_PC1 = (ADC1_Samples[0] + ADC1_Samples[4] + ADC1_Samples[8] + ADC1_Samples[12]) / 4; // temp sensor
avg_PC2 = (ADC1_Samples[1] + ADC1_Samples[5] + ADC1_Samples[9] + ADC1_Samples[13]) / 4;
avg_PC3 = (ADC1_Samples[2] + ADC1_Samples[6] + ADC1_Samples[10] + ADC1_Samples[14]) / 4;
avg_PC4 = (ADC1_Samples[3] + ADC1_Samples[7] + ADC1_Samples[11] + ADC1_Samples[15]) / 4;
// Conversion in volt
PC1_mV = (avg_PC1/4095) * 3300;
PC2_mV = (avg_PC2/4095) * 3300;
PC3_mV = (avg_PC3/4095) * 3300;
PC4_mV = (avg_PC4/4095) * 3300;
if ( (PC1_mV > 1500) || (PC2_mV > 1500) || (PC3_mV > 1500) || (PC4_mV > 1500) )
{
palSetPad(GPIOD, LED_RED);
}
else
{
palClearPad(GPIOD, LED_RED);
}
}
}
Thanks in advance for your help !
