找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 8512|回复: 9
收起左侧

如何用STC15单片机内部AD读取并在数码管显示电压值?

  [复制链接]
ID:592477 发表于 2019-8-21 16:43 | 显示全部楼层 |阅读模式
5黑币
MCU用的是STC15F2K60S2,外部硬件电路为一个20K的电位器,中间脚滑动端接AD输入引脚P1.0,另外两边引脚分别接GND和VCC,目前代码可以通过旋转电位器实现在四位一体共阴数码管上显示0~1023的数值,但是下一步想尝试显示电压值却总是格式不对显示不正常?参考了几个例程文件,还是不能弄出。代码部分的计算电压值时:adcnum=adcnum*500/1024;结果显示到数码管上就不正常了?以下是代码
  1. #include "reg52.h"
  2. #include "intrins.h"

  3. typedef unsigned char uchar;
  4. typedef unsigned int uint;

  5. sfr T2H = 0xd6; //定时器2高8位
  6. sfr T2L = 0xd7; //定时器2低8位
  7. sfr AUXR  = 0x8e; //辅助寄存器
  8. sfr ADC_CONTR  = 0xBC; //ADC控制寄存器
  9. sfr ADC_RES = 0xBD; //ADC高8位结果
  10. sfr ADC_RESL = 0xBE; //ADC低2位结果
  11. sfr P1ASF = 0x9D; //P1口第2功能控制寄存器
  12. sfr CLK_DIV = 0x97;

  13. sbit LSA=P3^2;
  14. sbit LSB=P3^3;
  15. sbit LSC=P3^4;

  16. uchar code smgduan[17]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,
  17.                                         0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71};//显示0~F的值

  18. uchar DisplayData[8];



  19. void Delay_ms(unsigned int ms)//ms级延时
  20. {
  21.         unsigned int a,b;
  22.         for(a=ms;a>0;)
  23.         {
  24.                 for(b=1000;b>0;)
  25.                 {
  26.                 b=b-1;
  27.                 }
  28.                 a--;
  29.         }
  30. }
  31. void ADC_int()                //ADC初始化
  32. {
  33.                                 ADC_CONTR=0X80;         
  34.                                 P1ASF=0X01;         
  35.         CLK_DIV=0X20;            
  36.         ADC_RESL=0;                                                                        
  37.         ADC_RES=0;                                       
  38.         Delay_ms(10);                               
  39. }
  40. unsigned int ADC_Read()   
  41. {
  42.         unsigned int a=0;
  43.         ADC_CONTR = 0X88;                                                                        
  44.                                 Delay_ms(1);                                                                
  45.         while(!(ADC_CONTR&0X10));  
  46.         a=ADC_RES*256+ADC_RESL;
  47.                                 ADC_CONTR&=~0x10;                                       
  48.         return a;               
  49. }
  50. void DigDisplay()
  51. {
  52.         uchar i;
  53.         for(i=0;i<8;i++)
  54.         {
  55.                 switch(i)         //位选,选择点亮的数码管,
  56.                 {
  57.                         case(0):
  58.                                 LSA=0;LSB=0;LSC=0; break;//显示第0位
  59.                         case(1):
  60.                                 LSA=1;LSB=0;LSC=0; break;//显示第1位
  61.                         case(2):
  62.                                 LSA=0;LSB=1;LSC=0; break;//显示第2位
  63.                         case(3):
  64.                                 LSA=1;LSB=1;LSC=0; break;//显示第3位
  65.                         case(4):
  66.                                 LSA=0;LSB=0;LSC=1; break;//显示第4位
  67.                         case(5):
  68.                                 LSA=1;LSB=0;LSC=1; break;//显示第5位
  69.                         case(6):
  70.                                 LSA=0;LSB=1;LSC=1; break;//显示第6位
  71.                         case(7):
  72.                                 LSA=1;LSB=1;LSC=1; break;//显示第7位       
  73.                 }
  74.                 P2=DisplayData[i];//发送段码
  75.                 Delay_ms(1);//间隔一段时间扫描       
  76.                 P2=0x00;//消隐
  77.         }
  78. }

  79. void datapros()
  80. {
  81.         uint adcnum;
  82.         adcnum=ADC_Read();
  83.         adcnum=adcnum*500/1024;
  84.         DisplayData[0]=smgduan[adcnum%1000%100%10/1];  //显示个位
  85.         DisplayData[1]=smgduan[adcnum%1000%100/10];                //显示十位
  86.         DisplayData[2]=smgduan[adcnum%1000/100];    //显示百位
  87.         DisplayData[3]=smgduan[adcnum/1000];        //显示千位
  88.         Delay_ms(10);
  89.        
  90. }

  91. void main()
  92. {
  93.   ADC_int(); //初始化ADC
  94.         while(1)
  95.   {
  96.                 datapros();    //数码管数据处理函数
  97.                 DigDisplay();  //数码管显示函数       
  98.                
  99.         }
  100. }
复制代码



回复

使用道具 举报

ID:236982 发表于 2019-8-21 17:35 | 显示全部楼层
        uint adcnum;
        adcnum=ADC_Read();
        adcnum=adcnum*500/1024; 数据超范围啦
回复

使用道具 举报

ID:592477 发表于 2019-8-21 18:48 | 显示全部楼层
suuy79 发表于 2019-8-21 17:35
uint adcnum;
        adcnum=ADC_Read();
        adcnum=adcnum*500/1024; 数据超范围啦

但是我看别人程序的,他用串口发送给电脑的却能正常显示?
  1.         void adcsend()
  2.         {
  3.                                 unsigned char a[4],b;
  4.         send=send*500/1024;        //电压计算
  5.                          a[0]=send%10+'0';               
  6.        a[1]=send/10%10+'0';               
  7.        a[2]='.';                                                  
  8.        a[3]=send/100+'0';               
  9.                 for(b=4;b>0;b--)             
  10.                 Uartsend(a[b-1]);     //从4-1=[3]个位开始依次[2][1][0]发送给数据
  11. }
复制代码
回复

使用道具 举报

ID:155507 发表于 2019-8-21 19:01 | 显示全部楼层
给你改了一下试试。

  1. #include "reg52.h"
  2. #include "intrins.h"

  3. typedef unsigned char uchar;
  4. typedef unsigned int uint;
  5. typedef unsigned long ulong;

  6. sfr T2H = 0xd6; //定时器2高8位
  7. sfr T2L = 0xd7; //定时器2低8位
  8. sfr AUXR  = 0x8e; //辅助寄存器
  9. sfr ADC_CONTR  = 0xBC; //ADC控制寄存器
  10. sfr ADC_RES = 0xBD; //ADC高8位结果
  11. sfr ADC_RESL = 0xBE; //ADC低2位结果
  12. sfr P1ASF = 0x9D; //P1口第2功能控制寄存器
  13. sfr CLK_DIV = 0x97;

  14. sbit LSA=P3^2;
  15. sbit LSB=P3^3;
  16. sbit LSC=P3^4;

  17. uchar code smgduan[17]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,
  18.         0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71};//显示0~F的值

  19. uchar DisplayData[8];



  20. void Delay_ms(unsigned int ms)//ms级延时
  21. {
  22.         unsigned int a,b;
  23.         for(a=ms;a>0;)
  24.         {
  25.                 for(b=1000;b>0;)
  26.                 {
  27.                         b=b-1;
  28.                 }
  29.                 a--;
  30.         }
  31. }
  32. void ADC_int()                //ADC初始化
  33. {
  34.         ADC_CONTR=0X80;         
  35.         P1ASF=0X01;         
  36.         CLK_DIV=0X20;            
  37.         ADC_RESL=0;                                                                        
  38.         ADC_RES=0;                                       
  39.         Delay_ms(10);                                
  40. }
  41. unsigned int ADC_Read()   
  42. {
  43.         unsigned int a=0;
  44.         ADC_CONTR = 0X88;                                                                        
  45.         Delay_ms(1);                                                                 
  46.         while(!(ADC_CONTR&0X10));  
  47.         a=ADC_RES*256+ADC_RESL;
  48.         ADC_CONTR&=~0x10;                                       
  49.         return a;               
  50. }
  51. void DigDisplay()
  52. {
  53.         uchar i;
  54.         for(i=0;i<8;i++)
  55.         {
  56.                 switch(i)         //位选,选择点亮的数码管,
  57.                 {
  58.                         case(0):
  59.                         LSA=0;LSB=0;LSC=0; break;//显示第0位
  60.                         case(1):
  61.                         LSA=1;LSB=0;LSC=0; break;//显示第1位
  62.                         case(2):
  63.                         LSA=0;LSB=1;LSC=0; break;//显示第2位
  64.                         case(3):
  65.                         LSA=1;LSB=1;LSC=0; break;//显示第3位
  66.                         case(4):
  67.                         LSA=0;LSB=0;LSC=1; break;//显示第4位
  68.                         case(5):
  69.                         LSA=1;LSB=0;LSC=1; break;//显示第5位
  70.                         case(6):
  71.                         LSA=0;LSB=1;LSC=1; break;//显示第6位
  72.                         case(7):
  73.                         LSA=1;LSB=1;LSC=1; break;//显示第7位        
  74.                 }
  75.                 P2=DisplayData[i];//发送段码
  76.                 Delay_ms(1);//间隔一段时间扫描        
  77.                 P2=0x00;//消隐
  78.         }
  79. }

  80. void datapros()
  81. {
  82.         ulong adcnum;
  83.         adcnum=ADC_Read();
  84.         adcnum=adcnum*500/1024;
  85.         DisplayData[0]=smgduan[adcnum%1000%100%10/1];  //显示个位
  86.         DisplayData[1]=smgduan[adcnum%1000%100/10];    //显示十位
  87.         DisplayData[2]=smgduan[adcnum%1000/100];       //显示百位
  88.         DisplayData[3]=smgduan[adcnum/1000];           //显示千位
  89.         Delay_ms(10);
  90.        
  91. }

  92. void main()
  93. {
  94.         ADC_int(); //初始化ADC
  95.         while(1)
  96.         {
  97.                 datapros();    //数码管数据处理函数
  98.                 DigDisplay();  //数码管显示函数        
  99.                
  100.         }
  101. }

复制代码
回复

使用道具 举报

ID:531987 发表于 2019-8-21 22:20 | 显示全部楼层
先将数据化为强制类型转换为整形,再将adcnum=adcnum*500/1024;里的500变为500.0,将结果转换为浮点型应该就行了,这问题我也遇到过
回复

使用道具 举报

ID:65956 发表于 2019-8-22 08:52 | 显示全部楼层
adcnum=adcnum*500/1024;关键就是这个算出来都是浮点数,所以当然不对,你应是定义为浮点数计算,然后再把结果数据放大为整数,然后再进行BCD解码,这样就OK了
回复

使用道具 举报

ID:466112 发表于 2020-2-17 23:23 | 显示全部楼层
将“adcnum=adcnum*500/1024"改为“adcnum=adcnum*0.49”就OK了。
回复

使用道具 举报

ID:445996 发表于 2020-3-26 18:57 | 显示全部楼层
根据楼上说的 你先乘0.49 然后乘100 得到49 *上前面的模拟值 然后模拟值会变成千位 你取千位和百位就可以避免浮点数运算
回复

使用道具 举报

ID:707815 发表于 2020-3-31 10:58 | 显示全部楼层
suuy79 发表于 2019-8-21 17:35
uint adcnum;
        adcnum=ADC_Read();
        adcnum=adcnum*500/1024; 数据超范围啦

没有超吧
回复

使用道具 举报

ID:30165 发表于 2024-4-17 08:54 | 显示全部楼层
adcnum=adcnum*500/1024; 要进行强制数据转换
改成 adcnum=500*(unsigned long)adcnun/1024
回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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