前期准备:
选择STM32F103RCTx系列芯片,配置时钟的同时会自动配置IO口引脚
将HCLK设置为最大频率72MHz
ADC即模拟数字转换器(Analog-to-digital converter)是用于将模拟形式的连续信号转换为数字形式的离散信号的一类设备。一个模拟数字转换器可以提供信号用于测量。与之相对的设备成为数字模拟转换器。
简单来说就是将看不见摸不着的数据转换成我们能直观看到感受到的数字
比如空气中的温度、湿度。
你真的知道周围空气中真实的温度和湿度吗?你了解到的温度无非是温度计、手机上看到的数字,原来人体的温度是37°,37°是这么个感觉
12位ADC是一种逐次逼近型模拟数字转换器。它有,3个ADC控制器,多达18个通道,可测量16个外部和2个内部信号源。各通道的A/D转换可以单次、连续、扫描或间断模式执行。ADC的结果可以左对齐或右对齐方式存储在16位数据寄存器中。
12位ADC, 即212 = 4096, 也就是说你希望采集到的量被分成了4096份,根据测出的ADC值即可推出实际的值
例:一节电池的最大电压为3V,现在用了一些电,我不知道还剩多少电,我用12位ADC测一下,测得的ADC值为2048。3V被分成了4096份,现在还剩2048份,也就是现在还剩1.5V
实际电压 = ( 测得的ADC / 4096 ) * 3 V
STM32共有3个ADC:
ADC1
ADC2
ADC3
1 单次转换模式: 只执行一次转换
2 连续转换模式: 转换结束之后马上开始新的转换
3 扫描模式: 对所有所选中的通道进行转换
4 间断模式: 触发一次,转换一个通道
总结:
ADC数据是12位精度的,但是数据是存储在 16 位数据寄存器中,所以ADC的存储结果可以分为左对齐或右对齐两种方式
因为ADC是采集的模拟信号,电压不能过大,基本上都是在 0~3.3V
下面就以ADC1_IN3 PA3 引脚为例
ADC转换时间 = 采样时间 + 12.5个周期
例:ADCCLK(ADC时钟)=14MHz(最大),采样时间为1.5Cycles(最快),ADC转换时间 = 1.5 + 12.5 = 14周期 = 1us
配置USART有讲过,这里和下面涉及USART的知识点快进不再讲解,不了解的具体请看
【STM32】HAL库 CubeMX例程三—串口中断通信(2)(附工程源码)
工程管理依旧是这几个选项,然后GENERATE CODE,STM32CubeMX部分完成。
//ADC函数
• HAL_ADC_Start(&hadcx); //轮询模式开启ADC
• HAL_ADC_Start_IT(&hadcx); //中断轮询模式开启ADC
• HAL_ADC_Start_DMA(&hadcx); //DMA模式开启ADC
• HAL_ADC_Stop() //轮询模式关闭ADC
• HAL_ADC_Stop_IT() //中断轮询模式关闭ADC
• HAL_ADC_Stop_DMA() //DMA模式关闭ADC
• HAL_ADCEx_Calibration_Start(&hadcx); //ADC校准函数
• HAL_ADC_GetValue() //读取ADC转换值
• HAL_ADC_PollForConversion(&hadc1, 50); //等待转换结束函数,50为等待时间(ms)
• HAL_ADC_ConvCpltCallback() //ADC中断回调函数,转换完成后回调,DMA模式下DMA传输完成后调用
• HAL_ADC_ConfigChannel() //配置规则组通道
• HAL_ADC_AnalogWDGConfig() //看门狗配置
首先在stm32f1xx_hal.c中重写fgetc和fputc函数
/* Includes ------------------------------------------------------------------*/
#include "stm32f1xx_hal.h"
#include
extern UART_HandleTypeDef huart1;
int fputc(int ch, FILE *f)
{
HAL_UART_Transmit(&huart1, (uint8_t *)&ch, 1, 0xffff);
return ch;
}
int fgetc(FILE *f)
{
uint8_t ch = 0;
HAL_UART_Receive(&huart1, &ch, 1, 0xffff);
return ch;
}
接着在main.c文件定义一个变量
/* USER CODE BEGIN PTD */
uint16_t ADC_Value; //ADC值
/* USER CODE END PTD */
在ADC初始化之后加上AD校准函数
MX_ADC1_Init();
MX_USART1_UART_Init();
/* USER CODE BEGIN 2 */
HAL_ADCEx_Calibration_Start(&hadc1); //AD校准
/* USER CODE END 2 */
接着在while里写
while (1)
{
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
HAL_ADC_Start(&hadc1); //启动ADC转换
HAL_ADC_PollForConversion(&hadc1, 50); //等待转换完成,时间为50ms
if(HAL_IS_BIT_SET(HAL_ADC_GetState(&hadc1), HAL_ADC_STATE_REG_EOC))
{
ADC_Value = HAL_ADC_GetValue(&hadc1); //获取AD值
printf("ADC1 读取 : %d \r\n",ADC_Value);
printf("PA3 实时电压 : %.4f \r\n",ADC_Value*3.3f/4096);
}
HAL_Delay(1500);
}
/* USER CODE END 3 */
本期工程文档——>Gitee