用户工具

站点工具


侧边栏

抱歉,您没有权限增加页面
4.单片机入门教程:9.adc电压采集

单片机入门教程之ADC电压采集

一:ADC是干什么的?

模数转换器(Analog to Digital Converter)简称ADC,就是把模拟信号转为数字信号。比如检测光敏电阻电压变化,电池电压等,这些输出的都是一定范围的模拟电压信号,单片机的数字IO口是无法检测电压变化的,这时候就需要用到ADC转换器,把电压变化范围采集转换成相应的数字值来进行处理。

ADC有8位10位12位等, 8位代表把ADC的参考电压分成2的8次方256份数字量。同样,10位就是分成2的10次方1024份。假设电池电压3.7V,ADC模拟参考电压为5V,我们用8位的ADC来进行测量,那么转换成数字值就是:3.7÷(5÷256) ≈189,在单片机中189这个数字量就代表3.7V电压。ADC位数越高,测量的电压分辨率就越高。

下面通过一个芯片来了解下ADC,挑个最常用的ADC0832,很老的一个片子了,就像七八十年代的老歌总让人回味。很多关于单片机的书上都有介绍,ADC0832 是美国国家半导体公司生产的一种8 位分辨率、双通道A/D转换芯片,先看下芯片管脚说明:

CH0和CH1是ADC的两个模拟电压输入通道,芯片启动和转换通过串行总线和单片机进行数据通信,注意REF这个管脚,这个是ADC参考电压输入,参考电压这个在ADC中是个很重要的参数,这个芯片的参考电压是和电源VCC接在一起的,VCC电压是5V则ADC参考电压也是5V,8位的ADC,则每一份的电压代表的数字值=5÷256,有些精密的ADC转换器有独立的REF参考电压输入管脚。CH0和CH1输入的模拟电压不能大于参考电压。

举个例子,如何用8位的ADC来测量电压呢?在代码中,电压通过ADC通道采集转换后的数字值单片机是知道多少的,然后就可以反过来计算出正在测量的那个电压是多少了,如:单片机从通道CH0得到转换后的数字值是180,则:5/255*180≈3.52V。

传统的51系列单片机内部没有AD功能,如果要使用ADC采集功能,就得外加芯片来解决,这无疑增加了成本,后来,一些增强型的51单片机出现,内部自带10位ADC,我们只要操作一下寄存器就可以打开使用ADC,STC12系列就是其中一种,P1口八个管脚都可以配置成ADC采集输入口。

二:开发板上ADC电压采集原理图

电路板上,调节电位器,利用电阻分压,使电压在0-5V之间变化送给单片机ADC通道0采集,单片机一共有8路通道可以输入,分别是P1.0口到P1.7口。ADC的模拟参考电压为单片机工作电压5V。

三:STC12C5A60S2的ADC相关的寄存器如下:

来看看各个寄存器的功能描述,这里只说前五个寄存器,后三个和中断有关,不管他们。
1.P1ASF:P1口模拟功能控制寄存器,当把IO口作为ADC使用时,需将P1ASF相应位置“1“配置为模拟端口,如:P1.0口作为ADC模拟口使用,则P1ASF=0x01; 其他口还可以继续作为IO口使用。
2.ADC_CONTR寄存器:ADC控制寄存器,负责打开AD转换器电源,转换速度控制及ADC输入通道选择等。
3.ADC_RES:ADC转换结果寄存器高位,用于保存AD转换结果高8位值。
4.ADC_RESL:ADC转换结果寄存器低位,用于保存AD转换结果2位值。
5.AUXR1:辅助寄存器1,只需用到ADRJ这一位,默认ADRJ=0,10位AD转换结果的高8位放在ADC_RES寄存器中,低2位放在ADC_RESL寄存器中,当ADRJ=1,则相反,一般默认,在程序中不去关心。

四:代码演示
实验现象:旋转电位器,LED灯会随电压增大和减小逐个点亮和熄灭

注:本代码完整工程在stc51 discovery开发板【实验例程】【入门实验】【实验三十二】

五:代码解释

第13行到19行,宏定义了一些ADC配置参数,后面的参数其实就是按照ADC_ CONTR寄存器中控制位写的,以宏定义的方式这样方便修改和维护。
然后跳转到第46行void AD_Init()初始化函数,器件初始化无疑就是配置必要的参数和打开开关等,然后就可以读写器件了。 第48行,P1ASF=0x01;设置P1.0为AD口。P1ASF寄存器如下:

第50行,ADC_CONTR = ADC_POWER | ADC_SPEEDLL; ADC_POWER 和ADC_SPEEDLL这个是上面的宏定义,替换后为:ADC_CONTR=0x80|0x00; 相或不影响其他位配置参数,ADC_POWER为0x80,实际上是配置ADC_CONTR寄存器B7位,打开ADC转换电源。ADC_SPEEDLL为0x00;配置B6B5使ADC转换速度为540个机器周期转换一次。

第59行,配置ADC_CONTR寄存器,设置要读取的AD通道并开始转换,上面说过ADC_CONTR = ADC_POWER | ADC_SPEEDLL | channel | ADC_START; 就等于,ADC_CONTR = 0x80 | 0x00 | channel | 0x08; 其中通道设置channel范围为0-7, ADC_CONTR寄存器说明如下。

第60到63行,使用4个_nop_();空指令延时一会等待AD转换稳定,。
第64行,while (!(ADC_CONTR & ADC_FLAG)); 查询等待AD是否转换完成,这里查询的是ADC_FLAG此标志位在ADC_CONTR寄存器中,说明如下:

第65行,ADC_CONTR &= ~ADC_FLAG; 把ADC_FLAG位软件清0不影响其他位。
第67行,ADC10Result=ADC_RES; 取出高8位转换结果寄存器ADC_RES中的值,由于寄存器是8位的,而10位AD转换结果最大是1024,所以要先取出AD转换寄存器高8位结果值,然后在合并转寄存器低2位值。
第68行,ADC10Result=ADC10Result«2|ADC_RESL; 高8位与低2位合并成10位值。
第69行,返回转换结果。

然后转回main函数大循环中
第39行,用一个int型变量读取10位AD转换结果值。
第40行,AD值为最大为1024,把得到根据电压变化的而变化的AD值除以128,分成8分,每一份对应一个LED灯,滑动电位器电压变化,就会逐个点亮LED灯。

4.单片机入门教程/9.adc电压采集.txt · 最后更改: 2017/03/06 21:37 由 wawooo