多路扫描AD转换,用DMA传输的例子(用STM32CUBEMX)

请版主介绍一下多路扫描AD转换,用DMA传输的例子(用CUBE)
已邀请:

xuwenmail - stm32爱好者

赞同来自: 李建波 ²º¹5¾ zlp rxj

问题解决了,我现在是用的3个ADC通道连续扫描,只需要将 if(HAL_ADC_Start_DMA(&hadc1, (uint32_t*)&uhADCxConvertedValue, 1) != HAL_OK),这一句里的1改成3就可以了。我现在第一个通道接地,第二个通道、第三个通道接3.3V,串口助手终于显示了正确的结果:
value is 0
value is 255
value is 255
value is 0
value is 255
value is 255
value is 0
value is 255
value is 255
value is 0
value is 255
value is 255
好高兴!!!

我最后总结下,stm32cubemx中的设置情况,例子中开了3个通道,用到的都是ADC1,好了,上图

无标题.png


无标题2.png

admin

赞同来自:

知道了.我也是在学习这个,最近公司忙,有时间我试试

admin

赞同来自:

你可以先研究下官方给出的例子

xuwenmail - stm32爱好者

赞同来自: 三分之一花甲 Yao

谢谢版主,看过官方的例子,只是单路AD然后DMA的例子,试过用CUBE设置多路,但是DMA方面的代码好象没有什么变化。缓冲区大小等一些参数不知道怎么设置,在哪里设置?

ZJZTO - 各种打酱油

赞同来自:

缓冲区可以按实际情况配置大小,比如定一个含1024个采样值的数组,然后将采样值循环写入,DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t)&uhADCDualConvertedValue;
最后将采样值按写入顺序读出。

admin

赞同来自: ZJZTO hellolixq

我的理解是,
hadc1.Init.ScanConvMode = ENABLE;
hadc1.Init.ContinuousConvMode = ENABLE;
hadc1.Init.NbrOfConversion = 3;
hadc1.Init.DMAContinuousRequests = ENABLE;
3个通道,扫描,连续,dma都使能,
定义一个数组
uint16_t uhADCxConvertedValue ;
将数组地址给
HAL_ADC_Start_DMA(&AdcHandle, (uint32_t*)&uhADCxConvertedValue, 1)
DMA设置里面使MEM自加
hdma_adc1.Init.MemInc = DMA_MINC_ENABLE;
这样数组里面的数据就会循环采集变化了吧??
不知道对不对,晚上回去试试,呵呵

shadow_bao

赞同来自:

我用keil自动的RTOS系统,DMA或者中断,智能单次采集,开启连续采集就死机。好像把整个CPU都用了似的,DMA不是不需要耗CPU的吗

xuwenmail - stm32爱好者

赞同来自:

/**
******************************************************************************
* File Name : main.c
* Date : 26/11/2014 13:25:00
* Description : Main program body
******************************************************************************
*
* COPYRIGHT(c) 2014 STMicroelectronics
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. Neither the name of STMicroelectronics nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
******************************************************************************
*/

/ Includes ------------------------------------------------------------------/
#include "stm32f4xx_hal.h"

/ USER CODE BEGIN Includes /
#include <stdio.h>
#ifdef _GNUC_
#define PUTCHAR_PROTOTYPE int_io_putchar(int ch)
#else
#define PUTCHAR_PROTOTYPE int fputc(int ch,FILE *f)
#endif
/ USER CODE END Includes /

/ Private variables ---------------------------------------------------------/
ADC_HandleTypeDef hadc1;
DMA_HandleTypeDef hdma_adc1;

UART_HandleTypeDef huart2;

/ USER CODE BEGIN PV /
__IO uint16_t uhADCxConvertedValue;
int i=0;
/ 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_ADC1_Init(void);
static void MX_USART2_UART_Init(void);

/ USER CODE BEGIN PFP /
static void Error_Handler(void);

/ USER CODE END PFP /

/ USER CODE BEGIN 0 /

/ USER CODE END 0 /

int main(void)
{

/ USER CODE BEGIN 1 /

/ USER CODE END 1 /

/ MCU Configuration----------------------------------------------------------/

/ Reset of all peripherals, Initializes the Flash interface and the Systick. /
HAL_Init();

/ Configure the system clock /
SystemClock_Config();

/ Initialize all configured peripherals /
MX_GPIO_Init();
MX_DMA_Init();
MX_ADC1_Init();
MX_USART2_UART_Init();

/ USER CODE BEGIN 2 /
if(HAL_ADC_Init(&hadc1) != HAL_OK)
{
/ Initialization Error /
Error_Handler();
}


/-3- Start the conversion process and enable interrupt ###########[size=16]#/ [/size]
if(HAL_ADC_Start_DMA(&hadc1, (uint32_t*)&uhADCxConvertedValue, 1) != HAL_OK)
{
/ Start Conversation Error /
Error_Handler();
}

/ USER CODE END 2 /

/ USER CODE BEGIN 3 /
/ Infinite loop /
while (1)
{
i++;
//printf("ok\n");
}
/ USER CODE END 3 /

}

/** System Clock Configuration
*/
void SystemClock_Config(void)
{

RCC_OscInitTypeDef RCC_OscInitStruct;
RCC_ClkInitTypeDef RCC_ClkInitStruct;

__PWR_CLK_ENABLE();

__HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1);

RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
RCC_OscInitStruct.HSEState = RCC_HSE_ON;
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
RCC_OscInitStruct.PLL.PLLM = 8;
RCC_OscInitStruct.PLL.PLLN = 336;
RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2;
RCC_OscInitStruct.PLL.PLLQ = 7;
HAL_RCC_OscConfig(&RCC_OscInitStruct);

RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_SYSCLK|RCC_CLOCKTYPE_PCLK1
|RCC_CLOCKTYPE_PCLK2;
RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV4;
RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV2;
HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_5);

}

/ ADC1 init function /
void MX_ADC1_Init(void)
{

ADC_ChannelConfTypeDef sConfig;

/**Configure the global features of the ADC (Clock, Resolution, Data Alignment and number of conversion)
*/
hadc1.Instance = ADC1;
hadc1.Init.ClockPrescaler = ADC_CLOCKPRESCALER_PCLK_DIV2;
hadc1.Init.Resolution = ADC_RESOLUTION8b;
hadc1.Init.ScanConvMode = ENABLE;
hadc1.Init.ContinuousConvMode = ENABLE;
hadc1.Init.DiscontinuousConvMode = DISABLE;
hadc1.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_NONE;
hadc1.Init.DataAlign = ADC_DATAALIGN_RIGHT;
hadc1.Init.NbrOfConversion = 3;
hadc1.Init.DMAContinuousRequests = ENABLE;
hadc1.Init.EOCSelection = EOC_SINGLE_CONV;
HAL_ADC_Init(&hadc1);

/**Configure for the selected ADC regular channel its corresponding rank in the sequencer and its sample time.
*/
sConfig.Channel = ADC_CHANNEL_1;
sConfig.Rank = 1;
sConfig.SamplingTime = ADC_SAMPLETIME_3CYCLES;
HAL_ADC_ConfigChannel(&hadc1, &sConfig);

/**Configure for the selected ADC regular channel its corresponding rank in the sequencer and its sample time.
*/
sConfig.Channel = ADC_CHANNEL_8;
sConfig.Rank = 2;
HAL_ADC_ConfigChannel(&hadc1, &sConfig);

/**Configure for the selected ADC regular channel its corresponding rank in the sequencer and its sample time.
*/
sConfig.Channel = ADC_CHANNEL_9;
sConfig.Rank = 3;
HAL_ADC_ConfigChannel(&hadc1, &sConfig);

}

/ USART2 init function /
void MX_USART2_UART_Init(void)
{

huart2.Instance = USART2;
huart2.Init.BaudRate = 115200;
huart2.Init.WordLength = UART_WORDLENGTH_8B;
huart2.Init.StopBits = UART_STOPBITS_1;
huart2.Init.Parity = UART_PARITY_NONE;
huart2.Init.Mode = UART_MODE_TX_RX;
huart2.Init.HwFlowCtl = UART_HWCONTROL_NONE;
huart2.Init.OverSampling = UART_OVERSAMPLING_16;
HAL_UART_Init(&huart2);

}

/**
* Enable DMA controller clock
*/
void MX_DMA_Init(void)
{
/ DMA controller clock enable /
__DMA2_CLK_ENABLE();

/ DMA interrupt init /
HAL_NVIC_SetPriority(DMA2_Stream0_IRQn, 0, 0);
HAL_NVIC_EnableIRQ(DMA2_Stream0_IRQn);

}

/** Configure pins as
* Analog
* Input
* Output
* EVENT_OUT
* EXTI
PC3 ------> I2S2_SD
PA4 ------> I2S3_WS
PA5 ------> SPI1_SCK
PA6 ------> SPI1_MISO
PA7 ------> SPI1_MOSI
PB10 ------> I2S2_CK
PC7 ------> I2S3_MCK
PA9 ------> USB_OTG_FS_VBUS
PA10 ------> USB_OTG_FS_ID
PA11 ------> USB_OTG_FS_DM
PA12 ------> USB_OTG_FS_DP
PC10 ------> I2S3_CK
PC12 ------> I2S3_SD
PB6 ------> I2C1_SCL
PB9 ------> I2C1_SDA
*/
void MX_GPIO_Init(void)
{

GPIO_InitTypeDef GPIO_InitStruct;

/ GPIO Ports Clock Enable /
__GPIOE_CLK_ENABLE();
__GPIOC_CLK_ENABLE();
__GPIOH_CLK_ENABLE();
__GPIOA_CLK_ENABLE();
__GPIOB_CLK_ENABLE();
__GPIOD_CLK_ENABLE();

/Configure GPIO pin : PE3 /
GPIO_InitStruct.Pin = GPIO_PIN_3;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_LOW;
HAL_GPIO_Init(GPIOE, &GPIO_InitStruct);

/Configure GPIO pin : PC0 /
GPIO_InitStruct.Pin = GPIO_PIN_0;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_LOW;
HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);

/Configure GPIO pin : PC3 /
GPIO_InitStruct.Pin = GPIO_PIN_3;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_LOW;
GPIO_InitStruct.Alternate = GPIO_AF5_SPI2;
HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);

/Configure GPIO pin : PA0 /
GPIO_InitStruct.Pin = GPIO_PIN_0;
GPIO_InitStruct.Mode = GPIO_MODE_EVT_RISING;
GPIO_InitStruct.Pull = GPIO_NOPULL;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);

/Configure GPIO pin : PA4 /
GPIO_InitStruct.Pin = GPIO_PIN_4;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_LOW;
GPIO_InitStruct.Alternate = GPIO_AF6_SPI3;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);

/Configure GPIO pins : PA5 PA6 PA7 /
GPIO_InitStruct.Pin = GPIO_PIN_5|GPIO_PIN_6|GPIO_PIN_7;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_LOW;
GPIO_InitStruct.Alternate = GPIO_AF5_SPI1;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);

/Configure GPIO pin : PB2 /
GPIO_InitStruct.Pin = GPIO_PIN_2;
GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
GPIO_InitStruct.Pull = GPIO_NOPULL;
HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);

/Configure GPIO pin : PB10 /
GPIO_InitStruct.Pin = GPIO_PIN_10;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_LOW;
GPIO_InitStruct.Alternate = GPIO_AF5_SPI2;
HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);

/*Configure GPIO pins : PD12 PD13 PD14 PD15
PD4 */
GPIO_InitStruct.Pin = GPIO_PIN_12|GPIO_PIN_13|GPIO_PIN_14|GPIO_PIN_15
|GPIO_PIN_4;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_LOW;
HAL_GPIO_Init(GPIOD, &GPIO_InitStruct);

/Configure GPIO pins : PC7 PC10 PC12 /
GPIO_InitStruct.Pin = GPIO_PIN_7|GPIO_PIN_10|GPIO_PIN_12;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_LOW;
GPIO_InitStruct.Alternate = GPIO_AF6_SPI3;
HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);

/Configure GPIO pin : PA9 /
GPIO_InitStruct.Pin = GPIO_PIN_9;
GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
GPIO_InitStruct.Pull = GPIO_NOPULL;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);

/Configure GPIO pins : PA10 PA11 PA12 /
GPIO_InitStruct.Pin = GPIO_PIN_10|GPIO_PIN_11|GPIO_PIN_12;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_LOW;
GPIO_InitStruct.Alternate = GPIO_AF10_OTG_FS;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);

/Configure GPIO pin : PD5 /
GPIO_InitStruct.Pin = GPIO_PIN_5;
GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
GPIO_InitStruct.Pull = GPIO_NOPULL;
HAL_GPIO_Init(GPIOD, &GPIO_InitStruct);

/Configure GPIO pins : PB6 PB9 /
GPIO_InitStruct.Pin = GPIO_PIN_6|GPIO_PIN_9;
GPIO_InitStruct.Mode = GPIO_MODE_AF_OD;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_LOW;
GPIO_InitStruct.Alternate = GPIO_AF4_I2C1;
HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);

/Configure GPIO pin : PE1 /
GPIO_InitStruct.Pin = GPIO_PIN_1;
GPIO_InitStruct.Mode = GPIO_MODE_EVT_RISING;
GPIO_InitStruct.Pull = GPIO_NOPULL;
HAL_GPIO_Init(GPIOE, &GPIO_InitStruct);

}

/ USER CODE BEGIN 4 /
static void Error_Handler(void)
{
/ Turn LED5 (RED) on /
HAL_GPIO_WritePin(GPIOD,GPIO_PIN_12,GPIO_PIN_SET);
while(1)
{
}
}
void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef* AdcHandle)

{

printf("value is %d\n value is %d \n value is %d \n ",uhADCxConvertedValue,uhADCxConvertedValue,uhADCxConvertedValue);

}
PUTCHAR_PROTOTYPE
{
/ Place your implementation of fputc here /
/ e.g. write a character to the USART /

HAL_UART_Transmit(&huart2,(uint8_t*)&ch,1,0xffff);



return ch;
}

/ USER CODE END 4 /

#ifdef USE_FULL_ASSERT

/**
* @brief Reports the name of the source file and the source line number
* where the assert_param error has occurred.
* @param file: pointer to the source file name
* @param line: assert_param error line source number
* @retval None
*/
void assert_failed(uint8_t* file, uint32_t line)
{
/ USER CODE BEGIN 6 /
// /* User can add his own implementation to report the file name and line number,
// ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */
/ USER CODE END 6 /

}

#endif

/**
* @}
*/

/**
* @}
*/

/*******************[i] (C) COPYRIGHT STMicroelectronics END OF FILE[/i]/

xuwenmail - stm32爱好者

赞同来自:

DMA设置:
hdma_adc1.Instance = DMA2_Stream0;
hdma_adc1.Init.Channel = DMA_CHANNEL_0;
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_HALFWORD;
hdma_adc1.Init.MemDataAlignment = DMA_MDATAALIGN_HALFWORD;
hdma_adc1.Init.Mode = DMA_CIRCULAR;
hdma_adc1.Init.Priority = DMA_PRIORITY_HIGH;
hdma_adc1.Init.FIFOMode = DMA_FIFOMODE_DISABLE;
HAL_DMA_Init(&hdma_adc1);

最后串口2printf uhADCxConvertedValue,uhADCxConvertedValue,uhADCxConvertedValue,结果只有uhADCxConvertedValue数据有变化(管脚悬空电压波动),后面的数据都为0,是哪里不对啊

popdes

赞同来自:

持续关注,O(∩_∩)O~

xuwenmail - stm32爱好者

赞同来自: admin

更进一步将 if(HAL_ADC_Start_DMA(&hadc1, (uint32_t*)&uhADCxConvertedValue, 1) != HAL_OK),中的1改成6,然后将转换后的存储变量定义为二维数组uhADCxConvertedValue;再观察串口输出的情况如下:v
alue is 0
value is 255
value is 255
value is 0
value is 255
value is 255
value is 0
value is 255
value is 255
value is 0
value is 255
value is 255
value is 0
value is 255
value is 255
value is 1
value is 255
value is 255
这样就是把第一次扫描转换的三个通道值存在数组的第一行的三个元素中,第二次扫描转换的值放在第二行的三个元素中。这样就可以方便后面的数字滤波处理了。

chupacabra96

赞同来自:

我的cubeMX完全无法 设置buffersize 缓存 ,请问楼主哪一个版本

全兜

赞同来自: 电子狂牛

那个DMA开中断就死的现象,其实是没有清除TCIF中断标志,这个标志如果一直存在就会不停进入中断

笑看风云

赞同来自: tinyuns

我的也是使用三个通道,但是只能读出一个通道的值。我也是使用 CUBE 生成的代码。
管理员可否分享一下你的程序。

romeo0108

赞同来自:

赞一个
 

wjb444

赞同来自:

谢谢!

小花

赞同来自:

1或者3?
HAL_StatusTypeDef HAL_ADC_Start_DMA(ADC_HandleTypeDef* hadc, uint32_t* pData, uint32_t Length)
Length到底是数据长度还是别的?
  * @param  Length: The length of data to be transferred from ADC peripheral to memory.
按照备注,应该是数据长度。

砖打怪兽

赞同来自: Sarah

我试过程序了,把1改成3,没用阿!看源文件的length 的意思是数据的长度啊。

顽石

赞同来自:

有代码吗?

KK - 硬件工程师

赞同来自:

这个社区有人用github吗?代码放到github上比较方便

The Virus

赞同来自:

有没有人做过多AD的DMA,请求帮助

好吧

赞同来自:

持续关注中,虽然我的3个通道数据都是0,不知道问题在哪里....

lemonoe

赞同来自:

关注啊,这个是很基本的需要。

金金

赞同来自:

stm32l053 使用HAL库怎样配置多通道



/**

  ******************************************************************************

  * File Name          : ADC.c

  * Description        : This file provides code for the configuration

  *                      of the ADC instances.

  ******************************************************************************

  *

  * COPYRIGHT(c) 2016 STMicroelectronics

  *

  * Redistribution and use in source and binary forms, with or without modification,

  * are permitted provided that the following conditions are met:

  *   1. Redistributions of source code must retain the above copyright notice,

  *      this list of conditions and the following disclaimer.

  *   2. Redistributions in binary form must reproduce the above copyright notice,

  *      this list of conditions and the following disclaimer in the documentation

  *      and/or other materials provided with the distribution.

  *   3. Neither the name of STMicroelectronics nor the names of its contributors

  *      may be used to endorse or promote products derived from this software

  *      without specific prior written permission.

  *

  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"

  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE

  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE

  * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE

  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL

  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR

  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER

  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,

  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE

  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

  *

  ******************************************************************************

  */


/* Includes ------------------------------------------------------------------*/

#include "adc.h"


#include "gpio.h"

#include "dma.h"


/* USER CODE BEGIN 0 */


/* USER CODE END 0 */


ADC_HandleTypeDef hadc1;

DMA_HandleTypeDef hdma_adc1;


/* ADC1 init function */

void MX_ADC1_Init(void)

{

  ADC_ChannelConfTypeDef sConfig;


    /**Common config 

    */

  hadc1.Instance = ADC1;

  hadc1.Init.ScanConvMode = ADC_SCAN_ENABLE;

  hadc1.Init.ContinuousConvMode = DISABLE;

  hadc1.Init.DiscontinuousConvMode = DISABLE;

  hadc1.Init.ExternalTrigConv = ADC_SOFTWARE_START;

  hadc1.Init.DataAlign = ADC_DATAALIGN_RIGHT;

  hadc1.Init.NbrOfConversion = 10;

  if (HAL_ADC_Init(&hadc1) != HAL_OK)

  {

    Error_Handler();

  }


    /**Configure Regular Channel 

    */

  sConfig.Channel = ADC_CHANNEL_0;

  sConfig.Rank = 1;

  sConfig.SamplingTime = ADC_SAMPLETIME_55CYCLES_5;

  if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK)

  {

    Error_Handler();

  }


    /**Configure Regular Channel 

    */

  sConfig.Channel = ADC_CHANNEL_1;

  sConfig.Rank = 2;

  if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK)

  {

    Error_Handler();

  }


    /**Configure Regular Channel 

    */

  sConfig.Channel = ADC_CHANNEL_2;

  sConfig.Rank = 3;

  if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK)

  {

    Error_Handler();

  }


    /**Configure Regular Channel 

    */

  sConfig.Channel = ADC_CHANNEL_3;

  sConfig.Rank = 4;

  if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK)

  {

    Error_Handler();

  }


    /**Configure Regular Channel 

    */

  sConfig.Channel = ADC_CHANNEL_4;

  sConfig.Rank = 5;

  if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK)

  {

    Error_Handler();

  }


    /**Configure Regular Channel 

    */

  sConfig.Channel = ADC_CHANNEL_8;

  sConfig.Rank = 6;

  if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK)

  {

    Error_Handler();

  }


    /**Configure Regular Channel 

    */

  sConfig.Channel = ADC_CHANNEL_9;

  sConfig.Rank = 7;

  if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK)

  {

    Error_Handler();

  }


    /**Configure Regular Channel 

    */

  sConfig.Channel = ADC_CHANNEL_10;

  sConfig.Rank = 8;

  if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK)

  {

    Error_Handler();

  }


    /**Configure Regular Channel 

    */

  sConfig.Channel = ADC_CHANNEL_11;

  sConfig.Rank = 9;

  if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK)

  {

    Error_Handler();

  }


    /**Configure Regular Channel 

    */

  sConfig.Channel = ADC_CHANNEL_12;

  sConfig.Rank = 10;

  if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK)

  {

    Error_Handler();

  }


}


void HAL_ADC_MspInit(ADC_HandleTypeDef* adcHandle)

{


  GPIO_InitTypeDef GPIO_InitStruct;

  if(adcHandle->Instance==ADC1)

  {

  /* USER CODE BEGIN ADC1_MspInit 0 */

__HAL_RCC_GPIOA_CLK_ENABLE();

__HAL_RCC_GPIOB_CLK_ENABLE();

__HAL_RCC_GPIOC_CLK_ENABLE();


  /* USER CODE END ADC1_MspInit 0 */

    /* Peripheral clock enable */

    __HAL_RCC_ADC1_CLK_ENABLE();

  

    /**ADC1 GPIO Configuration    

    PC0     ------> ADC1_IN10

    PC1     ------> ADC1_IN11

    PC2     ------> ADC1_IN12

    PA0-WKUP     ------> ADC1_IN0

    PA1     ------> ADC1_IN1

    PA2     ------> ADC1_IN2

    PA3     ------> ADC1_IN3

    PA4     ------> ADC1_IN4

    PB0     ------> ADC1_IN8

    PB1     ------> ADC1_IN9 

    */

    GPIO_InitStruct.Pin = MCU_AD_INPUT2_Pin|MCU_AD_INPUT3_Pin|V12_CURRENT_AD_Pin;

    GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;

    HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);


    GPIO_InitStruct.Pin = ACC_X_Pin|ACC_Y_Pin|ACC_Z_Pin|V12_OUT_AD_Pin 

                          |V12_IN_AD_Pin;

    GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;

    HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);


    GPIO_InitStruct.Pin = V5_IN_AD_Pin|MCU_AD_INPUT1_Pin;

    GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;

    HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);


    /* Peripheral DMA init*/

  

    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_HALFWORD;

    hdma_adc1.Init.MemDataAlignment = DMA_MDATAALIGN_HALFWORD;

    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(adcHandle,DMA_Handle,hdma_adc1);


  /* USER CODE BEGIN ADC1_MspInit 1 */

__HAL_DMA_ENABLE(&hdma_adc1);

__HAL_DMA_ENABLE_IT(&hdma_adc1, DMA_IT_TC);


  /* USER CODE END ADC1_MspInit 1 */

  }

}


void HAL_ADC_MspDeInit(ADC_HandleTypeDef* adcHandle)

{


  if(adcHandle->Instance==ADC1)

  {

  /* USER CODE BEGIN ADC1_MspDeInit 0 */


  /* USER CODE END ADC1_MspDeInit 0 */

    /* Peripheral clock disable */

    __HAL_RCC_ADC1_CLK_DISABLE();

  

    /**ADC1 GPIO Configuration    

    PC0     ------> ADC1_IN10

    PC1     ------> ADC1_IN11

    PC2     ------> ADC1_IN12

    PA0-WKUP     ------> ADC1_IN0

    PA1     ------> ADC1_IN1

    PA2     ------> ADC1_IN2

    PA3     ------> ADC1_IN3

    PA4     ------> ADC1_IN4

    PB0     ------> ADC1_IN8

    PB1     ------> ADC1_IN9 

    */

    HAL_GPIO_DeInit(GPIOC, MCU_AD_INPUT2_Pin|MCU_AD_INPUT3_Pin|V12_CURRENT_AD_Pin);


    HAL_GPIO_DeInit(GPIOA, ACC_X_Pin|ACC_Y_Pin|ACC_Z_Pin|V12_OUT_AD_Pin 

                          |V12_IN_AD_Pin);


    HAL_GPIO_DeInit(GPIOB, V5_IN_AD_Pin|MCU_AD_INPUT1_Pin);


    /* Peripheral DMA DeInit*/

    HAL_DMA_DeInit(adcHandle->DMA_Handle);

  }

  /* USER CODE BEGIN ADC1_MspDeInit 1 */


  /* USER CODE END ADC1_MspDeInit 1 */


/* USER CODE BEGIN 1 */


/* USER CODE END 1 */


/**

  * @}

  */


/**

  * @}

  */


/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/




用STM32CubeMX 直接生成的,然后把这个函数“HAL_ADC_Start_DMA(&hadc1, (uint32_t*)ADC1ConvertedValue, 10);” 放在main.c 里面的“while(1)”里面,注意:“ADC1ConvertedValue”这个变量一定要定义成无符号的16位,不能是32位。

uint16_t ADC1ConvertedValue[10];

当然,你用RTOS的话,也可以把这个函数放在线程里,性质是一样的。我这里定义了十个A/D转换口,ADC1-0,ADC1-1,ADC1-2,ADC1-3,ADC1-4,ADC1-8,ADC1-9,ADC1-10,ADC1-11,ADC1-12,测试下来,每个都可以用,不需要那么多口的,可以自己精简。

wide(BG7RGT)

赞同来自:

记号,正在要用到多通道采样项目

newfeng

赞同来自:

有没有试过一次最多能DMA多少个字节呀?

王建

赞同来自: 菜鸟新手

循环模式一旦错位,问题很严重。

bozai

赞同来自:

 __HAL_LINKDMA(adcHandle,DMA_Handle,hdma_adc1); 这句话的作用是什么?__HAL_LINKDMA这个函数用在什么地情况下?

赞同来自:

kkkkkk

qwer13579246

赞同来自:

楼主的方法可用,感谢分享

心中有个梦

赞同来自:

看看先

要回复问题请先登录注册