赞
踩
1、学会STM32CubeMX软件关于ADC的配置
2、掌握ADC三种模式(查询、中断、DMA)编程
3、具体目标:1、将开发板单片机采集到的电压值上传至上位机串口调试助手显示。
ADC(Analog to Digital Converter)即模数转换器,用来将模拟信号转换为数字信号。
A/D转换过程
分辨率: A/D转换器对输入模拟量微小变化的分辨能力,通常用二进制数的有效位表示。
在最大输入电压一定时,位数越多,量化单位越小,误差越小,分辨率越高。
STM32F103 系列最多有3个ADC控制器(ADC1,ADC2,ADC3),多达18个通道,可测量16个外部和2个内部信号源。各通道的A/D转换可以单次、连续、扫描或间断模式执行。ADC的结果可以左对齐或右对齐方式存储在16位数据寄存器中。ADC为12位,是一种逐次逼近型模拟数字转换器。
规则通道:
规则通道相当于你正常运行的程序,看它的名字就可以知道,很规矩,就是正常执行程序
注入通道:
注入通道可以打断规则通道,听它的名字就知道不安分,如果在规则通道转换过程中,有注入通道进行转换,那么就要先转换完注入通道,等注入通道转换完成后,再回到规则通道的转换流程。
配置选项说明:
模式设置
1、ADCs_Common_Settings DC模式设置
ADC_Mode_Independent 独立模式
独立模式模式下,双ADC不能同步,每个ADC接口独立工作。所以如果不需要ADC同步或者只是用了一个ADC的时候,应该设成独立模式,多个ADC同时使用时会有其他模式,如双重ADC同步模式,两个ADC同时采集一个或多个通道,可以提高采样率
ADC常规设置
1、Data Alignment (数据对齐方式): 右对齐/左对齐
2、Scan Conversion Mode( 扫描模式 ) :
如果只是用了一个通道的话,DISABLE,果使用了多个通道的话,会自动设置为ENABLE。
3、Continuous Conversion Mode(连续转换模式) :
设置为ENABLE,即连续转换。如果设置为DISABLE,则是单次转换。两者的区别在于连续转换直到所有的数据转换完成后才停止转换,而单次转换则只转换一次数据就停止,要再次触发转换才可以进行转换。
4、Discontinuous Conversion Mode(间断模式)
这里只用到了1个ADC,所以这个直接不使能即可。
规则通道设置
1、Enable Regular Conversions (启用常规转换模式) ENABLE
使能 否则无发进行下方配置
2、Number OF Conversion(转换通道数) 1
用到几个通道就设置为几,多个通道会自动使能扫描模式
3、Extenal Trigger Conversion Source (外部触发转换源)
默认采用:Regular Conversion launched by software 规则的软件触发 调用函数触发即可
Rank 转换顺序
1、多个通道时会有多个Rank,可以设定每个通道的转换顺序。
2、ADC总转换时间如下计算:
TCONV = 采样时间+ 12.5个周期 其中1周期为1/ADCCLK
为了保证ADC转换结果的准确性,ADC的时钟最好不超过14M。当ADCCLK=14MHz(最大),采样时间为1.5周期(最快)时,TCONV =1.5+12.5=14周期=1μs。STM32的ADC最大的转换速率为1MHz,也就是说最快转换时间为1us,
注入通道设置
1、注入通道的设置,和规则通道设置差不多。
WahchDog
1、当ADC转换的模拟电压值低于低阈值或高于高阈值时,便会产生中断。阈值的高低值由ADC_LTR和ADC_HTR配置模拟看门狗。
此项目利用printf 打印ADC采样值,先对USART1重定向,详细教程参考前面的教程:
https://blog.csdn.net/luojuan198780/article/details/138044075
代码设计:
- /* USER CODE BEGIN Includes */
-
- #include <stdio.h>
-
- /* USER CODE END Includes */
- /* USER CODE BEGIN 4 */
-
- /*********************************************************
- *
- *重定义 fputc 函数
- *
- *********************************************************/
- int fputc(int ch,FILE *f)
- {
- HAL_UART_Transmit (&huart1 ,(uint8_t *)&ch,1,HAL_MAX_DELAY );
- return ch;
- }
- /* USER CODE END 4 */
1.1CubeMX 配置 (单通道轮询)
配置:打开通道8,其他默认
1.2 程序设计
Step1 : 启用ADC
Step2 : 等待EOC标志位
Step3: 读取寄存器的数据 、<-- 查询环节
缺点:占用cpu的使用率
主要函数:
HAL_StatusTypeDef HAL_ADC_Start (ADC_HandleTypeDefhadc); //打开ADC的转换通道
HAL_StatusTypeDef HAL_ADC_Stop (ADC_HandleTypeDefhadc) //关闭ADC
HAL_StatusTypeDef HAL_ADC_PollForConversion (ADC_HandleTypeDef*hadc,uint32_t Timeout); // 查询函数
(1)在main.c中定义一个全局变量
uint16_t ADC_Value;
(2)在main 初始化中开启ADC校准
HAL_ADCEx_Calibration_Start(&hadc1); //AD校准
(3)在while 中编写ADC控制程序
- HAL_ADC_Start(&hadc1); //启动ADC转换
- HAL_ADC_PollForConversion(&hadc1, 50); //等待转换完成,50为最大等待时间,单位为ms
-
-
- if(HAL_IS_BIT_SET(HAL_ADC_GetState(&hadc1), HAL_ADC_STATE_REG_EOC))
- {
- ADC_Value = HAL_ADC_GetValue(&hadc1); //获取AD值
- printf("ADC值: %d \r\n",ADC_Value);
- printf("采样电压 : %.2f V\r\n",ADC_Value*3.3f/4096);
-
- }
- HAL_Delay(1000);
1.3 仿真效果
1.4 开发板实验效果
2.1CubeMX 配置
配置:其打开ADC中断。他与查询模式一样,
2.2 程序设计
Step1 : 启用ADC,使能中断
Step2 : 等待EOC自动触发中断
Step3: 在中断中读取寄存器的数据
主要函数
HAL_StatusTypeDef HAL_ADC_Start_IT (ADC_HandleTypeDefhadc) //使能ADC,打开中断标志位
HAL_StatusTypeDef HAL_ADC_Stop——IT (ADC_HandleTypeDefhadc)
HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef* hadc)//回调函数
(1)在main.c中定义一个全局变量
uint16_t ADC_Value;
(2)在main函数中开启ADC中断
HAL_ADC_Start_IT(&hadc1);
(3)编写中断回调函数
- void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef* hadc)//回调函数
- {
- ADC_Value = HAL_ADC_GetValue(&hadc1) * 3.3 /4096;
- printf("采样电压 : %.2f V\r\n",ADC_Value );
-
- HAL_ADC_Start_IT(&hadc1); //重新开启ADC中断转换
- }
DMA 有两种模式,分别为循环模式circular和正常模式normal
circular模式:DMA 的circular模式只需要调用一次DMA 开启函数,DMA 就会持续的搬运数据,提高了数据的刷新速度,但是在circular模式下,不管ADC新的一轮数据采集是否完成,有可能直接将旧数据搬运走.
normal模式:该模式下,DMA 启动函数调用一次,DMA 通道只会搬运一次数据,这样每调一次DMA 启动函数,DMA 只会搬运一次数据,等待数据传输完成后再次开启DMA 启动函数,这样更能保证ADC数据采集的可靠性.
3.1CubeMX 配置(circular模式)
配置1:开启连续转换
配置2:添加DMA,模式选择为循环模式circular
3.1 程序设计
(1)在main.c中定义一个全局变量
- uint16_t ADC_Value[50]={0};
- uint32_t Value=0; //存储平均值
- float Vol = 0.0; //电压值
(2)在main函数中开启ADC的 DMA
HAL_ADC_Start_DMA(&hadc1,(uint32_t*)&ADC_Value,50);
(3)在while 中编写ADC控制程序
- for(int i=0;i<50;i++)
- {
- Value+=ADC_Value[i];//求和
- }
- Value/=50; //取平均值
-
- printf("ADC值: %d \r\n",Value);
- Vol = Value*3.3/4096; //ADC最大值为4096,代表3.3V
- printf("采样电压:%.2f V\r\n",Vol);
- HAL_Delay(200);
- Value = 0;
1.1CubeMX 配置
多个通道时必须开启间断模式,并且每个间断组中只有一个通道,否则每次只能读取到每组最后一个通道的值。
1.2 程序设计
(1)在main.c中定义一个全局变量
uint16_t AD_value[2]={0};
(2)在while 中编写ADC控制程序
- for(i=0;i<2;i++)
- {
- HAL_ADC_Start(&hadc1);
- HAL_ADC_PollForConversion(&hadc1,10);
- AD_value[i]=HAL_ADC_GetValue(&hadc1);
- printf("i= %d;AD_value%d\r\n",i,AD_value[i]);
- printf("i= %d;电压值 = %.3f v\r\n",i,AD_value[i]*3.3/4096);
- }
- HAL_Delay(500);
多通道情况下使用中断来读取数据理论上是可行的,但是读取的数据会混淆,即无法确定读取的数据是属于哪一个通道的,因此一般不使用。
3.1CubeMX 配置 ,如果卡死,加大采样周期。
开启DMA并采用circular模式
3.2 程序设计
(1)在main.c中定义变量
- /* USER CODE BEGIN 1 */
- uint32_t ADC_Value1;
- uint16_t AD_Buf[100]={0};//两个通道采集数据存在这个数组里面
- /* USER CODE END 1 */
(2)在main函数中开启ADC的 DMA
- //开启ADC的校准
- HAL_ADCEx_Calibration_Start(&hadc1);
- //开启ADC的DMA,采集的数据放入 AD_Buf数组
- HAL_ADC_Start_DMA(&hadc1,(uint32_t *)&AD_Buf,100);
(3)在while 中编写ADC控制程序
- for(int i=0;i<100;i+=2)
- {
- ADC_Value1+=AD_Buf[i];//通道1求和
- }
- for(int i=1;i<100;i+=2)
- {
- ADC_Value2+=AD_Buf[i];//通道2求和
- }
-
- ADC_Value1 = ADC_Value1/50;//取平均值
- ADC_Value2 = ADC_Value2/50;
-
- printf("通道1ADC值: %d \r\n",ADC_Value1);
- printf("通道2ADC值: %d \r\n",ADC_Value2);
3.3 仿真效果
1、在DMA实验中容易卡死,一个原因是采样周期小容易卡死;
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。