GD32实战__ADC

[复制链接]
82|5
 楼主 | 2019-7-10 12:08 | 显示全部楼层 |阅读模式
原理

​        我们知道自然界中很多量都是模拟量,而CPU只能识别数字量,为此,我们按一定的时间间隔对模拟量进行采样,并把采集到的值转换成数字量。

​        一般情况,ADC都要经过采样,保持,量化,编码四个过程。


使用特权

评论回复
 楼主 | 2019-7-10 12:09 | 显示全部楼层
如何实现

首先,我们看下如何实现一个简单的ADC,如下图,

watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzE3ODU0NjYx,size_16,color_FFFFFF,t_70.jpg


使用特权

评论回复
 楼主 | 2019-7-10 12:09 | 显示全部楼层
模拟信号从UI输入后,通过比较器与UREF(假设是+UREF=3.2V,-UREF=0V)进行比较,每当采样脉冲到来时,就完成一次转化,转化结果如下表,参考下表,CPU只要读取编码器输出值,就可以知道模拟输入UI的电压值了。
673935d2565059284f.png

使用特权

评论回复
 楼主 | 2019-7-10 12:10 | 显示全部楼层
重要参数
ADC有下面几个重要参数必须掌握,可能不同芯片还会提供一些其他的功能参数,但是本质上都离不开下面几个参数。

分辨率

​        如上例中,编码器输出只有3个bit,最多能分辨UREF/3bit=3.2/2^3=0.4V,那么这个ADC的分辨率就是3位的。可见,分辨率代表了ADC对模拟量的识别精度。

转换时间

​        如上例中,假设比较器输出要1us,编码器输出3us,那么该ADC最快1+3=4us才能完成转换,这个就是转化时间。可见,转化时间代表了ADC的转化速度。至此,可以理解采样脉冲的时间间隔至少应该大于转换时间。

输入范围

​        如上例中,输入的模拟信号是通过比较器跟参考电压进行比较才能完成采样和转换的,如果超出参考电压的范围,上述电路肯定无法正常工作,因此,输入范围是-UREF到+UREF。


使用特权

评论回复
 楼主 | 2019-7-10 12:10 | 显示全部楼层
使用举例硬件设计

20190614093537543.jpg

如图,我们采集可变电阻的电压值。


使用特权

评论回复
 楼主 | 2019-7-10 12:11 | 显示全部楼层
软件设计
代码很简单,如下

static VOID ADC_GpioConfig(VOID)
{
    GPIO_InitPara GPIO_InitStructure;

    GPIO_InitStructure.GPIO_Pin = GPIO_PIN_3;
    GPIO_InitStructure.GPIO_Speed = GPIO_SPEED_50MHZ;
    GPIO_InitStructure.GPIO_Mode = GPIO_MODE_AIN;
    GPIO_Init(GPIOC, &GPIO_InitStructure);
}

static VOID ADC_AdcConfig(VOID)
{
    ADC_InitPara ADC_InitStructure;

    ADC_InitStructure.ADC_Mode = ADC_MODE_INDEPENDENT;
    ADC_InitStructure.ADC_Mode_Scan = DISABLE;
    ADC_InitStructure.ADC_Mode_Continuous = ENABLE;
    ADC_InitStructure.ADC_Trig_External = ADC_EXTERNAL_TRIGGER_MODE_NONE;
    ADC_InitStructure.ADC_Data_Align = ADC_DATAALIGN_RIGHT;
    ADC_InitStructure.ADC_Channel_Number = 1 ;
    ADC_Init(ADC1, &ADC_InitStructure);

    ADC_RegularChannel_Config(ADC1, ADC_CHANNEL_13, 1, ADC_SAMPLETIME_71POINT5);
    ADC_Enable(ADC1, ENABLE);
    ADC_Calibration(ADC1);
    ADC_SoftwareStartConv_Enable(ADC1, ENABLE);
}

VOID DRV_ADC_Init(VOID)
{
    RCC_APB2PeriphClock_Enable(RCC_APB2PERIPH_GPIOC , ENABLE);
    RCC_APB2PeriphClock_Enable(RCC_APB2PERIPH_ADC1, ENABLE);
    RCC_ADCCLKConfig(RCC_ADCCLK_APB2_DIV12);

    ADC_GpioConfig();
    ADC_AdcConfig();
}

U16 DRV_ADC_GetConversionValue(VOID)
{
    return ADC_GetConversionValue(ADC1);
}


使用特权

评论回复
扫描二维码,随时随地手机跟帖
您需要登录后才可以回帖 登录 | 注册

本版积分规则

我要发帖 投诉建议 创建版块 申请版主

快速回复

您需要登录后才可以回帖
登录 | 注册
高级模式

论坛热帖

在线客服 快速回复 返回顶部 返回列表