1. 选择使用的通道
2. 参数配置 独立模式、数据右对齐、扫描转换(多通道默认配置)、连续扫描、使能常规转换组、6通道、软件触发、Rank单独配置,否则全部默认一样的,到时候采样值全是第一个通道的
3.DMA
F103板子12位AD,半字足够了。
同样的配置,配置了ADC3的3个通道。
4. 中断配置(看一眼,全局中断是否开启是否影响DMA中断,待测试(反正开启没问题))
5.代码修改:在生成的代码中
main.c 初始化:
HAL_ADCEx_Calibration_Start(&hadc1);//ADC校准 HAL_UARTEx_ReceiveToIdle_DMA(&huart1,rx_buffer,BUFFER_SIZE);//打开DMA接收 HAL_ADCEx_Calibration_Start(&hadc3);//ADC校准 HAL_ADC_Start_DMA(&hadc1,(uint32_t *)ADC1_convert,adc1_convert_num);
adc.h 添加:
#define adc1_convert_num 30 //ADC1转化数据量,,每转换30个数据 DMA进行一次数据转移 #define adc1_channel 6 //ADC1使用的通道数 6个 #define adc3_convert_num 9 //ADC3转化数据量,每转换9个数据 DMA进行一次数据转移 #define adc3_channel 3 //ADC3使用的通道数 6个 //extern uint32_t ADC1_convert[10][6];//转换数据缓存,定义60个,用了一半 extern uint16_t ADC1_convert[10][6];//转换数据缓存 //extern uint32_t ADC3_convert[6][3];//转换数据缓存,定义18个,只用了一半 extern uint16_t ADC3_convert[6][3];//转换数据缓存
adc.c 添加:
/* 对应CUbemx里DMA设置的转存数据位宽 ** Word: uint32_t ** HalfWord: uint16_t, 在开启ADC_DMA时,只需强制转化地址指针,例如/ ** HAL_ADC_Start_DMA(&hadc1,(uint32_t *)ADC1_convert,24); */ //uint32_t ADC1_convert[10][6] = {0};//ADC1数据转存,每次可存储10组X6通道数据,每次刷新定义的数据量adc1_convert_num 个数 uint16_t ADC1_convert[10][6] = {0};//ADC1数据转存,每次可存储10组X6通道数据,每次刷新定义的数据量adc1_convert_num 个数 //uint32_t ADC3_convert[6][3];//ADC3数据转存,每次可存储6组X3通道数据,每次刷新定义的数据量adc3_convert_num 个数 uint16_t ADC3_convert[6][3];//ADC3数据转存,每次可存储6组X3通道数据,每次刷新定义的数据量adc3_convert_num 个数 /* USER CODE END 0 */
添加标志位与转存区域:
uint8_t ADC1_Rec_Flag;//ADC1转换完成标志 uint8_t ADC2_Rec_Flag;//ADC2转换完成标志 uint8_t ADC3_Rec_Flag;//ADC3转换完成标志 uint16_t ADC1_temp[10][6] = {0};//ADC1转化数据转存 //uint32_t ADC1_temp[10][6] = {0};// uint16_t ADC3_temp[6][3] = {0};//ADC3转化数据转存 //uint32_t ADC3_temp[6][3] = {0};//
重定义AD转换完成回调函数:void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef* hadc)
void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef* hadc) { if((hadc == &hadc1)&&(HAL_IS_BIT_SET(HAL_ADC_GetState(&hadc1),HAL_ADC_STATE_REG_EOC))) { ADC1_Rec_Flag = 1; } if((hadc == &hadc3)&&(HAL_IS_BIT_SET(HAL_ADC_GetState(&hadc3),HAL_ADC_STATE_REG_EOC))) { ADC3_Rec_Flag = 1; } }
任务函数添加:
void Start_Task2(void const * argument) { /* USER CODE BEGIN Start_Task2 */ uint16_t task2_ram_availa =0; uint8_t loop1 = 0,loop2 = 0;//循环次数计数 /* Infinite loop */ for(;;) { if(ADC1_Rec_Flag ==1) { ADC1_Rec_Flag = 0; /*停止DMA转存 HAL_ADC_Stop_DMA(); ** 1. 用于将采样数据从缓冲区转移至指定区域,后再开启DMA,期间数据不更新,避免同时读写 ** 2. 处理数据错位问题(经测试,不停止DMA对数据连续性没有影响,该用法保留) */ HAL_ADC_Stop_DMA(&hadc1); for(loop1 = 0;loop1<adc1_convert_num/adc1_channel;loop1++) { for(loop2 =0;loop2<adc1_channel;loop2++) { ADC1_temp[loop1][loop2] = ADC1_convert[loop1][loop2]; } } /* HAL_ADC_Start_DMA(ADC_HandleTypeDef* hadc, uint32_t* pData, uint32_t Length) ** hadc: 当前使用的ADC编号 ** pData:ADC采样后,DMA转存采样值的保存地址, ** Length:数据量,为配置的通道数n的倍数,假设为K,每次完成Length=N*k个数据的转换后,调用回调函数/ ** void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef* hadc); */ HAL_ADC_Start_DMA(&hadc1,(uint32_t *)ADC1_convert,adc1_convert_num); } if(ADC3_Rec_Flag ==1) { ADC3_Rec_Flag = 0; /*停止DMA转存 HAL_ADC_Stop_DMA(); ** 1. 用于将采样数据从缓冲区转移至指定区域,后再开启DMA,期间数据不更新,避免同时读写 ** 2. 处理数据错位问题(经测试,不停止DMA对数据连续性没有影响,该用法保留) */ HAL_ADC_Stop_DMA(&hadc3); for(loop1 = 0;loop1<adc3_convert_num/adc3_channel;loop1++) { for(loop2 =0;loop2<adc3_channel;loop2++) { ADC3_temp[loop1][loop2] = ADC3_convert[loop1][loop2]; } } /* HAL_ADC_Start_DMA(ADC_HandleTypeDef* hadc, uint32_t* pData, uint32_t Length) ** hadc: 当前使用的ADC编号 ** pData:ADC采样后,DMA转存采样值的保存地址, ** Length:数据量,为配置的通道数n的倍数,假设为K,每次完成Length=N*k个数据的转换后,调用回调函数/ ** void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef* hadc); */ HAL_ADC_Start_DMA(&hadc3,(uint32_t *)ADC3_convert,adc3_convert_num); } count_task2++; task2_ram_availa = uxTaskGetStackHighWaterMark(Task2Handle);//获取最高任务栈剩余量 printf("TASK2!__ %d,task2_ram_availa: %d\r\n",count_task2,task2_ram_availa); osDelay(5000); } /* USER CODE END Start_Task2 */ }
标签:DMA,convert,HAL,STM32CubeMX,ADC,ADC1,ADC3 From: https://www.cnblogs.com/ysyyrps-hhl/p/16603196.html