STC15F系列中关于AD转换,数模转换如何配置—代码开源—简单易懂超详细

首先,关于AD转换有两个比较重要的寄存器

P1ADF寄存器

ADC_CONTR寄存器

这两个寄存器均为不可位寻址寄存器,所以配置起来会比较困难一些

Q:不可位寻址是什么意思呢?

A:平时我们配置IO口的时候经常会用到sbit语句,假如我想让P00定位到P0端口的第0个引脚,那就会这样写

sbit P00 = P0^0;

但上面提到的两个寄存器却不能这么方便的进行配置,正是因为它们是不可寻址寄存器

除此之外还有两个寄存器是拿来保存转换结果的分别是ADC_RES和ADCRESL,但这储存方法还有两种,切换方法是CLK_DIV寄存器中的第五位(ADRJ)的值来的

至于为什么要这样搞我也就不太清楚了

一、端口选择

关于端口选择,上面两个寄存器中,P1ADF是专门选择AD转换的引脚的,而ADC_CONTR的后三位(CSH0、CSH1、CSH2)也是选择AD转换引脚的,所以在配置的时候这两个寄存器得相互对应起来才行

关于P1ADF选择就很简单,用哪个就让哪个置"1"就行,而另一个寄存器ADC_CONTR就得用3位代替8位来选择

但同时这三位又正好在后三位,所以通常我们用10进制赋值的之后就正好对应上去了,假如我想配置P17为AD输入,那就让ADC_CONTR = 7;就行了,因为十进制的7正好对应二进制的0111;而P1ADF寄存器就简单的用P1ADF = (0x01 << 7);这样就行了。

二、转换启动位

ADC_CONTR寄存器的第3位就是AD转换的启动位(ADC_START),当手动将其置"1"后,AD转换开始,当AD转换结束后这个位就会自动置"0",还是比较方便的。

三、转换标志位

ADC_CONTR寄存器的第4位就是AD转换的转换标志位(ADC_FLAG),每次当AD转换结束完成后,这个位就会自动置"1",需要手动将这一位重新置"0"。

四、转换速度

ADC_CONTR寄存器的第5、6位就是AD转换的速度选择(SPEED1、SPEED0),这个转换速度取决于系统时钟周期,具体配置如下

对于两位速度选择,一共就上面4种速度方式。

五、转换总开关

ADC_CONTR寄存器的第7位就是AD转换的总开关(ADC_POWER),这个不用过多解释,就是总开关,想用AD转换就必须把这个位置"1"

知道上面这些东西之后就可以愉快的进行AD转换了,这个代码是之前翻阅资料的时候找到的,同时我也是对这个函数进行了一些修改,让它变得可能好用一点

#include "STC15F2K60S2.h"
//将各个设置的标准提前宏定义好
#define ADC_POWER   0x80            //ADC 模数转换总电源			1000 0000
#define ADC_FLAG    0x10            //ADC 模数转换结束标志位  	0001 0000
#define ADC_START   0x08            //ADC 模数转换启动控制位 	0000 1000


//对于转换速度的宏定义,只用其中一个
#define ADC_SPEEDLL 0x00            //540 clocks    0000 0000
#define ADC_SPEEDL  0x20            //360 clocks 	0010 0000
#define ADC_SPEEDH  0x40            //180 clocks 	0100 0000
#define ADC_SPEEDHH 0x60            //90 clocks 	0110 0000

/*========================================================
*功能描述:	获取P1指定引脚的AD转换值
*参数说明:	H -> P1上某个IO值
*						(假如我想获取P1.0上的AD转换值
*						那么直接GetADCResult(0)即可)
*附加说明:	无
*========================================================*/
unsigned int GetADCResult(unsigned char H)
{ 
	unsigned int Up;	//定义返回值
	ADC_RES = 0;
	ADC_RESL = 0;
	P1ASF = (0x01 << H);  
	ADC_CONTR = ADC_POWER | ADC_SPEEDLL | H | ADC_START;       
	_nop_();
	_nop_();
	_nop_(); 
	_nop_();  
	while(!(ADC_CONTR & ADC_FLAG));
	ADC_CONTR &= ~ADC_FLAG; 
	Up = ADC_RES;
	return Up; 
} 

接下来我们逐行解释这个函数,这里使用的芯片是自带AD转换的STC15F2K60S2,大部分STC芯片都能用

首先开始就是一堆的宏定义哈,因为之前也说了,涉及AD转换的两个寄存器不能进行位寻址,所以只能直接通过计算赋值来实现功能,代码中对于每个宏定义的16进制对应的2进制都有标注,可以对照上面的解释来看

函数内部,参数定义了个ch,用来选择P1端口上的哪个口进行AD转换;

开始先把两个用来储存AD转换的值进行清零操作,这样转换的值不会收到上次转换的影响;

之后P1ASF = (0x01 << H);  用来进行端口选择之一;

ADC_CONTR = ADC_POWER | ADC_SPEEDLL | H | ADC_START;  这一行是直接把总电源,速度,端口选择,启动位置"1"全部进行或运算后赋值给了寄存器里,可以说是一步到位;

4个nop延迟是为了等待AD转换的启动(其实只需要在AD总电源打开的时候需要延迟,之后就不需要延迟了)

while(!(ADC_CONTR & ADC_FLAG));这一句用当前寄存器和转换结束标志位进行与运算,如果寄存器中标志位为"0",那么与运算后的值就是0x00(0000 0000),但是如果标志位为"1",进行与运算后的值就是0x10(0001 0000),而在while中非"0"则"1",所以加一个!的标志对结果进行取反,这样就能知道这个标志位是"0"还是"1"了,从然让while正确的进行拦截,等待转换完毕。

ADC_CONTR &= ~ADC_FLAG; 这句就是重新把AD转换标志位重新置"0",等待下次AD转换。

最后两句就是把转换的结果返回出去。

最后,如果你用电位器转换后值一直都是255,而且无论怎么转都是255。

别着急,电位器有三个引脚,需要的是把两段分别解VCC和GND,然后中间接AD转换输入引脚,这样接着滑动电位器,数值才会开始变化。之前我就是被这个坑给坑到了。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值