本次实现的是ADC实现数字信号与模拟信号的转化,数字信号时不连续的,模拟信号是连续的。
1.ADC转化的原理
模拟-数字转换技术使用的是逐次逼近法,使用二分比较的方法来确定电压值
当单片机对应的参考电压为3.3v时,0~ 3.3v(模拟信号)对应0~4095(数字信号),假如我们知道一个数字信号的值为x,那么他对应的模拟信号
x/4095=y/3.3
y就是x对应的模拟信号
假如要确定0.8v对应的数字信号的值
他会将0.8v电压保存在电容中,然后先和3.3v的一半对应的1.65v(2048)做比较,如果小于1.65v的话,12位最高位就是0,因为1000 0000 0000 对应的就是2048
接着就是和1.65的一半比较,0.825v(1024)>0.8v,所以12位中倒数第二高位就是0,因为0.825(1024)对应二进制就是0100 0000 0000
接着0.8v和0.825的一半比较->0.4125v(512),0.8v>0.4125v,所以第三位为1,因为512对应的二进制为0010 00000000
按这个方法依次确定0.8v对应的12位的二进制数,然后这个二进制对应的十进制就是0.8v对应的数字信号的值
所以对应的过程是1.启动ADC 2.采样&转换 3.获取&计算,针对STM32F103C8T6芯片有10个外部通道,和两个内部通道(内部温度传感器,内部参考电压)进行ADC的转化,ADC1和ADC2,两个转化结构,每个转化结构都有一个注入组和一个规则组,我们现在只讲讲规则组,我们要对一个通道的电压值进行采集的时候,我们需要将这个通道注册进这个通道中,当启动ADC,然后采样转化的电压值就会放在规则通道数据寄存器(12位二进制值)中,等待获取
2.实操
单片机有一个电位器,通过旋转电位器,使得PA5的输出电压发送变化,我们将其输出到串口上去
对应的PA5刚好是ADC1的通道5
char message[50]="";
float v=0.0;
int value=0;
/* USER CODE END 2 */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
HAL_ADC_Start(&hadc1);//开启ADC1
HAL_ADC_PollForConversion(&hadc1,HAL_MAX_DELAY);//等待转换
value=HAL_ADC_GetValue(&hadc1);//从寄存器中获取电压值
v=(value/4095.0)*3.3;//转模拟信号
sprintf(message,"v:%.2f,value:%d",v,value);
HAL_UART_Transmit(&huart2,message,strlen(message),HAL_MAX_DELAY);
HAL_Delay(500);
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
}
但是发现一个问题,就是电位器扭到头
最大为3.25v,达不到3.3v,这是因为手册里面说
char message[50]="";
float v=0.0;
int value=0;
HAL_ADCEx_Calibration_Start(&hadc1);//校准
/* USER CODE END 2 */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
HAL_ADC_Start(&hadc1);//开启ADC1
HAL_ADC_PollForConversion(&hadc1,HAL_MAX_DELAY);//等待转换
value=HAL_ADC_GetValue(&hadc1);//从寄存器中获取电压值
v=(value/4095.0)*3.3;//转模拟信号
sprintf(message,"v:%.2f,value:%d",v,value);
HAL_UART_Transmit(&huart2,(uint8_t*)message,strlen(message),HAL_MAX_DELAY);
HAL_Delay(500);
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
}
其实还有一种是循环转换,只需要开启一次ADC即可
char message[50]="";
float v=0.0;
int value=0;
HAL_ADCEx_Calibration_Start(&hadc1);//校准
HAL_ADC_Start(&hadc1);//开启ADC1
HAL_ADC_PollForConversion(&hadc1,HAL_MAX_DELAY);//等待转换
/* USER CODE END 2 */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
value=HAL_ADC_GetValue(&hadc1);//从寄存器中获取电压值
v=(value/4095.0)*3.3;//转模拟信号
sprintf(message,"v:%.2f,value:%d",v,value);
HAL_UART_Transmit(&huart2,(uint8_t*)message,strlen(message),HAL_MAX_DELAY);
HAL_Delay(500);
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
}