2017-12-04 01:33 PM
Hello,
I am using ADC multi-channel DMA on stm32f105rc to receive some data on 3 adc channels. Ideally I would see 3 values with not much variations on my PC display. However, values I retrieved from the DMA were changing all the time and I do not know what goes wrong. Here is what I have for the code, I basically use cubeMX to generate the code and make a few modification on it. The idea is to retrieve the adc data by using DMA and transmit to PC terminal by UART.
&sharpinclude 'main.h'
&sharpinclude 'stm32f1xx_hal.h'/* USER CODE BEGIN Includes */
/* USER CODE END Includes */
&sharpdefine LED_1 GPIO_PIN_12&sharpdefine SW_ENABLE_3V3 GPIO_PIN_1/* Private variables ---------------------------------------------------------*/ADC_HandleTypeDef hadc1;DMA_HandleTypeDef hdma_adc1;UART_HandleTypeDef huart1;
DMA_HandleTypeDef hdma_usart1_tx;/* USER CODE BEGIN PV */
/* Private variables ---------------------------------------------------------*/uint32_t buff_rx1[3];uint32_t adc[3];int len0, len1, i;char header[100];
/* USER CODE END PV *//* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);static void MX_GPIO_Init(void);static void MX_DMA_Init(void);static void MX_USART1_UART_Init(void);static void MX_ADC1_Init(void);int main(void)
{HAL_Init();
SystemClock_Config();
MX_GPIO_Init(); MX_DMA_Init(); MX_USART1_UART_Init(); MX_ADC1_Init(); while (1) {HAL_GPIO_WritePin(GPIOB, SW_ENABLE_3V3, GPIO_PIN_RESET);
HAL_Delay(500); HAL_ADC_Start_DMA(&hadc1, (uint32_t*)buff_rx1, 3); HAL_ADC_Start_IT(&hadc1);HAL_GPIO_WritePin(GPIOB, SW_ENABLE_3V3, GPIO_PIN_SET);
sprintf(header, '%lu %lu %lu data done\r\n', (unsigned long)buff_rx1[0], (unsigned long)buff_rx1[1], (unsigned long)buff_rx1[2]);
len0 = strlen(header); HAL_UART_Transmit(&huart1, header, len0, 500); HAL_Delay(1500); HAL_GPIO_TogglePin(GPIOC,LED_1); }}/************************************/
I set 3 adc channels with sampling time of 1.5 cycle. The output value looks like:
783 560 378 data done
783 755 2565 data done775 644 2326 data done776 2564 382 data done2638 2633 462 data done775 634 408 data done783 2564 373 data done776 732 2553 data done2637 2569 410 data done776 522 365 data done776 2620 437 data done2636 2563 402 data doneThanks for your help.
#multichannel-adc #dma #stm32f12017-12-04 01:52 PM
So may be show the ADC initialization code?
Do you have a sufficient sample time? You're charging a capacitor so think how much current your sources can supply to change the state from the prior channel.
Consider not restarting the ADC/DMA in every loop iteration. It should be possible to put the DMA in a circular mode so you don't lose channel synchronization.
How do you know if the conversion completes?
2017-12-04 03:14 PM
Thanks for your reply.
The adc init looks like this:
static void MX_ADC1_Init(void)
{ADC_ChannelConfTypeDef sConfig;
/**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 = 3; if (HAL_ADC_Init(&hadc1) != HAL_OK) { _Error_Handler(__FILE__, __LINE__); }/**Configure Regular Channel
*/ sConfig.Channel = ADC_CHANNEL_10; sConfig.Rank = 1; sConfig.SamplingTime = ADC_SAMPLETIME_1CYCLE_5; if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK) { _Error_Handler(__FILE__, __LINE__); }/**Configure Regular Channel
*/ sConfig.Channel = ADC_CHANNEL_12; sConfig.Rank = 2; if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK) { _Error_Handler(__FILE__, __LINE__); }/**Configure Regular Channel
*/ sConfig.Channel = ADC_CHANNEL_13; sConfig.Rank = 3; if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK) { _Error_Handler(__FILE__, __LINE__); }}
If I do not put the adc/dma into a loop, what would be the right way to read data continuously? When talking about the conversion complete, I know it may requires an interrupt but I don't know what would be the appropriate way. I am still new to stm32 and embedded.
2017-12-05 12:31 AM
You can configure DMA in circular mode and use HAL_ADC_ConvCpltCallback and HAL_ADC_ConvHalfCpltCallback to push data continuously from ADC to a buffer it is similar to that of doing ping pong.
2017-12-07 06:05 AM
Thank you!