设计分享 | STM32F103RCT6实现AD单通道转化(详细)

wechat:嵌入式工程师成长日记

https://mp.weixin.qq.com/s?__biz=Mzg4Mzc3NDUxOQ==&mid=2247484191&idx=1&sn=ceb08f232c86a8da9aa78e6c3fa97e6f&chksm=cf430647f8348f51eb17c199cef1478b6497df065f2024ab94d9e8531259fdfa6df7765ecda3&token=11263168&lang=zh_CN#rdhttps://mp.weixin.qq.com/s?__biz=Mzg4Mzc3NDUxOQ==&mid=2247484191&idx=1&sn=ceb08f232c86a8da9aa78e6c3fa97e6f&chksm=cf430647f8348f51eb17c199cef1478b6497df065f2024ab94d9e8531259fdfa6df7765ecda3&token=11263168&lang=zh_CN#rd

具体功能实现

打开开关后,OLED上显示模拟值(0-4095)和电压值(0-3.3),通过调节电位器,电压值和模拟值都在不断发生变化。与此同时模拟值和电压值是映射关系,一一对应。

STM32F103RCT6原理图

器件

STM32F103RCT6,OLED屏,若干杜邦线 ,电位器,小型螺丝刀(用来旋转电位器),面包板

电位器接线图:(以STM32F103C8T6为例)

前后展示图

刚启动时:

旋转电位器后

知识介绍

ADC介绍

ADC可以将引脚上连续变化的模拟电压转化为数字量,12位ADC是一种逐次逼近型模拟数字转换器,转换时间为1us。其多达18个通道,可测量16个外部和2个内部信号源。

各通道AD转换可以单次,连续,扫描或间断模式执行。最后的数据存储在16为数据寄存器中。

输入电压范围:0-3.3V

转换结果范围:0-4095

转换单元:规则组和注入组

ADC资源:ADC1,ADC2,10个外部输入通道

模拟看门狗

可以自动检测模拟电压范围,可以检测指定通道,当AD值高于设定的上阈值和下阈值时,会自动申请中断,然后交给用户进行处理(多次中断对于系统的程序有一定影响)

作用:对外设信号起监控作用。

比如在做信号处理的时候,对于一些快速的处理和保护,最常规的方法是直接在采集中断中比较设定的最大值和最小值

数据对齐

数据可以左对齐或者是右对齐。对于规则组通道,不需要减去偏移值,因此只有12位有效数据,但是数据寄存器是16位。(一般采用右对齐)

左移一次相当于乘以2

数据校准

ADC有个内置的自校准模式,校准可以大幅减少因内部电容器组的变化而造成的准精度误差,校准期间,每个电容器中都会计算一个误差修正码,用于消除随后的转化中每个电容器产生的误差

建议在每一次上电后都执行一次校准

启动校准前,ADC必须处于关电状态至少超过两个ADC时钟周期

外围电路设计

第一个是利用滑动变阻器,当滑动变阻器往下的时候,电压减小;往上滑时,电压增大。

第二个是利用传感器模块,可以等效为可变电阻,利用串联分压来反映电压变化情况

对应电位器接线图:电位器中间引脚接PA0,左右引脚分别接地和接正极

AD转化

转化步骤:采样,保持,量化,编码

总转化时间:TCONV = 采样时间+12.5个ADC周期

ADC周期是RCC六分频来的14Mhz

最快转化时间:当ADCCLK=14Mhz时,采样时间为1.5个ADC周期

TCONV = 1.5+12.5=14周期=1us

规则组的四种模式

①单次转换非扫描模式:

下图是ADC对通道2进行模数转换,一段时间转换完成后,结果会放在数据寄存器中,同时EOC标志位置1,最后在数据寄存器中读取结果。

(EOC:转换结束位,该位在通道组转换结束时设置,由软件清楚或由读取ADC_DR时清除。

其中0:转换未完成;1:转换完成)

②连续转换非扫描:

在一次转换后不会停止,而是立刻开始下一轮的转换,一直持续下去,直接从数据寄存器中读AD值

优点:开始转换时无需等待,因为一直在转换,无需手动转换。

③单次转换扫描:

扫描模式用到序列列表,每个通道可以任意指定,并且可以重复。但是规则组单次只能传输一个通道的数据,所以为了防止数据被覆盖,需要用DMA对数据进行转运,当通道全部转换完成后,产生EOC信号。

④连续转换扫描:

和非连续扫描模式同理,但是一次转换完成后立刻开始下一轮转换

主函数代码(C语言)KEIL5实现

//main.c

#include "stm32f10x.h"

#include "Delay.h"

#include "OLED.h"

#include "AD.h"

uint16_t ADValue;

float Voltage;

int main(void)

{

OLED_Init();

AD_Init();

OLED_ShowString(1, 1, "ADValue:");

OLED_ShowString(2, 1, "Volatge:0.00V");

while (1)

{

ADValue = AD_GetValue();

Voltage = (float)ADValue/4095 * 3.3;



OLED_ShowNum(1,9,ADValue,4);

OLED_ShowNum(2,9,Voltage,1);

OLED_ShowNum(2,11,(unsigned int)(Voltage*100) % 100,2);

Delay_ms(100);

}

}



//AD.c

#include "stm32f10x.h"

void AD_Init(void)

{

RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);

RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1,ENABLE);

RCC_ADCCLKConfig(RCC_PCLK2_Div6);

GPIO_InitTypeDef GPIO_InitStructure;

GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AIN;

GPIO_InitStructure.GPIO_Pin=GPIO_Pin_0;

GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;

GPIO_Init(GPIOA,&GPIO_InitStructure);

ADC_RegularChannelConfig(ADC1,ADC_Channel_0,1,ADC_SampleTime_55Cycles5);

ADC_InitTypeDef ADC_InitStructure;

ADC_InitStructure.ADC_DataAlign=ADC_DataAlign_Right;

ADC_InitStructure.ADC_ContinuousConvMode=DISABLE;

ADC_InitStructure.ADC_Mode=ADC_Mode_Independent;

ADC_InitStructure.ADC_ExternalTrigConv=ADC_ExternalTrigConv_None;

ADC_InitStructure.ADC_NbrOfChannel=1;

ADC_InitStructure.ADC_ScanConvMode=DISABLE;

ADC_Init(ADC1,&ADC_InitStructure);

ADC_Cmd(ADC1,ENABLE);

ADC_ResetCalibration(ADC1);

while(ADC_GetResetCalibrationStatus(ADC1)==SET);

ADC_StartCalibration(ADC1);

while(ADC_GetCalibrationStatus(ADC1)==SET);

}

uint16_t AD_GetValue()

{

ADC_SoftwareStartConvCmd(ADC1,ENABLE);

while(ADC_GetFlagStatus(ADC1,ADC_FLAG_EOC)==RESET);

return ADC_GetConversionValue(ADC1);

}

问题解答

Q:

为什么在配置ADCCLKConfig要选择六分频

A:

下图是RCC的时钟树,上面写着ADCCLK最大是14Mhz,其中stm32f10x系列的最大时钟频率是72Mhz,也就是最大只能是6分频,72/6=12Mhz,所以虽然始终书上说最大是14Mhz,但是最大可以达到的却只有12Mhz。

Q:

如何在上电时执行一次ADC校准?

A:

代码如下:

ADC_ResetCalibration(ADC1);

while(ADC_GetResetCalibrationStatus(ADC1)==SET);

ADC_StartCalibration(ADC1);

while(ADC_GetCalibrationStatus(ADC1)==SET);

首先进行复位校准,然后获取复位校准状态,然后ADC开始转化,最后获取ADC转化状态

wechat:嵌入式工程师成长日记

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值