单片机/MCU论坛
直播中

聂华川

6年用户 32经验值
擅长:可编程逻辑 电源/新能源 制造/封装 模拟技术 EDA/IC设计 控制/MCU
私信 关注
[问答]

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

各位大佬好,小弟在使用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--);
    }
}


回帖(4)

QXF

2018-5-11 10:46:18
加qq1481670533解决问题
举报

勇哥-lzu

2018-5-11 17:07:17
建议使用库函数版本的,获取AD很简单
举报

武林

2018-5-11 21:15:35
本帖最后由 wulinwl 于 2018-5-11 21:18 编辑

每次中断只转换一个通道,分三次转换,如此反复。
/*----------------------------
Initial ADC sfr
----------------------------*/
void InitADC()
{
    P1ASF = 0x07;                   //设置P1.0~1.2口为AD口
    ADC_RES = 0;                    //清除结果寄存器高8位
        ADC_LOW2= 0;                    //清除结果寄存器低2位
    ADC_CONTR = ADC_POWER | ADC_SPEEDLL | ADC_START | 0x00;//启动转换
    Delay(2);                       //ADC上电并延时
}
/*----------------------------
ADC interrupt service routine
----------------------------*/

void adc_isr() interrupt 5 using 1
{
        static unsigned char CH=0;
        switch(CH)
        {                        
                case 0:
                ADC_CONTR &= !ADC_FLAG;        //Clear ADC interrupt flag        
                ADC_CONTR = ADC_POWER | ADC_SPEEDLL | ADC_START |CH;
                ad_out0 = (ADC_RES << 2) + ADC_LOW2; //高8位+低2位
                CH++;
                break;

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

                case 2:
                ADC_CONTR &= !ADC_FLAG;        //Clear ADC interrupt flag
                ADC_CONTR = ADC_POWER | ADC_SPEEDLL | ADC_START |CH;
                ad_out2 = (ADC_RES << 2) + ADC_LOW2;//高8位+低2位  
                CH=0;
                break;
        }               
}
举报

alonggege

2019-7-17 14:20:35
不错,很好的经验分享,这方面资料欠缺,非常感谢,麻烦了,谢谢。
举报

更多回帖

发帖
×
20
完善资料,
赚取积分