Can i use DMA-ADC1 for continous conversion and ADC2 for single conversion at the same time?
Hello there, I've been looking a way to sample ADC continously with DMA for measuring power supply current and voltage, and then another ADC for temperature reading which probably just readed only once per second.
I've read STM32 ADC modes and yet don't understand whether my application was possible, probably because my english was not that good.
I have tried some code by myself, but can't get it to work
Here is my code :
extern "C" void DMA1_Channel1_IRQHandler(void)
{
HAL_DMA_IRQHandler(&hdma_adc1);
}
extern "C" void HAL_ADC_MspInit(ADC_HandleTypeDef* hadcx)
{
GPIO_InitTypeDef GPIO_InitStruct = {0};
if(hadcx->Instance==ADC2){
__HAL_RCC_ADC2_CLK_ENABLE();
}
if(hadcx->Instance==ADC1)
{
__HAL_RCC_ADC1_CLK_ENABLE();
hdma_adc1.Instance = DMA1_Channel1;
hdma_adc1.Init.Direction = DMA_PERIPH_TO_MEMORY;
hdma_adc1.Init.PeriphInc = DMA_PINC_DISABLE;
hdma_adc1.Init.MemInc = DMA_MINC_ENABLE;
hdma_adc1.Init.PeriphDataAlignment = DMA_PDATAALIGN_WORD;
hdma_adc1.Init.MemDataAlignment = DMA_MDATAALIGN_WORD;
hdma_adc1.Init.Mode = DMA_CIRCULAR;
hdma_adc1.Init.Priority = DMA_PRIORITY_LOW;
if (HAL_DMA_Init(&hdma_adc1) != HAL_OK)
{
Error_Handler();
}
__HAL_LINKDMA(hadcx,DMA_Handle,hdma_adc1);
}
}
extern "C" void HAL_ADC_MspDeInit(ADC_HandleTypeDef* hadcx)
{
if(hadcx->Instance==ADC1)
{
__HAL_RCC_ADC1_CLK_DISABLE();
HAL_DMA_DeInit(hadcx->DMA_Handle);
}
if(hadcx->Instance==ADC2)
{
__HAL_RCC_ADC2_CLK_DISABLE();
HAL_DMA_DeInit(hadcx->DMA_Handle);
}
}
static void MX_DMA_Init(void)
{
/* DMA controller clock enable */
__HAL_RCC_DMA1_CLK_ENABLE();
/* DMA interrupt init */
/* DMA1_Channel1_IRQn interrupt configuration */
HAL_NVIC_SetPriority(DMA1_Channel1_IRQn, 0, 0);
HAL_NVIC_EnableIRQ(DMA1_Channel1_IRQn);
}
static void MX_ADC1_Init(void)
{
/* USER CODE BEGIN ADC1_Init 0 */
/* USER CODE END ADC1_Init 0 */
ADC_ChannelConfTypeDef sConfig = {0};
ADC_ChannelConfTypeDef sConfig2 = {0};
/* USER CODE BEGIN ADC1_Init 1 */
/* USER CODE END ADC1_Init 1 */
/** Common config
*/
hadc1.Instance = ADC1;
hadc1.Init.ScanConvMode = ADC_SCAN_ENABLE;
hadc1.Init.ContinuousConvMode = ENABLE;
hadc1.Init.DiscontinuousConvMode = DISABLE;
hadc1.Init.ExternalTrigConv = ADC_SOFTWARE_START;
hadc1.Init.DataAlign = ADC_DATAALIGN_RIGHT;
hadc1.Init.NbrOfConversion = 4;
if (HAL_ADC_Init(&hadc1) != HAL_OK)
{
Error_Handler();
}
/*
sConfig2.Channel = ADC_CHANNEL_8;
sConfig2.Rank = ADC_REGULAR_RANK_3;
sConfig2.SamplingTime = ADC_SAMPLETIME_55CYCLES_5;
if (HAL_ADC_ConfigChannel(&hadc2, &sConfig2) != HAL_OK){
Error_Handler();
}
*/
//////////////////////////////////////////////////////////////////
sConfig.Channel = ADC_CHANNEL_2;
sConfig.Rank = ADC_REGULAR_RANK_1;
sConfig.SamplingTime = ADC_SAMPLETIME_7CYCLES_5;
if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK){
Error_Handler();
}
sConfig.Channel = ADC_CHANNEL_3;
sConfig.Rank = ADC_REGULAR_RANK_2;
sConfig.SamplingTime = ADC_SAMPLETIME_7CYCLES_5;
if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK){
Error_Handler();
}
sConfig.Channel = ADC_CHANNEL_4;
sConfig.Rank = ADC_REGULAR_RANK_3;
sConfig.SamplingTime = ADC_SAMPLETIME_7CYCLES_5;
if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK){
Error_Handler();
}
sConfig.Channel = ADC_CHANNEL_9;
sConfig.Rank = ADC_REGULAR_RANK_4;
sConfig.SamplingTime = ADC_SAMPLETIME_7CYCLES_5;
if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK){
Error_Handler();
}
if (HAL_ADCEx_Calibration_Start(&hadc1) != HAL_OK){
Error_Handler();
}
hadc2.Instance = ADC2;
hadc2.Init.ScanConvMode = ADC_SCAN_DISABLE;
hadc2.Init.ContinuousConvMode = DISABLE;
hadc2.Init.DiscontinuousConvMode = DISABLE;
hadc2.Init.ExternalTrigConv = ADC_SOFTWARE_START;
hadc2.Init.DataAlign = ADC_DATAALIGN_RIGHT;
hadc2.Init.NbrOfConversion = 1;
if (HAL_ADC_Init(&hadc2) != HAL_OK)
{
Error_Handler();
}
sConfig2.Channel = ADC_CHANNEL_6;
sConfig2.Rank = ADC_REGULAR_RANK_1;
sConfig2.SamplingTime = ADC_SAMPLETIME_55CYCLES_5;
if (HAL_ADC_ConfigChannel(&hadc2, &sConfig2) != HAL_OK){
Error_Handler();
}
sConfig2.Channel = ADC_CHANNEL_7;
sConfig2.Rank = ADC_REGULAR_RANK_2;
sConfig2.SamplingTime = ADC_SAMPLETIME_55CYCLES_5;
if (HAL_ADC_ConfigChannel(&hadc2, &sConfig2) != HAL_OK){
Error_Handler();
}
//if (HAL_ADCEx_Calibration_Start(&hadc2) != HAL_OK){
//Error_Handler();
//}
}
int readTherm(int channel){
ADC_ChannelConfTypeDef adcChannel = {0};
switch(channel){
case 0:
//adcChannel.Channel = ADC_CHANNEL_8;
break;
case 1:
adcChannel.Channel = ADC_CHANNEL_6;
break;
case 2:
adcChannel.Channel = ADC_CHANNEL_7;
break;
}
adcChannel.Rank = 1;
adcChannel.SamplingTime = ADC_SAMPLETIME_55CYCLES_5; //or any other value available.
if(HAL_ADC_ConfigChannel(&hadc2, &adcChannel) != HAL_OK){
Error_Handler();
}
HAL_ADC_Start(&hadc2);
if (HAL_ADC_PollForConversion(&hadc2, 10) == HAL_OK){
return HAL_ADC_GetValue(&hadc2);
}
}
int raw_ch1Voltage;
int raw_ch2Voltage;
int raw_ch1Current;
int raw_ch2Current;
void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef* AdcHandle)
{
if(AdcHandle->Instance==ADC1){
raw_ch1Voltage = (dmaAdcBuffer[0]+dmaAdcBuffer[4]+dmaAdcBuffer[8])/3;
raw_ch2Voltage = (dmaAdcBuffer[2]+dmaAdcBuffer[6]+dmaAdcBuffer[10])/3;
raw_ch1Current = (dmaAdcBuffer[3]+dmaAdcBuffer[7]+dmaAdcBuffer[11])/3;
raw_ch2Current = (dmaAdcBuffer[1]+dmaAdcBuffer[5]+dmaAdcBuffer[9])/3;
// Add value from DMA buffer to running average (for smooth performance).
ch1Voltage.reading(raw_ch1Voltage);
ch2Current.reading(raw_ch2Current);
ch2Voltage.reading(raw_ch2Voltage);
ch1Current.reading(raw_ch1Current);
}
}
void initializeHAL(){
HAL_Init();
MX_GPIO_Init();
MX_DMA_Init();
MX_ADC1_Init();
HAL_ADC_Start(&hadc1);
HAL_ADC_Start_DMA(&hadc1, dmaAdcBuffer, 12);
}If i call HAL_ADC_Start(&hadc2) or readTherm(); or HAL_ADCEx_Calibration_Start(&hadc2); at some point on my code, the DMA crashed, the buffer was filled with some random big number, but the temperature reading is jsut fine.
the DMA could only able to work if i'm not calling those 3 function.
my chip is STM32F103C8T6
