AD_Dat = (ADC_RES<<2)|(ADC_RESL&0x03); //高低字节拼接成一个10位数。 关于这句代码,是不需要强制转换为int的, 因为AD_Dat是int类型,2个字节16位的,式子右边的高位是不会丢失的。 |
你把b端,值接到单片机VCC引脚尝试一下,(即和单片机同一基准)看看a的读数是不是512左右。 或者,你把b端接到P3.7口, 把P3.7设置为推挽输出,高电平。然后再测a端读数,我怀疑你之所以a端700多,是因为你b端超过量程了,只能显示1023,其实1400了…… |
本帖最后由 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 |
188461 发表于 2018-8-29 09:38 单片机的AD转换时只能使用一个模拟输入通道吗 |
小帖 发表于 2018-8-30 16:17 vcc为4.75v,没接基准电压,电路简单 |
wulin 发表于 2018-8-30 17:23 P1M1 = 0x08; P1M0 = 0x00; 我换了P1.3端口,并把其置为高阻模式了,可是没有效果啊 ![]() 设为准双向口时,把电源和地换位置,测得ad值也是700多,换位置前后ad值差不多,说明内部上拉电阻没并联在上分压电阻上啊。这是不是说明总的ad值有1500多【哭晕】 这是怎么回事呢,求解答,万分感谢!!!!! |
188461 发表于 2018-8-29 09:25 你把AD输入端设为准双向口当然测出的电压比实际电压高,因为准双向口使用了内部上拉电阻,这个电阻相当于接在你的外电路的a、b两点之间。也就是并联在上分压电阻上从而改变上分压电阻阻值。 |
hdx 好东西 好东西 谢谢喽 |
VCC是否是单片机的基准电压,还是大于基准电压,用的10位的AD,最大值了 |
lilao3 发表于 2018-8-29 00:23 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口的,设置为模拟输入了啊 ![]() |
devcang 发表于 2018-8-28 17:29 没有设置基准参考电压,因为应用简单,直接与vcc比较的 测试时vcc电压是稳定的5.02v,串联电阻两端电压5.00v |
wulin 发表于 2018-8-28 16:51 一个电阻为9.88k,一个为9.95k。P1端口:P1M1 = 0; P1M0 = 0; //设置为准双向口 相应的p1.0端口通过ADC_CONTR设置为模拟输入了 为什么要设置成高阻呢??? |
看你的情况,貌似IO口没有配置成模拟输入,默认有弱上拉,所以理论值512,实际测700多。
![]() |
AD的参考电压是多少,要是参考电压的1半,结果才是那样。不然,就是自己的参考电压,2路AD,其中1路是参考电压,另1路是测试的电压。 |
你能确认两个10K电阻的实际阻值相同?相应端口是否设为高阻和模拟输入模式? |