打印
[STC单片机]

关于 IAP 15F2K61S2的ADC问题

[复制链接]
2610|2
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
吕泽帅|  楼主 | 2015-9-26 18:09 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
请问,STC-ISP内部的这个源程序是什么意思,怎么使用?刚从51单片机跨越到这个单片机,不太明白内部ADC转换的原理,把一个模拟信号转换为数字信号是怎么转换的,怎么用下面的源程序输出使用,原理是啥。。。
希望有个大神指点一下,哪怕一点点也行。



/*---------------------------------------------------------------------*/
/* --- STC MCU Limited ------------------------------------------------*/
/* --- STC15F4K60S4 系列 AD转换查询方式举例----------------------------*/
/* --- Mobile: (86)13922805190 ----------------------------------------*/
/* --- Fax: 86-0513-55012956,55012947,55012969 ------------------------*/
/* --- Tel: 86-0513-55012928,55012929,55012966-------------------------*//
/* 如果要在程序中使用此代码,请在程序中注明使用了STC的资料及程序        */
/* 如果要在**中应用此代码,请在**中注明使用了STC的资料及程序        */
/*---------------------------------------------------------------------*/


//本示例在Keil开发环境下请选择Intel的8058芯片型号进行编译
//若无特别说明,工作频率一般为11.0592MHz




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


#define FOSC    11059200L
#define BAUD    9600


typedef unsigned char BYTE;
typedef unsigned int WORD;


#define     URMD    0           //0:使用定时器2作为波特率发生器
                                //1:使用定时器1的模式0(16位自动重载模式)作为波特率发生器
                                //2:使用定时器1的模式2(8位自动重载模式)作为波特率发生器


sfr T2H   = 0xd6;               //定时器2高8位
sfr T2L   = 0xd7;               //定时器2低8位


sfr  AUXR       =   0x8e;       //辅助寄存器                              


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 InitUart();
void InitADC();
void SendData(BYTE dat);
BYTE GetADCResult(BYTE ch);
void Delay(WORD n);
void ShowResult(BYTE ch);


void main()
{
    InitUart();                     //初始化串口
    InitADC();                      //初始化ADC
    while (1)
    {
        ShowResult(0);              //显示通道0
        ShowResult(1);              //显示通道1
        ShowResult(2);              //显示通道2
        ShowResult(3);              //显示通道3
        ShowResult(4);              //显示通道4
        ShowResult(5);              //显示通道5
        ShowResult(6);              //显示通道6
        ShowResult(7);              //显示通道7
    }
}


/*----------------------------
发送ADC结果到PC
----------------------------*/
void ShowResult(BYTE ch)
{
    SendData(ch);                   //显示通道号
    SendData(GetADCResult(ch));     //显示ADC高8位结果


//    SendData(ADC_LOW2);           //显示低2位结果
}


/*----------------------------
读取ADC结果
----------------------------*/
BYTE GetADCResult(BYTE ch)
{
    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;         //Close ADC


    return ADC_RES;                 //返回ADC结果
}


/*----------------------------
初始化串口
----------------------------*/
void InitUart()
{
    SCON = 0x5a;                //设置串口为8位可变波特率
#if URMD == 0
    T2L = 0xd8;                 //设置波特率重装值
    T2H = 0xff;                 //115200 bps(65536-18432000/4/115200)
    AUXR = 0x14;                //T2为1T模式, 并启动定时器2
    AUXR |= 0x01;               //选择定时器2为串口1的波特率发生器
#elif URMD == 1
    AUXR = 0x40;                //定时器1为1T模式
    TMOD = 0x00;                //定时器1为模式0(16位自动重载)
    TL1 = 0xd8;                 //设置波特率重装值
    TH1 = 0xff;                 //115200 bps(65536-18432000/4/115200)
    TR1 = 1;                    //定时器1开始启动
#else
    TMOD = 0x20;                //设置定时器1为8位自动重装载模式
    AUXR = 0x40;                //定时器1为1T模式
    TH1 = TL1 = 0xfb;           //115200 bps(256 - 18432000/32/115200)
    TR1 = 1;
#endif
}


/*----------------------------
初始化ADC
----------------------------*/
void InitADC()
{
    P1ASF = 0xff;                   //设置P1口为AD口
    ADC_RES = 0;                    //清除结果寄存器
    ADC_CONTR = ADC_POWER | ADC_SPEEDLL;
    Delay(2);                       //ADC上电并延时
}


/*----------------------------
发送串口数据
----------------------------*/
void SendData(BYTE dat)
{
    while (!TI);                    //等待前一个数据发送完成
    TI = 0;                         //清除发送标志
    SBUF = dat;                     //发送当前数据
}


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


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




相关帖子

沙发
xyz549040622| | 2015-9-26 20:47 | 只看该作者
AD直接读取模拟电压,然后读取的结果值存储在一个数据寄存器中,读出来通过串口发送。大概就这么个意思

使用特权

评论回复
板凳
无量寿经| | 2015-9-26 23:11 | 只看该作者
下面程序更简洁一些,并有详细注释,可不作任何修改直接用于IAP15F2K61S2单片机,内容来源于《51单片机轻松入门-基于STC15W4K系列》
9.2.2、实例代码
例9.1   IAP15W4K58S4单片机A/D转换程序,查询方式,测量结果电压值发送到计算机串口助手显示,波特率9600/22.1184MHz,电路如图1-13所示。当使用配套实验板时,需要将跳线帽“AD/串口2”插接到AD处。
#include"UART.H"          // 包含IAP15W4K58S4寄存器定义文件
#define VCC 4.970          // 存放用万用表实测的单片机供电电压
unsigned int ADC_P11()
{
    unsigned int i;         // 用于软件延时程序
    unsigned char status;   // 用于判断A/D转换结束的标志
    unsigned int AD_Dat=0;  //10位A/D转换值
    unsigned char Tmp;      // 临时变量用于将A/D转换出来的2个字节合成一个字节     
    ADC_CONTR|=0x80;        // 开ADC转换器电源,第一次使用时要打开内部模拟电源
    for (i=0;i<10000;i++);  // 适当延时等待ADC转换供电稳定,一般延时1ms以内即可,为了缩短
                            // A/D调用时间,可把这2行剪切到主程序中去。
    P1ASF|=0x02;            // 选择P1.1作为ADC转换通道,0x02= 0000 0010   
    ADC_CONTR=0xE1;         // 选择P1.1作为ADC转换通道,最高转换速度,清转换完成标志。
    for (i=0;i<1000;i++);  // 如果是多通道模拟量进行A/D转换,则更换A/D转换通道后要适当延时,
// 使输入电压稳定,延时量取20μs~200μs即可,与输入电压源的内阻有关,如果输入电压信号源的内
// 阻在10K以下,可不加延时,如果是单通道模拟量转换,则不需要更换A/D转换通道,也不需要加延时。
    ADC_CONTR|=0x08;        // 启动 A/D 转换,ADC_START=1。
    status=0;
    while(status==0)        // 等待A/D转换结束。
    {
       status=ADC_CONTR&0x10;   // 判断ADC_FLAG是否等于1,0x10=0001 0000B。
    }
    ADC_CONTR&=0xE7;        // 将ADC_FLAG清0, 0xE7=1110 0111B,ADC_FLAG=0,ADC_START=0。  
    AD_Dat = ADC_RES;       // 默认高字节高8位。
    AD_Dat <<= 2;
    Tmp = ADC_RESL;         // 默认低字节低2位。
    Tmp &= 0x03;           // 屏蔽无关位
    AD_Dat |= Tmp;          // 高低字节拼接成一个10位数。
    return AD_Dat;
}  
void main(void)
{   
    float Vin;                     // 存放计算出来的外部输入电压
    unsigned int ADvalue;          // 存放A/D转换返回的结果
    UART_init();                   // 串口初始化9600/22.1184MHz
    printf("串口初始化完毕");
    while(1)
    {           
        ADvalue=ADC_P11();         // 采样P1.1口模拟输入电压
        Vin=VCC*ADvalue/1023;     // 注意是1023才正确
        printf("%.3f    ",Vin);        
        delay500ms();
    }                             // 若不用串口显示,此行可设置断点仿真观察结果
}
实验测试数据如表9-5所示,表中的“参考基准电压”和“输入电压(V)”是使用四位半数字万用表VC86E测量获得的结果, ADC的输入信号是来自10K的可调电位器。
                         表9-5  单片机内部ADC实验结果数据表
  
参考基准电压
  
输入电压(V)
串口助手显示电压(V)
相对误差
4.970
0.000
0.005
0.005/4.970×100% = 0.1%
1.000
1.011
0.011/4.970×100% = 0.2%
2.000
2.011
0.011/4.970×100% = 0.2%
3.000
3.032
0.032/4.970×100% = 0.6%
4.000
4.018
0.018/4.970×100% = 0.4%
4.970
4.970
0.000/4.970×100% = 0.0%

使用特权

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

本版积分规则

16

主题

43

帖子

1

粉丝