2016-08-16 08:06 AM
I'm converting a bunch of ADC channels, and the ADC is setup to sequence through them.
I'm polling the results.How do I determine which channel was just converted?I can't find any calls into the HAL or any registers that will indicate which channel was just converted.Maybe it would be better to set the channel rather than have it sequence. I'm guessing you would do that with the HAL_ADC_ConfigChannel calls? But how do you cancel a previous channel?-Matt #adc #stm32l0x12016-08-16 08:18 PM
>I'm converting a bunch of ADC channels, and the ADC is setup to sequence through them.
>How do I determine which channel was just converted? I believe you can infer what channel is being converted by the number of times that the data register has been read. From reading the reference manual for the stm32f0 line, (specifically the ''Example Timing Diagrams'' section) I gather that the ADC waits for the end of conversion (EOC) flag to be cleared by reading the data register (DR) before starting the next channels conversion. This continues until the full set of channels have been read. This is with continuous mode disabled. Accessing the registers directly (this is code for the stm32f042, so check your chip's reference manual)//configure ADC clock
RCC->APB2ENR |= RCC_APB2ENR_ADC1EN;
//enable ADC clock
RCC->CR2 |= RCC_CR2_HSI14ON;
//enable sample clock
while
((RCC->CR2 & RCC_CR2_HSI14RDY) == 0);
//wait for clock to start up
//configure ADC
ADC1->CR |= ADC_CR_ADEN;
//enable ADC
while
((ADC1->ISR & ADC_ISR_ADRDY) == 0);
//wait until ready
ADC1->CFGR2 &= (~ADC_CFGR2_CKMODE);
//set ADC clock mode
uint16_t ADC_Result[3];
//select channels to convert
ADC1->CHSELR = ADC_CHSELR_CHSEL0 | ADC_CHSELR_CHSEL9 | ADC_CHSELR_CHSEL10;
while
(1) {
// Performs the AD conversion
ADC1->CR |= ADC_CR_ADSTART;
// Start the ADC conversion
//reads channel 0, channel 9, then channel 10 into the data array
for
(
int
i=0; i<3; i++){
while
((ADC1->ISR & ADC_ISR_EOC) == 0);
// Wait end of conversion
ADC_Result[i] = ADC1->DR;
// Store the ADC conversion result
}
}
Using the HAL library (I have not tried this)
//stmCube code should have taken care of channel and ADC initialization above here
uint16_t ADC_Result[i];
while
(1) {
//start conversion
HAL_ADC_Start(&hadc);
for
(
int
i=0; i<3; i++) {
//get the data from the channels
HAL_ADC_PollForConversion(&hadc, 10);
ADC_Result[i] = HAL_ADC_GetValue(&hadc);
}
}
>Maybe it would be better to set the channel rather than have it sequence. I'm guessing you would do that with the HAL_ADC_ConfigChannel calls? But how do you cancel a previous channel?
Accessing registers directly, you could clear the CHSELR register then write the bit for one channel every time you want to preform a conversion.
-Nebk
2016-08-17 07:44 AM
Nebk - thanks for your post.
I decided to only set 1 channel at a time. That way I know what was converted.<code>
void service_adc(ADC_HandleTypeDef *p_hadc){ if (HAL_OK == HAL_ADC_PollForConversion(p_hadc, 0xFFFF)) { ADC_ChannelConfTypeDef sConfig; uint8_t txx = 0; // Update stdread switch (cur_adc_chan) {..... value = HAL_ADC_GetValue(p_hadc);..... // Disable current channel sConfig.Channel = adc_channels[cur_adc_chan]; sConfig.Rank = ADC_RANK_NONE; if (HAL_ADC_ConfigChannel(p_hadc, &sConfig) != HAL_OK) { Error_Handler(); } ++cur_adc_chan; if (NUM_ADC_CHAN < cur_adc_chan) cur_adc_chan = 0; // Enable new channel sConfig.Channel = adc_channels[cur_adc_chan]; sConfig.Rank = ADC_RANK_CHANNEL_NUMBER; if (HAL_ADC_ConfigChannel(p_hadc, &sConfig) != HAL_OK) { Error_Handler(); } if (HAL_ADC_Start(p_hadc) != HAL_OK) { Error_Handler(); } }}</code>I think relying on the order of conversion is to open to error.-Matt