STM32CubeMX ADC多通道DMA(循环传输Circular,单次Normal)
程序员文章站
2024-02-21 21:27:28
...
Cube配置
代码
uint16_t AD_Value[20];
//main.c文件
HAL_ADC_Start_DMA(&hadc1,(uint32_t *)AD_Value,20);
上面配置如果是word,则更改一下定义就好了,cube生成的代码会随着变:
uint32_t AD_Value[20];
//main.c文件
HAL_ADC_Start_DMA(&hadc1,(uint32_t *)AD_Value,20);
分析一下函数原型
HAL_StatusTypeDef HAL_ADC_Start_DMA(ADC_HandleTypeDef* hadc, uint32_t* pData, uint32_t Length)
有网友就简单看到原型是uint32_t就认为必须是32位了,其实ad只有12位,数据定义成16位才是物尽其用。产生这个试验想法是基于std库用过一次就是16位的,另外uint16_t AD_Value[20]也可以换成二维数组uint16_t AD_Value[10][2],二者本质没什么区别,好处是通道更多了就只需要改变第二个下标就行了,再其他地方处理AD数据的时候也很方便。
采样的数据:
再来看看normal模式吧(调试遇到问题了)
代码如下
/* USER CODE BEGIN 0 */
uint16_t AD_Value[20];
uint8_t Rec_Flag;
void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef* hadc)
{
Rec_Flag=1;
}
/* USER CODE END 0 */
/**
* @brief The application entry point.
* @retval int
*/
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();
/* USER CODE BEGIN Init */
/* USER CODE END Init */
/* Configure the system clock */
SystemClock_Config();
/* USER CODE BEGIN SysInit */
/* USER CODE END SysInit */
/* Initialize all configured peripherals */
MX_GPIO_Init();
MX_DMA_Init();
MX_ADC1_Init();
MX_USART1_UART_Init();
/* USER CODE BEGIN 2 */
HAL_ADC_Start_DMA(&hadc1,(uint32_t *)AD_Value,20);
/* USER CODE END 2 */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
if(Rec_Flag==1)
{
Rec_Flag=0;
HAL_ADC_Start_DMA(&hadc1,(uint32_t *)AD_Value,20);
}
HAL_Delay(500);
}
/* USER CODE END 3 */
}
补贴:
Normal模式下,结果多次尝试,最终解决了
讨论一下单次传输的好处:DMA传输的时候如果读取内存片段,会有仲裁器的问题,在以前做过FFT的例子中,需要获取一个连续间隔的AD,如取1024点,假设前面的500个点是DMA刚传输的,而后面的点是上个时刻的数据,电压数据导出到excel显示波形就有断点,但这并不影响FFT本身,前后是循环是接在一起的,出现误差的影响的是恰好500这个点会有时钟偏差(影响不太大,最多一个时钟周期,可查阅相关数据手册)。采集直流信号二者无差别!
加了一句关闭DMA的语句,更改后代码如下
/* USER CODE BEGIN 0 */
uint16_t AD_Value[20];
uint8_t Rec_Flag;
void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef* hadc)
{
Rec_Flag=1;
}
/* USER CODE END 0 */
/**
* @brief The application entry point.
* @retval int
*/
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();
/* USER CODE BEGIN Init */
/* USER CODE END Init */
/* Configure the system clock */
SystemClock_Config();
/* USER CODE BEGIN SysInit */
/* USER CODE END SysInit */
/* Initialize all configured peripherals */
MX_GPIO_Init();
MX_DMA_Init();
MX_ADC1_Init();
MX_USART1_UART_Init();
/* USER CODE BEGIN 2 */
HAL_ADC_Start_DMA(&hadc1,(uint32_t *)AD_Value,20);
/* USER CODE END 2 */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
if(Rec_Flag==1)
{
Rec_Flag=0;
HAL_ADC_Stop_DMA(&hadc1);
HAL_ADC_Start_DMA(&hadc1,(uint32_t *)AD_Value,20);
}
HAL_Delay(500);
}
/* USER CODE END 3 */
}
欢迎交流,Q:aaa@qq.com