请教一下STC12C5A60S2用中断来获取A/D的3个I/O值

qaz836045001 2018-05-10 10:48:04
各位大佬好,小弟在使用STC12C5A60S2的中断时遇到一点问题,我的想法是,在一个中断中用A/D轮流读取P1.0,P1.1,P1.2的值。但是我参考的例程有些问题,就是P1.1和P1.2的值都是P1.0的,应该是只读到了P1.0的值,或者没有清空P1.0。以下是我的代码,希望大佬们能帮忙看一下,谢谢!
#include "reg51.h"
#include "stdio.h"
#include "gsm.h"
#include "intrins.h"

/*Declare SFR associated with the ADC */
//STC12C5A60S2 特殊功能寄存器 关于AD部分的寄存器定义
sfr ADC_CONTR = 0xBC; //ADC控制寄存器
sfr ADC_RES = 0xBD; //ADC高8位数据寄存器(存AD转换的结果,共10位)
sfr ADC_LOW2 = 0xBE; //ADC低2位数据寄存器(存AD转换的结果,共10位)
sfr P1ASF = 0x9D; //P1第二功能选择寄存器

/*Define ADC operation const for ADC_CONTR*/
//ADC_CONTR寄存器的位变量定义
#define ADC_POWER 0x80 //ADC power control bit
#define ADC_FLAG 0x10 //ADC complete flag
#define ADC_START 0x08 //ADC start control bit
#define ADC_SPEEDLL 0x00 //420 clocks
#define ADC_SPEEDL 0x20 //280 clocks
#define ADC_SPEEDH 0x40 //140 clocks
#define ADC_SPEEDHH 0x60 //70 clocks

void Delay(unsigned int n); //延时函数申明
void InitADC(); //AD初始化函数申明

unsigned int ad_out0; //10位AD数据缓存
unsigned int ad_out1; //10位AD数据缓存
unsigned int ad_out2; //10位AD数据缓存

void main()
{
float ad_out_tur;
float ad_out_temp;
float ad_out_ph;

unsigned int delay;
Http_Init();
InitADC(); //AD初始化
IE = 0xa0; //允许AD中断
//Start A/D conversion
while (1)
{
EA = 0; //约间隔1秒打开AD中断,读取AD值

ad_out_tur = (ad_out0 * 5.00) / 1024; //浑浊度输出

ad_out_temp = (ad_out1 * 1.00) / 1024; //温度输出

ad_out_ph = (-5.65 * (ad_out2 * 5.00 / 1024) + 23.97); //PH输出

Http_Init();
Http_Send(ad_out_tur,ad_out_temp,ad_out_ph); //发送浑浊度、温度、PH

if(delay++ > 6000) //约1秒读取一次AD值
{
delay = 0;
EA = 1;
}
}
}


/*----------------------------
ADC interrupt service routine
----------------------------*/

void adc_isr() interrupt 5 using 1
{
ADC_CONTR &= !ADC_FLAG; //Clear ADC interrupt flag
ADC_CONTR = ADC_POWER | ADC_SPEEDLL | ADC_START | 000;
ad_out0 = (ADC_RES << 2) + ADC_LOW2; //高8位+低2位


ADC_CONTR &= !ADC_FLAG; //Clear ADC interrupt flag
ADC_CONTR = ADC_POWER | ADC_SPEEDLL | ADC_START | 001;
ad_out1 = (ADC_RES << 2) + ADC_LOW2; //高8位+低2位


ADC_CONTR &= !ADC_FLAG; //Clear ADC interrupt flag
ADC_CONTR = ADC_POWER | ADC_SPEEDLL | ADC_START | 010;
ad_out2 = (ADC_RES << 2) + ADC_LOW2; //高8位+低2位

}

/*----------------------------
Initial ADC sfr
----------------------------*/
void InitADC()
{
P1ASF = 0xff; //设置P1为A/D
ADC_RES = 0; //Clear previous result
ADC_LOW2 = 0;
ADC_CONTR = ADC_POWER | ADC_SPEEDLL | ADC_START | 000;
Delay(2); //ADC power-on delay and Start A/D conversion

ADC_CONTR = ADC_POWER | ADC_SPEEDLL | ADC_START | 001;
Delay(2); //ADC power-on delay and Start A/D conversion

ADC_CONTR = ADC_POWER | ADC_SPEEDLL | ADC_START | 010;
Delay(2); //ADC power-on delay and Start A/D conversion
}

/*----------------------------
Software delay function
----------------------------*/
void Delay(unsigned int n)
{
unsigned int x;

while (n--)
{
x = 5000;
while (x--);
}
}
...全文
1166 1 打赏 收藏 转发到动态 举报
写回复
用AI写文章
1 条回复
切换为时间正序
请发表友善的回复…
发表回复
tianxj001 2018-05-16
  • 打赏
  • 举报
回复
ADC中断不是这样用的,这里所谓ADC中断应该是ADC转换完成后的中断申请吧,如果你非要在ADC中断里面进行通道切换,那你必须进行中断计数,或者进行已知的ADC通道寄存器数据,进行条件判断,然后根据计数或者判断结果,在ADC中断里面刷新ADC通道,然后,你就可以在下次中断里面,获取完成的该通道数据。 正常多通道ADC程序,典型的是这样做的: 如果非要采用ADC中断方式,那么,由于中断函数是不会向外面传递数据的,因此你必须设置一个全局寄存器,用来保存ADC结果。 然后我们可以在主函数,不断的循环切换ADC通道,并通过合理的时间后,去读取该全局寄存器,获取该通道数据,然后进行处理。 根据你要求的,其实采用轮询法更简单。 就一个ADC转换----等待完成-----返回测试数据的 ADC转换函数 然后主函数里面,用for循环或者什么 切换ADC通道,调用该ADC转换函数,直接获取结果、、处理、、、、

27,373

社区成员

发帖
与我相关
我的任务
社区描述
硬件/嵌入开发 单片机/工控
社区管理员
  • 单片机/工控社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧