之前写到stm32cubemx配置采集stm32F4,本次分享如何通过配置stm32cubemx采集stm32H743IIT6。
本篇文章分享通过阻塞实现单通道和多通道的ADC的采集。
stm32cubemx的版本6.10.0。
一、阻塞采集单通道ADC数据
阻塞采集是每次采集adc数据,cpu死等,直到采集完或者在设定时间超时没能采集,返回到cpu。
配置sm32cubemx:
1、配置时钟源
使用的是25M无源晶振。
这里power regulator voltage scale 选择“Power Regulator Voltage Scale 0”,系统时钟能达到480MHz。查看数据手册
2、时基选择系统滴答定时器
3、配置时钟
配置时钟为480MHz,系统自动生成时钟树。
ADC的时钟是50MHz。
4、配置ADC
5、配置串口
6、调试模式
配置成SW模式
7、项目管理
配置完成后,生成初始化代码。
代码部分
(1)添加头文件
/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
#include "stdio.h" //添加头文件
/* USER CODE END Includes */
(2)添加打印函数
/* USER CODE BEGIN 0 */
int fputc(int c, FILE *stream) //重写fputc函数
{
/*
huart1是工具生成代码定义的UART1结构体,
如果以后要使用其他串口打印,只需要把这个结构体改成其他UART结构体。
*/
HAL_UART_Transmit(&huart1, (unsigned char *)&c, 1, 1000);
return 1;
}
/* USER CODE END 0 */
(3)添加变量
int main(void)
{
/* USER CODE BEGIN 1 */
uint32_t ADC_value;//adc读到的数据
uint8_t i;
float ADCx;//转换后的电压值
/* USER CODE END 1 */
(4)添加提示
/* USER CODE BEGIN 2 */
printf("<<<<<<<ADC 非DMA单通道采集\r\n ");
HAL_Delay(2000);
/* USER CODE END 2 */
(5)while添加采集
while (1)
{
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
printf("\r\n *****ADC 输出 *****\r\n"); //我这里设置间断数为1,也就是将1个通道分成了1组,那么我每次采集的时候都需要手动去触发ADC采集,也就是调用一次HAL_ADC_Start函数
ADC_value=0;//采集的电压值清零
for(i=0;i<50;i++)//循环采集50次
{
HAL_ADC_Start(&hadc1);//启动ADC转换,必须放在for循环中,否则只能采集第一个通道的ADC值;
HAL_ADC_PollForConversion(&hadc1,100); //用于轮询转换,是一个阻塞函数,等待转换完成,参数100ms是阻塞时间
if(HAL_IS_BIT_SET(HAL_ADC_GetState(&hadc1),HAL_ADC_STATE_REG_EOC)) //判断转换完成标志位是否设置,为1的时候产生中断。
ADC_value+=HAL_ADC_GetValue(&hadc1); //读到的ADC的值,累加
}
ADC_value=ADC_value/50;//求平均值
ADCx =ADC_value *3.3/65536;//转换成电压值
printf("AD value =%d 电压= %.2fV",ADC_value,ADCx);//打印输出
HAL_Delay(1000);
}
(6)添加adc校准函数
这里很关键!stm32cubemx初始化不包含校准函数,需要自己手动添加。
在adc.c的初始化函数void MX_ADC1_Init(void)内添加
/* USER CODE BEGIN ADC1_Init 2 */
HAL_ADCEx_Calibration_Start(&hadc1, ADC_CALIB_OFFSET, ADC_SINGLE_ENDED); /* ADC校准 */
/* USER CODE END ADC1_Init 2 */
(7)编译
stm32H7系列编译起来时间超级长
花了十分钟多。有两个解决办法:
①、不勾选“Browse information”![](https://i-blog.csdnimg.cn/direct/d25e8d976aa645f58cb657ca23be2652.png)
②编译器选择“version 6“
两个方法都能编译速度极大的提升!
运行
如果不进行校准。
对接地采集电压,
上面添加校准函数,
下面去掉校准函数。
这里就体现出校准函数的重要性!
二、阻塞采集多通道ADC数据
和阻塞采集单通道ADC数据一样的配置就不贴图了。
(1)ADC配置
配置完成后,生成初始化代码。
代码部分
(1)添加头文件
/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
#include "stdio.h" //添加头文件
/* USER CODE END Includes */
(2)添加打印函数
/* USER CODE BEGIN 0 */
int fputc(int c, FILE *stream) //重写fputc函数
{
/*
huart1是工具生成代码定义的UART1结构体,
如果以后要使用其他串口打印,只需要把这个结构体改成其他UART结构体。
*/
HAL_UART_Transmit(&huart1, (unsigned char *)&c, 1, 1000);
return 1;
}
/* USER CODE END 0 */
(3)添加变量
int main(void)
{
/* USER CODE BEGIN 1 */
uint32_t ADC_value[100];//存放采集到数据
uint32_t temp1,temp2;//存放累加值,这里要选择32位,因为adc采集的位数是16位
uint16_t ADC_value1,ADC_value2;//adc采集的值
uint8_t i;
float ADCx1,ADCx2;//转换后的电压值
/* USER CODE END 1 */
(4)添加提示
/* USER CODE BEGIN 2 */
printf("<<<<<<<ADC 非DMA多通道采集\r\n ");
HAL_Delay(2000);
/* USER CODE END 2 */
(5)while添加采集
while (1)
{
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
temp1=0; //清零
temp2=0; //清零
printf("\r\n *****ADC 输出 *****\r\n"); //我这里设置间断数为1,也就是将2个通道分成了2组,那么我每次采集的时候都需要手动去触发ADC采集,也就是调用一次HAL_ADC_Start函数
for(i=0;i<100;i++)
{
HAL_ADC_Start(&hadc1);//启动ADC转换,必须放在for循环中,否则只能采集第一个通道的ADC值;
HAL_ADC_PollForConversion(&hadc1,100); //用于轮询转换,是一个阻塞函数,等待转换完成,参数100ms是阻塞时间
if(HAL_IS_BIT_SET(HAL_ADC_GetState(&hadc1),HAL_ADC_STATE_REG_EOC)) //判断转换完成标志位是否设置,为1的时候产生中断。
ADC_value[i]=HAL_ADC_GetValue(&hadc1); //开始读ADC的值
}
for(i=0;i<50;i++)
{
temp1=temp1+ADC_value[2*i];//50次采集求和
temp2=temp2+ADC_value[2*i+1];//50次采集求和
}
ADC_value1=temp1/50; //平均值
ADC_value2=temp2/50; //平均值
ADCx1 =ADC_value1 *3.3/65536; //转化成电压值
ADCx2 =ADC_value2 *3.3/65536; //转化成电压值
printf("AD1 value =%d 电压= %.2fV ",ADC_value1,ADCx1);//打印输出
printf("AD2 value =%d 电压= %.2fV ",ADC_value2,ADCx2);//打印输出
HAL_Delay(1000);
}
(6)添加adc校准函数
这里很关键!stm32cubemx初始化不包含校准函数,需要自己手动添加。
在adc.c的初始化函数void MX_ADC1_Init(void)内添加
/* USER CODE BEGIN ADC1_Init 2 */
HAL_ADCEx_Calibration_Start(&hadc1, ADC_CALIB_OFFSET, ADC_SINGLE_ENDED); /* ADC校准 */
/* USER CODE END ADC1_Init 2 */