打印

帮我看看厂家stc15系列的例程是不是写错了

[复制链接]
4265|9
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
wolfbeard|  楼主 | 2014-7-16 14:56 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
/*---------------------------------------------------------------------*/
/* --- STC MCU Limited ------------------------------------------------*/
/* --- STC15F4K60S4 系列 通过BandGap电压精确测量外部输入电压值举例-----*/
/* --- Mobile: (86)13922805190 ----------------------------------------*/
/* --- Fax: 86-755-82905966 -------------------------------------------*/
/* --- Tel: 86-755-82948412 -------------------------------------------*/
/* --- Web: www.**.com --------------------------------------------*/
/* 如果要在程序中使用此代码,请在程序中注明使用了宏晶科技的资料及程序   */
/* 如果要在**中应用此代码,请在**中注明使用了宏晶科技的资料及程序   */
/*---------------------------------------------------------------------*/

//本示例在Keil开发环境下请选择Intel的8058芯片型号进行编译
//假定测试芯片的工作频率为18.432MHz

#include "reg51.h"
#include "intrins.h"

typedef unsigned char BYTE;
typedef unsigned int WORD;

//说明:
//    ADC的第9通道是用来测试内部BandGap参考电压的,由于内部BandGap参考电
//压很稳定,不会随芯片的工作电压的改变而变化,所以可以通过两次测量和一次计算
//便可得到外部的精确电压.公式如下:
//ADCbg / Vbg = 1023 / VCC
//ADCx / Vx   = 1023 / VCC
//由于两次测量的时间间隔很短,VCC的电压在此期间的波动可忽略不计
//从而可推出 ADCbg / Vbg = ADCx / Vx
//进一步得出 Vx = Vbg * ADCx / ADCbg
//其中:ADCbg为Bandgap电压的ADC测量值
//     Vbg为实际Bandgap的电压值,在单片机进行CP测试时记录的参数,单位为毫伏(mV)
//     ADCx为外部输入电压的ADC测量值
//     Vx外部输入电压的实际电压值,单位为毫伏(mV)
//
//具体的测试方法:首先将P1ASF初始化为0,即关闭所有P1口的模拟功能
//然后通过正常的ADC转换的方法读取第0通道的值,即可通过ADC的第9通道读取当前
//内部BandGap参考电压值ADCbg,然后测量有外部电压输入的ADC通道,测量出
//外部输入电压的ADC测量值ADCx,接下来从RAM区或者ROM区读取实际Bandgap的电压值Vbg,
//最后通过公式Vx = Vbg * ADCx / ADCbg,即可计算出外部输入电压的实际电压值Vx

//-----------------------------------------

WORD idata Vbg_RAM _at_ 0xef;               //对于只有256字节RAM的MCU存放地址为0EFH
//WORD idata Vbg_RAM _at_ 0x6f;             //对于只有128字节RAM的MCU存放地址为06FH

//注意:需要在下载代码时选择"在ID号前添加重要测试参数"选项,才可在程序中获取此参数
//WORD code Vbg_ROM _at_ 0x03f7;            //1K程序空间的MCU
//WORD code Vbg_ROM _at_ 0x07f7;            //2K程序空间的MCU
//WORD code Vbg_ROM _at_ 0x0bf7;            //3K程序空间的MCU
//WORD code Vbg_ROM _at_ 0x0ff7;            //4K程序空间的MCU
//WORD code Vbg_ROM _at_ 0x13f7;            //5K程序空间的MCU
//WORD code Vbg_ROM _at_ 0x1ff7;            //8K程序空间的MCU
//WORD code Vbg_ROM _at_ 0x27f7;            //10K程序空间的MCU
//WORD code Vbg_ROM _at_ 0x2ff7;            //12K程序空间的MCU
//WORD code Vbg_ROM _at_ 0x3ff7;            //16K程序空间的MCU
//WORD code Vbg_ROM _at_ 0x4ff7;            //20K程序空间的MCU
//WORD code Vbg_ROM _at_ 0x5ff7;            //24K程序空间的MCU
//WORD code Vbg_ROM _at_ 0x6ff7;            //28K程序空间的MCU
//WORD code Vbg_ROM _at_ 0x7ff7;            //32K程序空间的MCU
//WORD code Vbg_ROM _at_ 0x9ff7;            //40K程序空间的MCU
//WORD code Vbg_ROM _at_ 0xbff7;            //48K程序空间的MCU
//WORD code Vbg_ROM _at_ 0xcff7;            //52K程序空间的MCU
//WORD code Vbg_ROM _at_ 0xdff7;            //56K程序空间的MCU
WORD code Vbg_ROM _at_ 0xeff7;              //60K程序空间的MCU

//-----------------------------------------
                                            
sfr ADC_CONTR   =   0xBC;                   //ADC控制寄存器
sfr ADC_RES     =   0xBD;                   //ADC高8位结果
sfr ADC_LOW2    =   0xBE;                   //ADC低2位结果
sfr P1ASF       =   0x9D;                   //P1口第2功能控制寄存器
                                            
#define ADC_POWER   0x80                    //ADC电源控制位
#define ADC_FLAG    0x10                    //ADC完成标志
#define ADC_START   0x08                    //ADC起始控制位
#define ADC_SPEEDLL 0x00                    //540个时钟
#define ADC_SPEEDL  0x20                    //360个时钟
#define ADC_SPEEDH  0x40                    //180个时钟
#define ADC_SPEEDHH 0x60                    //90个时钟

/*----------------------------
软件延时
----------------------------*/
void Delay(WORD n)
{
    WORD x;

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

BYTE GetADC(BYTE ch)
{
    ADC_CONTR = ADC_POWER | ADC_SPEEDLL;
    Delay(2);                               //ADC上电并延时
    ADC_CONTR = ADC_POWER | ADC_SPEEDLL | ch | ADC_START;
    _nop_();                                //等待4个NOP
    _nop_();
    _nop_();
    _nop_();
    while (!(ADC_CONTR & ADC_FLAG));        //等待ADC转换完成
    ADC_CONTR &= ~ADC_FLAG;                 //清除ADC标志
   
    return ADC_RES;
}

void main()
{
    BYTE ADCbg;
    BYTE ADCx;
    WORD Vx;
   
//第一步:通过ADC的第2通道测试外部输入电压的ADC测量值
    ADC_RES = 0;                            //清除结果寄存器
    P1ASF = 0x02;                           //设置P1.1口为模拟通道
    GetADC(1);
    GetADC(1);
    ADCx = GetADC(1);
   
//第二步:通过ADC的第9通道测试Bandgap电压的ADC测量值
    ADC_RES = 0;                            //清除结果寄存器
    P1ASF = 0x00;                           //不设置P1ASF,即可从ADC的第9通道读取内部Bandgap电压的ADC测量值
    GetADC(1);
    GetADC(1);
    ADCbg = GetADC(1);

//第三步:通过公式计算外部输入的实际电压值
    Vx = Vbg_RAM * ADCx / ADCbg;            //使用RAM中的Bandgap电压参数进行计算
    //Vx = Vbg_ROM * ADCx / ADCbg;          //使用ROM中的Bandgap电压参数进行计算
   
    while (1);
}

我觉得这里

//第二步:通过ADC的第9通道测试Bandgap电压的ADC测量值
    ADC_RES = 0;                            //清除结果寄存器
    P1ASF = 0x00;                           //不设置P1ASF,即可从ADC的第9通道读取内部Bandgap电压的ADC测量值
    GetADC(1);
    GetADC(1);
    ADCbg = GetADC(1);

应该改为

//第二步:通过ADC的第9通道测试Bandgap电压的ADC测量值
    ADC_RES = 0;                            //清除结果寄存器
    P1ASF = 0x00;                           //不设置P1ASF,即可从ADC的第9通道读取内部Bandgap电压的ADC测量值
    GetADC(0);
    GetADC(0);
    ADCbg = GetADC(0);

否则取不出 BandGap 的ADC值

(这段例程在手册和ISP v6.75里面都有)

相关帖子

沙发
Morgancy| | 2014-7-16 15:01 | 只看该作者

使用特权

评论回复
板凳
wangch_sh| | 2014-7-16 15:32 | 只看该作者
不是第9通道吗?你那样成了第0通道了。

使用特权

评论回复
地板
gxl117| | 2014-7-16 16:05 | 只看该作者
手机上看了看文档,没看到跟你一样的代码,文档里没定义GetADC()函数,而是直接在主循环里完成的三步,并且通道号没错。版本不一样?

使用特权

评论回复
5
鉲┊布奇诺| | 2014-7-17 10:35 | 只看该作者
一般STC的范例程序是不会有什么问题的,如有疑问,可以咨询STC原厂,确实是错的话,会进行修改的,感谢您的意见

使用特权

评论回复
6
gxl117| | 2014-7-17 13:17 | 只看该作者
昨天晚上回家在电脑上看了看,发现文档里的没错,但STC-ISP下载软件里带的范例确实是错的,跟楼主的一样,通道号给错了。STC的人看到了,应该给个解释,到底P1AFS设置为0后还与ADC_CONTR里的通道设置有关没有。

使用特权

评论回复
评分
参与人数 1威望 +1 收起 理由
wolfbeard + 1 很给力!
7
wolfbeard|  楼主 | 2014-7-17 13:37 | 只看该作者
是我粗心了,手册里的没错,我的这段程序来自IPS下载程序里的范例程序,我就看了手册里的标题,以为同样标题的范例程序都一样呢.
还有一个问题:我用的stc15f2k60s2(v7.1.1s),当ISP下载时选择了"在程序区的结束处添加重要测试参数"后,在程序区应该添加BandGap电压的位置(0xeff7),没有添加该电压,而是写了0,不知道是什么原因.

使用特权

评论回复
8
如何RH| | 2014-7-26 21:30 | 只看该作者
刚好困扰在楼主说的范例上的GetADC(1)上,开始没照范例做,自我认为0通道,就是GetADC(0),得到的ADC值,按10位计算接近260 (即1.27V左右);再看范例是取GetADC(1),以为自己是做错了,就再按范例做,得到AD值总是看不懂。
看到论坛上正好有同样的话题能解惑,太好了!菜鸟总是担心会走错路,原来大大们早已了如指掌了。
经常来论坛看看,受益匪浅!

使用特权

评论回复
9
coody| | 2014-7-28 10:34 | 只看该作者
可能是写例程的人拷贝后没修改,实际应该是GetADC(0)

使用特权

评论回复
10
如何RH| | 2014-8-2 23:00 | 只看该作者
把 WORD idata Vbg_RAM _at_ 0xef; 拷贝到程序中,却
出错C274: Vbg_RAM :absolute specifier illegal
不明白?
照搬STC的例程里语句,却不能用,应该是漏了定义标注?

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

9

主题

46

帖子

0

粉丝