数码之家

 找回密码
 立即注册
搜索
查看: 6174|回复: 20

[C51] stc单片机adc计算问题求助

[复制链接]
发表于 2021-6-20 20:16:09 | 显示全部楼层 |阅读模式


这个程序里面,GetADCResult(5)是5通道输入电压adc值,Powr_voltage是vcc电压,公式是计算5通道电压值,都是unsigned int 数据类型,不知道是不是类型不同,V1的值,通过串口显示都是0000,论坛大佬,指点一下

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x
发表于 2021-6-24 09:57:49 | 显示全部楼层
C语言

整数相乘、除,结果是整数。所以如果值是0.几,不足进位,就会变成0。。。

不用强制转换,其中有一个数是浮点的就可以,结果自动再转换成整数。
unsigned ng voltage;
voltage=bandgap*1024.0/adc_9gallery_res*1000;  //放大1000倍,以便计算小数。
回复 支持 反对

使用道具 举报

 楼主| 发表于 2021-6-21 19:17:40 | 显示全部楼层
谢谢各位大佬指点,已经改好了,是数据类型导致的错误,把数据类型改成long,就正常了。
回复 支持 反对

使用道具 举报

发表于 2021-6-21 14:56:12 | 显示全部楼层
4楼说的很清楚了,咋看不明白:doubt:
电压最好用mv单位,用uint32计算
回复 支持 反对

使用道具 举报

 楼主| 发表于 2021-6-21 14:19:42 | 显示全部楼层
  1. /*----------------------------
  2. 读取ADC结果
  3. ----------------------------*/
  4. uint_16 GetADCResult(uchar_8 ch)
  5. {
  6.     uint_16 ADC_10BIT_RES;
  7.     ADC_CONTR = ADC_POWER | ADC_SPEEDLL | ch | ADC_START;
  8.     _nop_();                        //等待4个NOP
  9.     _nop_();
  10.     _nop_();
  11.     _nop_();
  12.     while (!(ADC_CONTR & ADC_FLAG));//等待ADC转换完成
  13.     ADC_CONTR &= ~ADC_FLAG;         //关闭 ADC
  14.     ADC_10BIT_RES=ADC_RES;      //得到高8位
  15.     ADC_10BIT_RES<<=2;
  16.     ADC_10BIT_RES+=ADC_RESL;     //得到低2位
  17.     return ADC_10BIT_RES;                 //返回ADC结果
  18.   

  19. }


  20. /*----------------------------
  21. 读取Bandgap电压值与adc值
  22. 计算VCC工作电压值
  23. ----------------------------*/
  24. uint_16 ShowResult()
  25. {
  26.                
  27.     uint_16 bandgap,       //bandgap预储存校准值,单位毫伏
  28.     adc_9gallery_res; //测量第九通道(bandgap)值

  29.     float power_voltage;      //系统供电电压,单位毫伏
  30.    // ADC_voltage;     //设定通道电压值,单位毫伏

  31.     uchar_8  code *cptr; //定义ROM(代码)区指针
  32.                 cptr = ID_ADDR_ROM;         //从程序区读取BandGap电压值(单位:毫伏mV)
  33.     bandgap=*cptr++;
  34.     bandgap<<=8;
  35.     bandgap+=*cptr;
  36. //测量第九通道(bandgap)值
  37.     ADC_RES = 0;                    //清除结果寄存器
  38.     P1ASF = 0x00;                   //设置读第九通道
  39.     GetADCResult(0);                 //测bandgap时,调用此函数时通道数只能填0
  40.     GetADCResult(0);                 //读三次获得稳定
  41.     adc_9gallery_res=GetADCResult(0);
  42.                
  43. //计算系统供电电压
  44.     power_voltage=(float)bandgap*1024/adc_9gallery_res;
  45.                
  46.           return  power_voltage;
  47. }
复制代码


回复 支持 反对

使用道具 举报

发表于 2021-6-21 09:32:48 | 显示全部楼层
选择unsigned int ,先乘如果超出65536会出错(虽然除后不超)。
回复 支持 反对

使用道具 举报

发表于 2021-6-21 09:23:09 | 显示全部楼层
本帖最后由 慕名而来 于 2021-6-21 09:28 编辑

公式方面:
ADC=(1024*VIN)/VCC
VIN=(ADC*VCC)/1024;---------这个是编程用的公式。代码方面:
GetADCResult(5)这个函数的原型不知道,但必须是unsigned int GetADCResult(unsigned char date),如果是unsigned char GetADCResult(unsigned char date)就会不对了。
下面是我在用的STC12C5604AD的10位ADC代码仅供参考:
  1. /*----------------------------
  2. 初始模数转换寄存器函数
  3. ----------------------------*/
  4. void InitADC()
  5. {
  6.    ADC_DATA = 0;                    //ADC数据寄存器清零
  7.         ADC_LOW2 = 0;
  8.         ADC_CONTR = ADC_POWER | ADC_SPEEDLL;
  9.         Delay(2);                       
  10. }
  11. /*----------------------------------------------------------
  12. 10位ADC转换执行函数
  13. GetADCResult变量必须设置成unsigned int
  14. 若设成unsigned char则输出结果将错乱
  15. ----------------------------------------------------------*/
  16. uint GetADCResult(uchar ch)
  17. {
  18.     ADC_CONTR = ADC_POWER | ADC_SPEEDLL | ch | ADC_START;
  19.     _nop_();                        //必要的查询等待
  20.     _nop_();
  21.     _nop_();
  22.     _nop_();
  23.     while (!(ADC_CONTR & ADC_FLAG));//等待标志位
  24.     ADC_CONTR &=~ADC_FLAG;        //关闭 ADC
  25. return((ADC_DATA<<2)+ADC_LOW2);   //返回AD转换完成的10位数据(16进制)
  26. }
  27. /*********************************************/
  28. float AD_work(uchar ch)
  29. {
  30. float AD_val; //转换结果传递变量设为浮点数   
  31. uchar m;
  32. for(m=0;m<50;m++)
  33. {AD_val+=GetADCResult(ch);} //转换50次求平均值(提高精度)
  34. AD_val/=50;
  35. AD_val=(AD_val*5)/1024; //AD的参考电压是单片机上的5v,所以乘5即为实际电压值
  36. return AD_val*100;
  37. }
复制代码
主循环之前调用一次initADC();
函数float AD_work(uchar ch)中的ch是通道号码,返回的结果是经过50次采样的平均值并且放大了100倍,如果不需要求平均值和小数点后的数据就不用设置浮点变量了,这个函数可以变成
uint AD_work(uchar ch)
{
uint AD_val;

AD_val+=GetADCResult(ch);
AD_val=(AD_val*5)/1024; //计算对应的电源电压为5V。

return AD_val;
}

回复 支持 1 反对 0

使用道具 举报

发表于 2021-6-21 09:19:36 | 显示全部楼层
law3411209 发表于 2021-6-21 09:09
GetADCResult(5)输入是接的5v电压,读取的ADC值是1023,Powr_voltage是通过内部的带隙电压计算出来vcc电压 ...

很可能是数据类型引起的,可以用16位无符号整型试试。
回复 支持 反对

使用道具 举报

 楼主| 发表于 2021-6-21 09:09:01 | 显示全部楼层
GetADCResult(5)输入是接的5v电压,读取的ADC值是1023,Powr_voltage是通过内部的带隙电压计算出来vcc电压值是5014mv,这几个数据是通过串口助手显示的,人工计算,如果先乘法后除,得出来的是1.999.先除后乘,得出来的是5009mv。可是带入到程序里面,就不行了,显示0000,大佬们,是因为数据类型使用错误导致的吗,回家后改成浮点数类型的看看
回复 支持 反对

使用道具 举报

发表于 2021-6-21 08:16:43 | 显示全部楼层
先乘再除,51上面不适合用浮点,就用无符号16位型变量计算。
回复 支持 反对

使用道具 举报

发表于 2021-6-21 07:47:35 来自手机浏览器 | 显示全部楼层
如果电源电压是5v,就用AD采样值,乘以4882,再除以1000。得到的数自己找个合适的地方确定小数点。没有浮点运算的单片机,计算浮点的时间很长。
回复 支持 反对

使用道具 举报

头像被屏蔽
发表于 2021-6-21 06:28:10 | 显示全部楼层
有意思,上面都已经说出答案了
回复 支持 反对

使用道具 举报

发表于 2021-6-21 02:43:13 | 显示全部楼层
就算是先乘再除精度也很差,要精度高,使用浮点数计算,如果精度要求不高,可以先把AD值放大10的n次幂再计算,如要保留2为小数,可以把AD值乘以100再计算,使用时除以100再使用,如计算得到101,则当做1.01V使用。
回复 支持 反对

使用道具 举报

发表于 2021-6-21 00:43:47 来自手机浏览器 | 显示全部楼层
公式变通一下。首先adc值不会超过1024,其次你用的是整数类型,adc值不管是除以1024还是除以vcc都是零。原公式你要使用浮点数类型
回复 支持 反对

使用道具 举报

发表于 2021-6-20 23:30:20 | 显示全部楼层
本帖最后由 lyy-cy 于 2021-6-20 23:40 编辑

先直接打印   GetADCResult(5)  看看  adc值
然后分别接  vcc 和 地  再看看数值
回复 支持 反对

使用道具 举报

发表于 2021-6-20 22:21:54 | 显示全部楼层
inthsunshine 发表于 2021-6-20 22:14
你自己看错, 图片公式里的左边是AD值, 不是Vin

啊,是我看错了
回复 支持 反对

使用道具 举报

发表于 2021-6-20 22:14:14 | 显示全部楼层
本帖最后由 inthsunshine 于 2021-6-20 22:15 编辑
广东梁百万 发表于 2021-6-20 22:09
都说你公式错了,还说没错!!!   把VCC和1024对调, 看清楚2楼的图片
VIN=(ADC值/vcc)*1024 ...

你自己看错, 图片公式里的左边是AD值, 不是Vin:lol:
回复 支持 反对

使用道具 举报

发表于 2021-6-20 22:09:29 | 显示全部楼层
本帖最后由 广东梁百万 于 2021-6-20 22:10 编辑
law3411209 发表于 2021-6-20 21:20
公式没错,VIN=(ADC值/1024)*vcc

都说你公式错了,还说没错!!!   把VCC和1024对调, 看清楚2楼的图片
VIN=(ADC值/vcc)*1024
回复 支持 反对

使用道具 举报

发表于 2021-6-20 21:38:39 | 显示全部楼层
本帖最后由 inthsunshine 于 2021-6-20 21:42 编辑

先乘再除,否则,除完1024只剩0,再乘也没意义
回复 支持 反对

使用道具 举报

 楼主| 发表于 2021-6-20 21:20:13 | 显示全部楼层
广东梁百万 发表于 2021-6-20 20:58
你的公式错了吧!

看文档

公式没错,VIN=(ADC值/1024)*vcc
回复 支持 反对

使用道具 举报

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

本版积分规则

APP|手机版|小黑屋|关于我们|联系我们|法律条款|技术知识分享平台

闽公网安备35020502000485号

闽ICP备2021002735号-2

GMT+8, 2025-5-29 17:13 , Processed in 0.280800 second(s), 12 queries , Redis On.

Powered by Discuz!

© 2006-2025 MyDigit.Net

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