找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 5933|回复: 11
打印 上一主题 下一主题
收起左侧

关于STC15W408AS单片机的ADC程序疑问

[复制链接]
跳转到指定楼层
楼主
ID:590194 发表于 2020-11-3 12:38 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
ADC是模转数.用的芯片是15W408AS 我是按照范例 用的是ADC查询..

芯片是5V供电

P1.2作为ADC脚

然后P1.2短接GND 为啥读出来的还是FF?

/* 如果要在程序中使用此代码,请在程序中注明使用了STC的资料及程序        */
/* 如果要在文章中应用此代码,请在文章中注明使用了STC的资料及程序        */
/*---------------------------------------------------------------------*/

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


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

#define FOSC    11059200L
#define BAUD    115200

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 P1M1 = 0x91;    //PxM1.n,PxM0.n     =00--->Standard,    01--->push-pull
sfr P1M0 = 0x92;    //                  =10--->pure input,  11--->open drain
sfr P0M1 = 0x93;
sfr P0M0 = 0x94;
sfr P2M1 = 0x95;
sfr P2M0 = 0x96;
sfr P3M1 = 0xB1;
sfr P3M0 = 0xB2;
sfr P4M1 = 0xB3;
sfr P4M0 = 0xB4;
sfr P5M1 = 0xC9;
sfr P5M0 = 0xCA;
sfr P6M1 = 0xCB;
sfr P6M0 = 0xCC;
sfr P7M1 = 0xE1;
sfr P7M0 = 0xE2;

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()
{
    P0M0 = 0x00;
    P0M1 = 0x00;
    P1M0 = 0x00;
    P1M1 = 0x00;
    P2M0 = 0x00;
    P2M1 = 0x00;
    P3M0 = 0x00;
    P3M1 = 0x00;
    P4M0 = 0x00;
    P4M1 = 0x00;
    P5M0 = 0x00;
    P5M1 = 0x00;
    P6M0 = 0x00;
    P6M1 = 0x00;
    P7M0 = 0x00;
    P7M1 = 0x00;

    InitUart();                     //初始化串口
    InitADC();                      //初始化ADC
    while (1)
    {
        ShowResult(0);              //显示通道0
                        Delay(100);
        ShowResult(1);              //显示通道1
                        Delay(100);
        ShowResult(2);              //显示通道2
                        Delay(100);
        ShowResult(3);              //显示通道3
                        Delay(100);
        ShowResult(4);              //显示通道4
                        Delay(100);
        ShowResult(5);              //显示通道5

                        Delay(500);
                        
    }
}

/*----------------------------
发送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 = (65536 - (FOSC/4/BAUD));
    T2H = (65536 - (FOSC/4/BAUD)) >> 8;
    AUXR = 0x14;                //T2为1T模式, 并启动定时器2
    AUXR |= 0x01;               //选择定时器2为串口1的波特率发生器
#elif URMD == 1
    AUXR = 0x40;                //定时器1为1T模式
    TMOD = 0x00;                //定时器1为模式0(16位自动重载)
    TL1 = (65536 - (FOSC/4/BAUD));
    TH1 = (65536 - (FOSC/4/BAUD)) >> 8;
    TR1 = 1;                    //定时器1开始启动
#else
    TMOD = 0x20;                //设置定时器1为8位自动重装载模式
    AUXR = 0x40;                //定时器1为1T模式
    TH1 = TL1 = (256 - (FOSC/32/BAUD));
    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--);
    }
}


分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏3 分享淘帖 顶 踩
回复

使用道具 举报

沙发
ID:213173 发表于 2020-11-3 15:22 | 只看该作者
        P1M1 = 0xff;                                         //设置P1.0~1.7高阻:1111 1111 ADC输入高阻
        P1M0 = 0x00;                                         //设置P1.0~1.7高阻:0000 0000 ADC输入高阻
回复

使用道具 举报

板凳
ID:47286 发表于 2020-11-3 22:25 | 只看该作者
你试试把P1口设置成高阻
回复

使用道具 举报

地板
ID:590194 发表于 2020-11-4 11:01 | 只看该作者
wulin 发表于 2020-11-3 15:22
P1M1 = 0xff;                                         //设置P1.0~1.7高阻:1111 1111 ADC输入高阻
        P1M0 = 0x00;                                         //设置P1.0~1.7高阻 ...

修改了还是不行.是跟GND短接吗?我跟GND 跟VDD 短接读出来的都是FF FE
回复

使用道具 举报

5#
ID:401564 发表于 2020-11-4 11:45 | 只看该作者
一步一步去找问题
1:在开发板或者是现成的板子上进行测试:设定一个输出,不管是数码管还是8个LED都可以,只要能大概显示一个输出就行
2:P1.2接上一个可调电压,调节电压输出有变化,就说明你ADC设置是可以进行ADC的了,如果是有完整的显示就更好了
3:只有完成前面两个测试,证明ADC可以正常转换之后,再进行串口显示,
有的串口软件并不成正常的显示8051发送的数据的,如果你已经证明ADC可以正常进行,并且可以输出可以变化的数据,但串口还是FF,那就说明是串口这一块有问题,不是代码就是串口软件不行,慢慢找 就可以的了
回复

使用道具 举报

6#
ID:590194 发表于 2020-11-4 12:06 | 只看该作者
Y_G_G 发表于 2020-11-4 11:45
一步一步去找问题
1:在开发板或者是现成的板子上进行测试:设定一个输出,不管是数码管还是8个LED都可以,只 ...

谢谢了.我本以为串口输出会比较好..我最开始用的就是4个LED来读去的但是读去的一直是1655所以才尝试用串口输出的..我再试试
回复

使用道具 举报

7#
ID:401564 发表于 2020-11-4 13:53 | 只看该作者
sq8422779 发表于 2020-11-4 12:06
谢谢了.我本以为串口输出会比较好..我最开始用的就是4个LED来读去的但是读去的一直是1655所以才尝试用串 ...

只要是IO能够随着P1.2的电压变动,这就说明ADC已经在正常转换了,数据不对就只是ADC格式或者算法不对而已
加了串口就不一样了,STC串口实际上是有好几个的,要去设定,而且电脑端的串口软件有一些并不是通用的,无形中增加了出现问题的可能性
回复

使用道具 举报

8#
ID:590194 发表于 2020-11-5 09:03 | 只看该作者
Y_G_G 发表于 2020-11-4 13:53
只要是IO能够随着P1.2的电压变动,这就说明ADC已经在正常转换了,数据不对就只是ADC格式或者算法不对而已
...

谢谢.已经能正常显示了..有个问题请教一下.这个数值,我用的是平均值..线路设计的时候.光感直接2个角接在P1.2和GND吗?中间不用加电阻,和电容吗??
回复

使用道具 举报

9#
ID:401564 发表于 2020-11-5 09:25 | 只看该作者
sq8422779 发表于 2020-11-5 09:03
谢谢.已经能正常显示了..有个问题请教一下.这个数值,我用的是平均值..线路设计的时候.光感直接2个角接在P ...

如果光敏电阻,就是串联一个电阻,分压取ADC
进入ADC端口串联不串联的,没什么影响,你可以试一下就知道了,实际感觉不到它有什么用,但是,如果是实际的项目,一定是要用个串联的电阻的,大概100欧左右就可以了,焊盘可以靠近一点,方便以后焊接元件或者直接短路
P1.2端口一定要并联一个104电容到地,这是最基本的,如果你的电源用的是开关电源,可以换成102或者103的都行,电池或者变压器就用104的.这个电容一定要有
这104电容就这样:它有作用的时候,你感觉不到它存在,它没有的时候你才感觉它有作用
回复

使用道具 举报

10#
ID:590194 发表于 2020-11-10 08:22 | 只看该作者
Y_G_G 发表于 2020-11-5 09:25
如果光敏电阻,就是串联一个电阻,分压取ADC
进入ADC端口串联不串联的,没什么影响,你可以试一下就知道了, ...

嗯.我试了下.串联一个500k电阻刚好所有量程都在..10bit能采集到.然后这个并的电容.起到什么作用呢?除了这个光感外,还有一个音量采集...这个好像直接接在P1.2上采集不到..是不是要放大电路?
回复

使用道具 举报

11#
ID:401564 发表于 2020-11-10 08:55 | 只看该作者
sq8422779 发表于 2020-11-10 08:22
嗯.我试了下.串联一个500k电阻刚好所有量程都在..10bit能采集到.然后这个并的电容.起到什么作用呢?除了这 ...

104电容是抗干扰用的
音频采样是要整流才能采样的,这个我没有玩过,你上网找一下,自己测试一下
回复

使用道具 举报

12#
ID:146782 发表于 2020-11-10 09:25 | 只看该作者
并联电容是起到滤波的作用吧
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表