找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 4719|回复: 14
收起左侧

IAP15W4K58S4单片机的ad读数问题

  [复制链接]
回帖奖励 3 黑币 回复本帖可获得 3 黑币奖励! 每人限 1 次
ID:367880 发表于 2018-8-28 15:04 | 显示全部楼层 |阅读模式
宏晶IAP15W4K58S4单片机最小模块,测AD值,两个10k电阻串联,测a点的ad值不是1024的二分之一,而是700多,为什么?????测b点的ad值就是1023,为什么?????

紧急求助

IMG_20180828_150527.jpg
回复

使用道具 举报

ID:213173 发表于 2018-8-28 16:51 | 显示全部楼层
你能确认两个10K电阻的实际阻值相同?相应端口是否设为高阻和模拟输入模式?
回复

使用道具 举报

ID:277550 发表于 2018-8-28 17:29 | 显示全部楼层


AD的参考电压是多少,要是参考电压的1半,结果才是那样。不然,就是自己的参考电压,2路AD,其中1路是参考电压,另1路是测试的电压。
回复

使用道具 举报

ID:139455 发表于 2018-8-29 00:23 | 显示全部楼层
看你的情况,貌似IO口没有配置成模拟输入,默认有弱上拉,所以理论值512,实际测700多。 无标题.jpg

回复

使用道具 举报

ID:367880 发表于 2018-8-29 09:25 | 显示全部楼层
wulin 发表于 2018-8-28 16:51
你能确认两个10K电阻的实际阻值相同?相应端口是否设为高阻和模拟输入模式?

一个电阻为9.88k,一个为9.95k。P1端口:P1M1 = 0;        P1M0 = 0;        //设置为准双向口
相应的p1.0端口通过ADC_CONTR设置为模拟输入了
为什么要设置成高阻呢???
回复

使用道具 举报

ID:367880 发表于 2018-8-29 09:35 | 显示全部楼层
devcang 发表于 2018-8-28 17:29
AD的参考电压是多少,要是参考电压的1半,结果才是那样。不然,就是自己的参考电压,2路AD,其中1路是 ...

没有设置基准参考电压,因为应用简单,直接与vcc比较的
测试时vcc电压是稳定的5.02v,串联电阻两端电压5.00v
回复

使用道具 举报

ID:367880 发表于 2018-8-29 09:38 | 显示全部楼层
lilao3 发表于 2018-8-29 00:23
看你的情况,貌似IO口没有配置成模拟输入,默认有弱上拉,所以理论值512,实际测700多。

        ADC_CONTR = 0x80;         //开AD转换电源,第一次使用时要打开start the ADC
        for (g=0;g<10000;g++);
        P1ASF|=0x08;                        // 选择P1.3作为AD转换通道,0x02= 0000 1000       
        ADC_CONTR=0xE3;         // 选择P1.3作为AD转换通道,最高转换速度,清转换完成标志。
        for (g=0;g<1000;g++);
        ADC_CONTR|=0x08;  
        while((ADC_CONTR & 0x10) == 0)        ;        //wait for ADC finish
        ADC_CONTR &= 0xE7;                //将ADC_FLAG清0, 0xE7=1110 0111B,ADC_FLAG=0
        AD_Dat = (ADC_RES<<2)|(ADC_RESL&0x03);        //高低字节拼接成一个10位数。
        return AD_Dat;
这个程序是p1.3口的,设置为模拟输入了啊
回复

使用道具 举报

ID:391656 发表于 2018-8-30 16:17 | 显示全部楼层
VCC是否是单片机的基准电压,还是大于基准电压,用的10位的AD,最大值了
回复

使用道具 举报

ID:391695 发表于 2018-8-30 17:17 | 显示全部楼层
hdx  好东西  好东西  谢谢喽
回复

使用道具 举报

ID:213173 发表于 2018-8-30 17:23 | 显示全部楼层
188461 发表于 2018-8-29 09:25
一个电阻为9.88k,一个为9.95k。P1端口:P1M1 = 0;        P1M0 = 0;        //设置为准双向口
相应的p1.0端口通过ADC_ ...

你把AD输入端设为准双向口当然测出的电压比实际电压高,因为准双向口使用了内部上拉电阻,这个电阻相当于接在你的外电路的a、b两点之间。也就是并联在上分压电阻上从而改变上分压电阻阻值。
回复

使用道具 举报

ID:367880 发表于 2018-8-31 16:45 | 显示全部楼层
wulin 发表于 2018-8-30 17:23
你把AD输入端设为准双向口当然测出的电压比实际电压高,因为准双向口使用了内部上拉电阻,这个电阻相当于 ...

P1M1 = 0x08;        P1M0 = 0x00;
我换了P1.3端口,并把其置为高阻模式了,可是没有效果啊
设为准双向口时,把电源和地换位置,测得ad值也是700多,换位置前后ad值差不多,说明内部上拉电阻没并联在上分压电阻上啊。这是不是说明总的ad值有1500多【哭晕】
这是怎么回事呢,求解答,万分感谢!!!!!
回复

使用道具 举报

ID:367880 发表于 2018-8-31 16:46 | 显示全部楼层
小帖 发表于 2018-8-30 16:17
VCC是否是单片机的基准电压,还是大于基准电压,用的10位的AD,最大值了

vcc为4.75v,没接基准电压,电路简单
回复

使用道具 举报

ID:517379 发表于 2019-5-28 16:37 | 显示全部楼层
188461 发表于 2018-8-29 09:38
ADC_CONTR = 0x80;         //开AD转换电源,第一次使用时要打开start the ADC
        for (g=0;g

单片机的AD转换时只能使用一个模拟输入通道吗
回复

使用道具 举报

ID:111280 发表于 2021-8-29 04:24 | 显示全部楼层
本帖最后由 dbxzjq 于 2021-8-31 00:14 编辑

#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个时钟

/*----------------------------
初始化ADC
----------------------------*/
void InitADC(void)
{
    //P1M0 &= ~0x10;
    //P1M1 |= 0x10;        
    P1ASF = 0x07;                   //设置P1口为AD口
    ADC_RES = 0;                    //清除结果寄存器
        ADC_RESL = 0;
        CLK_DIV |= 0x20;                //ADRJ=1,ADC_RES[1:0]存放高2位ADC结果,ADC_RESL[7:0]存放低8位结果
    ADC_CONTR = ADC_POWER | ADC_SPEEDL; //开启ADC电源,配置ADC转换速度为180个时钟
    //Delay(2);                       //ADC上电并延时
}

unsigned int GetADCResult(unsigned char ch)
{
        //unsigned int a=0;
    ADC_CONTR =   ADC_POWER | ADC_SPEEDL | ch | ADC_START;
    _nop_();                        //等待4个NOP
    _nop_();
    _nop_();
    _nop_();
    while (!(ADC_CONTR & ADC_FLAG));//等待ADC转换完成
    ADC_CONTR &= ~ADC_FLAG;         //Close ADC
        //a=ADC_RES;
        //a=a<<8|ADC_RESL;
    return (unsigned int)ADC_RES<<8|ADC_RESL;                 //返回ADC结果
}

测量出来的ADC都非常正常的啊!切换通道后必须等待四个空周期才能进行测量,另外这型号对于IO口不用设置为高阻输入的,只管P1ASF设置对应为模拟口即可,不过手册上也说最好把ADC对应的测量IO配置为高阻输入为好楼主的代码:发现合成10位有问题,如下:
AD_Dat = (ADC_RES<<2)|(ADC_RESL&0x03);        //高低字节拼接成一个10位数。
修改为AD_Dat =(int)(ADC_RES<<2)|(ADC_RESL&0x03);        //高低字节拼接成一个10位数。
这里(int)(ADC_RES<<2)因为左移2位后,超出来寄存器的8位宽度,8位机只能默认R0-R7寄存器组都为8位的,必须得强制转换为16位,
编译器才会把ADC_RES<<2放在两个临时的R0-R7寄存器组里头再进行运算,得到的最终结果才是正确的值

比如ADC_RES=11111111的二进制值,执行ADC_RES<<2后=11111100,但是如果(int)(ADC_RES<<2)就会不一样了,它会换成16位进行运算
得到的会是0000 0011 1111 1100的16位值再位或|(ADC_RESL&0x03)这部分的结果送给予6位变量AD_Dat

评分

参与人数 1黑币 +50 收起 理由
admin + 50 回帖助人的奖励!

查看全部评分

回复

使用道具 举报

ID:624769 发表于 2021-8-29 22:36 | 显示全部楼层
你把b端,值接到单片机VCC引脚尝试一下,(即和单片机同一基准)看看a的读数是不是512左右。
或者,你把b端接到P3.7口, 把P3.7设置为推挽输出,高电平。然后再测a端读数,我怀疑你之所以a端700多,是因为你b端超过量程了,只能显示1023,其实1400了……
回复

使用道具 举报

ID:759755 发表于 2021-10-5 17:57 | 显示全部楼层
AD_Dat = (ADC_RES<<2)|(ADC_RESL&0x03);        //高低字节拼接成一个10位数。
关于这句代码,是不需要强制转换为int的, 因为AD_Dat是int类型,2个字节16位的,式子右边的高位是不会丢失的。
回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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