早就听说,STC15系列单片机有AD转化功能,不过一直没用过,最近再给本科生做课程设计,课程要求利用STC15系列单片机读取煤气和酒精浓度。然后本人决定通过MQ2和MQ3分别读取酒精浓度和煤气浓度,然后买到的模块输出的是测量到的模拟量,也就要进行相应的转化,但是翻遍本站也没有找到怎么读取两个AD值的相关博客,然后本人看了看STC的技术手册,最终实现了,在这分享一下,给有需要的人,新人第一次写博客还是很不成熟的,还望大家多多包涵。
首先的话,先介绍一下STC15如何进行AD转化吧。
A/D转化器结构
从上图可以看出,通过模拟多路开关,将通过ADC0~7的模拟量输入送给比较器。用数/模转换器(DAC)转换的模拟量与输入的模拟量通过比较器进行比较,将比较结果保存到逐次比较寄存器,并通过逐次比较寄存器输出转换结果。但是需要说明的一点是尽管这八个端口都能进行AD转化,但是每次只能选择一个端口进行读取。
相关配置寄存器
这个寄存器的功能就是打开对应的IO口,如P1ASF.0=1;就是把P1.0口的AD功能打开了。
ADC控制寄存器ADC_CONTR
其中,ADC_POWER是ADC电源控制位。0:关闭电源。1:打开电源。
SPEED1,SPEED0是AD转化所读控制位。
ADC_FLAG是模数转换器结束标志位,完成后ADC_FLAG=1,要软件清零。
ADC_START是模数转换器转换启动控制位,ADC_START=1开始转换,结束后自动清零。
CHS2/CHS1/CHS0是模拟输入通道选择,这也就是咱们如果实现串行读取最重要的配置。
还有的话就是ADC结果调成寄存器,ADRJ用于控制ADC转化后结果存储的位置。
最后是,特殊功能寄存器ADCRES和ADCRESL寄存器用于保存A/D转换结果。
在完成相关的配置介绍之后,最后给出代码。
首先是初始化代码
#define nop _nop_()//延时
#define ADC_POWER 0x80//开电源
#define ADC_START 0x08//AD转换启动控制。
#define ADC_FLAG 0x10//AD转换结束标志
#define ADC_SPEEDH 0x40//转换速度为180个时钟周期
#define ADRJ 0X20 //ADRJ=1
/***************AD初始化函数****************
数据存放方式为高两位低八位;
开启电源;
设置转换速度;unsigned int Del_50ms
*******************************************/
void adc_init(unsigned int dk)
{
P1ASF=0X01;//P1ASF.0=1;//设置P1为模拟量输入
CLK_DIV=CLK_DIV|ADRJ;//ADRJ=1
ADC_CONTR = ADC_POWER|ADC_SPEEDH|dk;
//设置AD电源开启、转换速度设置、AD输入端口
nop;nop;nop;nop;//延时4个机械周期
}
通过对dk的设置,也就配置输入通道选择寄存器,CHS2/CHS1/CHS0三位实现了对端口的选择。
之后的话是得到转化值得函数
unsigned int get_adc()
{
unsigned int i,j;
ADC_CONTR=ADC_CONTR|ADC_START;//开始转换
while((ADC_CONTR&ADC_FLAG)!=ADC_FLAG);//等待转换标志位
i=ADC_RES;
j=ADC_RESL;
i=i<<8;
i=i|j;
ADC_CONTR=ADC_CONTR&~ADC_FLAG;//清零转换标志位
ADC_RES=0;//数据清零
ADC_RESL=0;//数据清零
return(i);
}
转化后得结果以16进制形式输出。
最后是main函数
void main()
{
while(1)
{
adc_init(0x00);//打开AD,配置AD转化,通过P10读取第一个传感器得值
DAT= get_adc();//把转换好的AD数据赋给DAT
DAT=DAT*0.0475;//把DAT转换为十进制数
h1=DAT;
Delay_500ms();
adc_init(0x01);//打开AD,配置AD转化,通过P11读取第二个传感器得值
DAT= get_adc();//把转换好的AD数据赋给DAT
DAT=DAT*0.0475;//把DAT转换为十进制数
h2=DAT;
}
}
这样也就在h1和h2两个变量内存储了两个传感器得数据。也就实现了我们最开始任务,串行读取两个传感器的数据。 就尽管STC15系列单片机尽管有8个io口可以进行AD,但是每次只能选择一个,本人进行了多次配置进而实现了对两个传感器数据的读取。当然除了这个方案的话,还有别的方案,这个给出供大家思考,也就是通过继电器控制不同的传感器导通,这样的话,也就可以实现只用一个io口,对不同传感器的读取,这也是一种串行读取的方式。