771749862 发表于 2013-2-16 21:21:40

请教大家关于使用STC12C5A32S2的AD功能中的问题

本帖最后由 771749862 于 2013-2-17 11:11 编辑

我想用stc12c5a32s2做一个电池与市电之间的供电切换,但是看了老姚的手册很久,还是写不出需要的程序,我的要求是电池电压降到某一电压后,切换市电供电,电池是太阳能充电的,当电池电压上升到某一电压后,切换为电池供电。
我现在看老姚的手册写的程序连点LED都不行。
#include"reg52.h"
#include"intrins.h"

#define FOSC 18432000L
#define BAUD 9600

typedef unsigned char BYTE;
typedef unsigned intWORD;

uint now_val;

sfr    ADC_CONTR= 0xbc;   
sfr    ADC_RES    = 0xbd;   
sfr    ADC_LOW2   = 0xbe;   
sfr    P1ASF      = 0x9d;   

sbit LED=P0^5;

#define ADC_POWER   0x80   
#define ADC_FLAG    0x10   
#define ADC_START   0x08   
#define ADC_SPEEDLL 0x00   
#define ADC_SPEEDL0x20   
#define ADC_SPEEDH0x40   
#define ADC_SPEEDHH 0x60   


void InitADC();
BYTE GetADCResult(BYTE ch);
void Delay(WORD n);

void main()
{      
InitADC();            
while(1)
{
    now_val = GetADCResult(0) * 30 / 51 + 1,
    if(now_val>3)
        {
          LED=0;
        }
}
}

BYTE GetADCResult(BYTE ch)
{
   ADC_CONTR=ADC_POWER|ADC_SPEEDLL|ch|ADC_START;
   _nop_();
   _nop_();
   _nop_();
   _nop_();
   while(!(ADC_CONTR&ADC_FLAG));
   ADC_CONTR&=~ADC_FLAG;

   return ADC_RES;
}

void InitADC()
{
P1ASF = 0xff;      
ADC_RES = 0;
ADC_CONTR = ADC_POWER|ADC_SPEEDLL;   
Delay(2);   
}

void Delay(WORD n)
{
WORD x;

while(n--)
{
    x=5000;
    while(x--);
}
}

12tangyang12 发表于 2013-2-16 21:35:28

貌似这个不麻烦吧。切换只需个电压比较器就行了。至于要得到确定的数值 那就用AD测量吧

771749862 发表于 2013-2-16 22:25:12

12tangyang12 发表于 2013-2-16 21:35 static/image/common/back.gif
貌似这个不麻烦吧。切换只需个电压比较器就行了。至于要得到确定的数值 那就用AD测量吧 ...

测量到了电压,但是不知道怎么比较

tt98 发表于 2013-2-17 10:04:11

AD>=设定值---执行电池供电!
AD<设定值--执行市电供电!

771749862 发表于 2013-2-17 10:43:35

tt98 发表于 2013-2-17 10:04 static/image/common/back.gif
AD>=设定值---执行电池供电!
AD

上面的大侠,能不能给个模版看看

771749862 发表于 2013-2-17 12:45:16

谁能帮帮我啊

th1993 发表于 2013-2-17 16:52:50

/*********************************************************************************************
程序名:    10位ADC转换实验程序
编写人:    杜洋 
编写时间:  2010年3月24日
硬件支持:  STC12C5A60S2 使用10位ADC功能 外部晶体12MHz
接口说明:  P1.0接口接电位器
修改日志:  
  1-                                                               
/*********************************************************************************************
说明:
PC串口端设置 [ 4800,8,无,1,无 ]
将ADC读出的数值通过串口以十六进制方式显示(第一个数据是ADC高8位,第二个数据是ADC低2位)。
/*********************************************************************************************/

#include <STC12C5A60S2.H> //单片机头文件
#include <intrins.h>        //51基本运算(包括_nop_空函数)

/*********************************************************************************************
函数名:毫秒级CPU延时函数
调用:DELAY_MS (?);
参数:1~65535(参数不可为0)
返回值:无
结果:占用CPU方式延时与参数数值相同的毫秒时间
备注:应用于1T单片机时i<600,应用于12T单片机时i<125
/*********************************************************************************************/
void DELAY_MS (unsigned int a){
        unsigned int i;
        while( a-- != 0){
                for(i = 0; i < 600; i++);
        }
}
/*********************************************************************************************/

/*********************************************************************************************
函数名:UART串口初始化函数
调用:UART_init();
参数:无
返回值:无
结果:启动UART串口接收中断,允许串口接收,启动T/C1产生波特率(占用)
备注:振荡晶体为12MHz,PC串口端设置 [ 4800,8,无,1,无 ]
/**********************************************************************************************/
void UART_init (void){
        //EA = 1; //允许总中断(如不使用中断,可用//屏蔽)
        //ES = 1; //允许UART串口的中断

        TMOD = 0x20;        //定时器T/C1工作方式2
        SCON = 0x50;        //串口工作方式1,允许串口接收(SCON = 0x40 时禁止串口接收)
        TH1 = 0xF3;        //定时器初值高8位设置
        TL1 = 0xF3;        //定时器初值低8位设置
        PCON = 0x80;        //波特率倍频(屏蔽本句波特率为2400)
        TR1 = 1;        //定时器启动   
}
/**********************************************************************************************/

/*********************************************************************************************
函数名:UART串口发送函数
调用:UART_T (?);
参数:需要UART串口发送的数据(8位/1字节)
返回值:无
结果:将参数中的数据发送给UART串口,确认发送完成后退出
备注:
/**********************************************************************************************/
void UART_T (unsigned char UART_data){ //定义串口发送数据变量
        SBUF = UART_data;        //将接收的数据发送回去
        while(TI == 0);                //检查发送中断标志位
        TI = 0;                        //令发送中断标志位为0(软件清零)
}
/**********************************************************************************************/
/*********************************************************************************************
函数名:10位A/D转换初始化函数
调用:Read_init (?);
参数:输入的端口(0000 0XXX 其中XXX是设置输入端口号,可用十进制0~7表示,0表示P1.0,7表示P1.7)
返回值:无
结果:开启ADC功能并设置ADC的输入端口
备注:适用于STC12C5A60S2系列单片机(必须使用STC12C5A60S2.h头文件)
/**********************************************************************************************/
void Read_init (unsigned char CHA){
        unsigned char AD_FIN=0; //存储A/D转换标志
    CHA &= 0x07;            //选择ADC的8个接口中的一个(0000 0111 清0高5位)
    ADC_CONTR = 0x40;                //ADC转换的速度(0XX0 0000 其中XX控制速度,请根据数据手册设置)
    _nop_();
    ADC_CONTR |= CHA;       //选择A/D当前通道
    _nop_();
    ADC_CONTR |= 0x80;      //启动A/D电源
    DELAY_MS(1);            //使输入电压达到稳定(1ms即可)
}
/**********************************************************************************************/
/*********************************************************************************************
函数名:10位A/D转换函数
调用:ADC_Read ();
参数:无
返回值:无(10位ADC数据高8位存放在ADC_RES中,低2位存放在ADC_RESL中)
结果:读出指定ADC接口的A/D转换值,并返回数值
备注:适用于STC12C5A60S2系列单片机(必须使用STC12C5A60S2.h头文件)
/**********************************************************************************************/
void ADC_Read (void){
        unsigned char AD_FIN=0; //存储A/D转换标志
    ADC_CONTR |= 0x08;      //启动A/D转换(0000 1000 令ADCS = 1)
    _nop_();
    _nop_();
    _nop_();
    _nop_();
    while (AD_FIN ==0){   //等待A/D转换结束
      AD_FIN = (ADC_CONTR & 0x10); //0001 0000测试A/D转换结束否
    }
    ADC_CONTR &= 0xE7;      //1111 0111 清ADC_FLAG位, 关闭A/D转换,
}
/**********************************************************************************************/
/*********************************************************************************************
函数名:主函数
调用:无
参数:无
返回值:无
结果:程序开始处,无限循环
备注:
/**********************************************************************************************/
void main (void){
        UART_init();//串口初始程序
        Read_init(0);//ADC初始化
        P1M1 = 0x01; //P1.7~P1.0:0000 0001(高阻)//注意:更改ADC通道时须同时将对应的IO接口修改为高阻输入。
        P1M0 = 0x00; //P1.7~P1.0:0000 0000(强推)
        while(1){
          ADC_Read ();//调用ADC转换程序
          UART_T (ADC_RES); //串口小秘书,将ADC读出值高8位送入串口0000 0000
          UART_T (ADC_RESL); //串口小秘书,将ADC读出值低2位送入串口XXXX XX00
        }
}/**********************************************************************************************/
/*************************************************************

th1993 发表于 2013-2-17 16:53:38

我就是用这个,你改一改main函数就可以了

771749862 发表于 2013-2-17 22:24:40

th1993 发表于 2013-2-17 16:53 static/image/common/back.gif
我就是用这个,你改一改main函数就可以了

谢谢你的帮助

清雨影 发表于 2013-2-18 18:53:24

tt98 发表于 2013-2-17 10:04 static/image/common/back.gif
AD>=设定值---执行电池供电!
AD

最好搞个门限,否则在临界值上会蛋疼的。

sdf159372008 发表于 2013-2-19 22:29:59

你需要在某一个AD口上接一个基准。否则在电池供电的系统下会造成相当大的误差……
你在P1.7上接一个2.5V基准,那么按照下面的算式算出来的就是P1.0口的电压(测量电压不能超过基准电压,如果超过了,需要用电阻分压)
R1=(GetADCResult(0)*1.0/GetADCResult(7))*2500      ;           //电池电压
      P1.0口AD值             P1.7口AD值         基准电压(mV)   
然后进行比较(得出的值都是mV!)

另外,STC单片机AD精度和电源电压有关。

hamipeter 发表于 2013-2-20 10:15:50

顶一下!!

771749862 发表于 2013-2-20 12:26:06

sdf159372008 发表于 2013-2-19 22:29 static/image/common/back.gif
你需要在某一个AD口上接一个基准。否则在电池供电的系统下会造成相当大的误差……
你在P1.7上接一个2.5V基 ...

我试试看吧

djkc 发表于 2013-2-21 13:25:21

好资料,正好可以用到
页: [1]
查看完整版本: 请教大家关于使用STC12C5A32S2的AD功能中的问题