模吧

 找回密码
 立即注册

QQ登录

只需一步,快速开始

手机号码,快捷登录

[单片机课堂] 第十三课:扩展课!电压变成数字

  [复制链接]
发表于 2016-12-3 12:22:39 | 显示全部楼层
学习,学习。。。好教程要顶起来!!!!!!!!!!!!!!
回复 支持 1 反对 0

使用道具 举报

发表于 2016-12-3 20:57:30 | 显示全部楼层
你好,我想自制一个简易微型万用表,具有常用的简单功能,可以挂在钥匙上,偶尔用一下。
我的单片机是20脚的12c5608ad,为了减少接口和缩小体积,想用一个数码管依次显示几位数字。

使用小型锂电池供电,电压3.5到4.2v。
基本功能为:直流电压-2到10v -20到100v,二极管压降0到3v,电阻0到3k。
电压接口并联蓝色发光管作为限压保护,压降2.7v,反向用4148,压降0.6v。
基本测量范围-1到2.5v,用431产生1v作为基准,以便能够测量电压极性。
单片机输出pwm产生1ma恒流,为测量二极管和电阻提供电流,使电阻测量比较准确。
回复 支持 1 反对 0

使用道具 举报

发表于 2016-12-3 22:43:26 | 显示全部楼层

收到,马上补上~!
回复 支持 1 反对 0

使用道具 举报

 楼主| 发表于 2016-12-3 23:05:50 | 显示全部楼层
长寿烙铁 发表于 2016-12-3 20:57
你好,我想自制一个简易微型万用表,具有常用的简单功能,可以挂在钥匙上,偶尔用一下。
我的单片机是20脚 ...

这么复杂,哪里还叫简易……测个电压电流还算简单,电阻二极管就不推荐搞了
回复 支持 2 反对 0

使用道具 举报

发表于 2016-12-3 23:41:14 | 显示全部楼层
我爱萝丽爱萝丽 发表于 2016-12-3 23:05
这么复杂,哪里还叫简易……测个电压电流还算简单,电阻二极管就不推荐搞了 ...

支持老师,等知识慢慢积累到一定程度自然就懂了。先做电流电压的。
回复 支持 0 反对 1

使用道具 举报

发表于 2016-12-3 23:49:34 | 显示全部楼层
长寿烙铁 发表于 2016-12-3 20:57
你好,我想自制一个简易微型万用表,具有常用的简单功能,可以挂在钥匙上,偶尔用一下。
我的单片机是20脚 ...

说实在话,我们维修人都希望有个自己diy而又实用的东西,但涉及的知识面太广,难以实现。
回复 支持 1 反对 0

使用道具 举报

发表于 2016-12-4 00:40:15 | 显示全部楼层
萝丽老师,我紧跟这你的教程学习和实验,数码管的后两位数字变化不稳定,有时看不清,这该怎么解决呢?下一步是不是就该讲到了?
回复 支持 0 反对 1

使用道具 举报

发表于 2016-12-4 07:51:01 | 显示全部楼层
别具一格的教程初学者喜欢
回复 支持 1 反对 0

使用道具 举报

 楼主| 发表于 2016-12-4 16:23:07 | 显示全部楼层
my21602 发表于 2016-12-4 00:40
萝丽老师,我紧跟这你的教程学习和实验,数码管的后两位数字变化不稳定,有时看不清,这该怎么解决呢?下一 ...

你的电路和程序是否跟例程一样?数码管后两位没问题
回复 支持 1 反对 0

使用道具 举报

发表于 2016-12-4 20:26:19 | 显示全部楼层
我爱萝丽爱萝丽 发表于 2016-12-3 23:05
这么复杂,哪里还叫简易……测个电压电流还算简单,电阻二极管就不推荐搞了 ...

电路不复杂,我画了测量电路的草图,恒流电路需要试验和调整一下,应该可行。
我对pwm输出还不太懂,还要学习和试验,电阻二极管的测量是比较常用的。 第十三课:扩展课!电压变成数字  作者:长寿烙铁 8383
回复 支持 0 反对 1

使用道具 举报

发表于 2016-12-4 20:30:04 | 显示全部楼层
panlongdian 发表于 2016-12-3 23:49
说实在话,我们维修人都希望有个自己diy而又实用的东西,但涉及的知识面太广,难以实现。 ...

电路不复杂,我画了测量电路的草图,恒流电路需要试验和调整一下,应该可行。
回复 支持 1 反对 0

使用道具 举报

 楼主| 发表于 2016-12-4 23:25:36 | 显示全部楼层
长寿烙铁 发表于 2016-12-4 20:26
电路不复杂,我画了测量电路的草图,恒流电路需要试验和调整一下,应该可行。
我对pwm输出还不太懂,还要 ...

你还是用最简单的电阻串联分压测量电阻吧,比你这个简单10倍
回复 支持 1 反对 0

使用道具 举报

 楼主| 发表于 2016-12-5 00:51:46 | 显示全部楼层
my21602 发表于 2016-12-4 00:40
萝丽老师,我紧跟这你的教程学习和实验,数码管的后两位数字变化不稳定,有时看不清,这该怎么解决呢?下一 ...

你应该是没接电位器,显示的电压当然会乱跳
回复 支持 1 反对 0

使用道具 举报

 楼主| 发表于 2016-12-5 03:37:29 | 显示全部楼层
本帖最后由 我爱萝丽爱萝丽 于 2016-12-27 23:58 编辑

1.3 项目规划

上次说到如何把ADC转换结果转换为电压,这个算法应该中学生都会:(前提是单片机5V要准)
  电压x        adc
————= ———
    5V           255
所以电压x=adc/255*5=adc/51。假设adc=128,x=2.5。
不过要注意,由于单片机没有小数点,你要是想精确到小数点后,需要把adc扩大10倍,x=25,显示时再补上小数点。

思考题:a=29*10/10; 与 b=29/10*10; 有什么区别?
表面上好像一样,实际上大不相同!
a=29*10/10 =290/10 =29;
b=29/10*10 =2*10 =20;
由于单片机的除法会损失精度,所以必须先乘后除。

学了新知识,就要学以致用。本期的项目就是要做一个实用的小电压表。


根据已学到的知识,你起码可以完成的最低要求:
单片机使用稳压5V或3.3V供电,测量一路0~5V或0~3.3V电压。


中等要求:
单片机稳压供电,用10k、10k电阻分压,量程增加2倍。
增加数码管显示小数点功能。


扩展要求:
多路不同量程电压测量,自动切换显示或按键切换……
使用10位ADC或多次测量求平均值等方法提高精度……





一个实现中等要求的小程序:
  1. #include<reg51.h>

  2. sfr P2M0=0x96;     //声明 P2引脚模式寄存器
  3. sfr P3M0=0xb2;     //声明 P3引脚模式寄存器
  4. sfr P1ASF=0x9D;    //声明 P1口模拟功能寄存器
  5. sfr ADC_RES=0xBD;  //声明 ADC转换结果寄存器
  6. sfr ADC_CONTR=0xBC;//声明 ADC控制寄存器


  7. sbit DA=P2^4;                        //数码管每个引脚
  8. sbit DB=P3^2;
  9. sbit DC=P3^6;
  10. sbit DD=P2^0;
  11. sbit DE=P2^1;
  12. sbit DF=P2^3;
  13. sbit DG=P3^5;
  14. sbit DP=P3^7;

  15. sbit B1=P2^5;                        //四个数码管的引脚定义
  16. sbit B2=P2^2;
  17. sbit B3=P3^3;
  18. sbit B4=P3^4;


  19. unsigned char display_time;        //定义变量用于显示次数

  20. unsigned char Data1;        //第一个数码管要显示的数据
  21. unsigned char Data2;        //第二个数码管要显示的数据
  22. unsigned char Data3;        //第三个数码管要显示的数据
  23. unsigned char Data4;        //第四个数码管要显示的数据

  24. unsigned char count;        //计时
  25. unsigned int adc;          //AD转换计算


  26. void Delay1ms()                //@12.000MHz
  27. {
  28.         unsigned char i, j;

  29.         i = 12;
  30.         j = 169;
  31.         do
  32.         {
  33.                 while (--j);
  34.         } while (--i);
  35. }

  36. void delay_n_ms(unsigned int n) //延时n毫秒函数
  37. {
  38.         while(n)         
  39.         {
  40.                 Delay1ms();
  41.                 n=n-1;//每循环一次n减小1
  42.         }   
  43. }

  44. void Delay50us()                //@12.000MHz
  45. {
  46.         unsigned char i, j;

  47.         i = 1;
  48.         j = 146;
  49.         do
  50.         {
  51.                 while (--j);
  52.         } while (--i);
  53. }

  54. void display(unsigned char x)//控制数码管显示内容的函数
  55. {
  56.         //判断x的值来决定显示什么
  57.         if(x==0){DA=1;DB=1;DC=1;DD=1;DE=1;DF=1;DG=0;DP=0;} //显示“0”        
  58.         if(x==1){DA=0;DB=1;DC=1;DD=0;DE=0;DF=0;DG=0;DP=0;} //显示“1”        
  59.         if(x==2){DA=1;DB=1;DC=0;DD=1;DE=1;DF=0;DG=1;DP=0;} //显示“2”        
  60.         if(x==3){DA=1;DB=1;DC=1;DD=1;DE=0;DF=0;DG=1;DP=0;} //显示“3”
  61.         if(x==4){DA=0;DB=1;DC=1;DD=0;DE=0;DF=1;DG=1;DP=0;} //显示“4”        
  62.         if(x==5){DA=1;DB=0;DC=1;DD=1;DE=0;DF=1;DG=1;DP=0;} //显示“5”        
  63.         if(x==6){DA=1;DB=0;DC=1;DD=1;DE=1;DF=1;DG=1;DP=0;} //显示“6”        
  64.         if(x==7){DA=1;DB=1;DC=1;DD=0;DE=0;DF=0;DG=0;DP=0;} //显示“7”        
  65.         if(x==8){DA=1;DB=1;DC=1;DD=1;DE=1;DF=1;DG=1;DP=0;} //显示“8”        
  66.         if(x==9){DA=1;DB=1;DC=1;DD=1;DE=0;DF=1;DG=1;DP=0;} //显示“9”
  67.                                                         
  68.         if(x==10){DA=1;DB=1;DC=1;DD=1;DE=1;DF=1;DG=0;DP=1;} //显示“0”带小数点        
  69.         if(x==11){DA=0;DB=1;DC=1;DD=0;DE=0;DF=0;DG=0;DP=1;} //显示“1”带小数点        
  70.         if(x==12){DA=1;DB=1;DC=0;DD=1;DE=1;DF=0;DG=1;DP=1;} //显示“2”带小数点        
  71.         if(x==13){DA=1;DB=1;DC=1;DD=1;DE=0;DF=0;DG=1;DP=1;} //显示“3”带小数点
  72.         if(x==14){DA=0;DB=1;DC=1;DD=0;DE=0;DF=1;DG=1;DP=1;} //显示“4”带小数点        
  73.         if(x==15){DA=1;DB=0;DC=1;DD=1;DE=0;DF=1;DG=1;DP=1;} //显示“5”带小数点        
  74.         if(x==16){DA=1;DB=0;DC=1;DD=1;DE=1;DF=1;DG=1;DP=1;} //显示“6”带小数点
  75.         if(x==17){DA=1;DB=1;DC=1;DD=0;DE=0;DF=0;DG=0;DP=1;} //显示“7”带小数点        
  76.         if(x==18){DA=1;DB=1;DC=1;DD=1;DE=1;DF=1;DG=1;DP=1;} //显示“8”带小数点
  77.         if(x==19){DA=1;DB=1;DC=1;DD=1;DE=0;DF=1;DG=1;DP=1;} //显示“9”带小数点
  78. }


  79. main()
  80. {
  81.         P2M0=0x1B;                //需要高电平大电流的引脚 2.4、2.3、2.1、2.0,填入数值0001 1011
  82.         P3M0=0xE4;                //需要高电平大电流的引脚 3.7、3.6、3.5、3.2,填入数值1110 0100
  83.         
  84.         P1ASF=0x80;  //设置P1.7引脚为模拟功能
  85.         
  86.         while(1)
  87.         {
  88.                 delay_n_ms(4);//系统周期4ms
  89.                
  90.                 count=count+1;
  91.                 if(count>125)  //0.5秒测量一次电压
  92.                 {
  93.                         count=0;
  94.                         
  95.                         ADC_CONTR=0x88+7;  //开始P1.7引脚转换
  96.                         Delay50us();   //等待AD转换完成
  97.                         adc=ADC_RES;  //读取转换结果
  98.                         
  99.                         adc=adc*2;      //量程增大倍数
  100.                         adc=adc*10/51;  //计算电压*10倍,消除小数点                        
  101.                         
  102.                         Data1=0;
  103.                         Data2=adc/100;          //百位数据
  104.                         Data3=adc%100/10; //十位数据
  105.                         Data3=Data3+10;   //加10,display函数显示的数字会带小数点
  106.                         
  107.                         Data4=adc%10;     //个位数据        
  108.                 }
  109.                
  110.                
  111.                 ///////////////////////////////////////////////////////
  112.                 //显示程序模块化,只需要改变Data1/2/3/4的值就可以控制显示内容
  113.                
  114.                 display_time=display_time+1;
  115.                 if(display_time>3)
  116.                 {
  117.                         display_time=0;  //0、1、2、3 四个循环
  118.                 }
  119.                
  120.                 if(display_time==0)//第0次显示第一个数码管
  121.                 {
  122.                         B1=0;B2=1;B3=1;B4=1;        
  123.                         display(Data1);                //显示第1位数据
  124.                 }
  125.                
  126.                 if(display_time==1)//第1次显示第二个数码管
  127.                 {
  128.                         B1=1;B2=0;B3=1;B4=1;        
  129.                         display(Data2);                //显示第2位数据
  130.                 }
  131.                
  132.                 if(display_time==2)//第2次显示第三个数码管
  133.                 {
  134.                         B1=1;B2=1;B3=0;B4=1;        
  135.                         display(Data3);                //显示第3位数据
  136.                 }
  137.                
  138.                 if(display_time==3)//第3次显示第四个数码管
  139.                 {
  140.                         B1=1;B2=1;B3=1;B4=0;        
  141.                         display(Data4);                //显示第4位数据
  142.                 }
  143.                         
  144.                
  145.         }
  146. }
复制代码




回复 支持 1 反对 0

使用道具 举报

发表于 2016-12-5 05:57:14 | 显示全部楼层
本帖最后由 我是天才 于 2016-12-5 06:08 编辑

大神,看看我的转化方法行不?
http://www.moz8.com/thread-82795-1-1.html我有认真完成作业哟~嘿嘿
回复 支持 1 反对 0

使用道具 举报

发表于 2016-12-5 08:28:29 | 显示全部楼层
好东西啊!顶!!!!!!!!
回复 支持 1 反对 0

使用道具 举报

 楼主| 发表于 2016-12-5 14:11:15 | 显示全部楼层
我是天才 发表于 2016-12-5 05:57
大神,看看我的转化方法行不?
http://www.moz8.com/thread-82795-1-1.html我有认真完成作业哟~嘿嘿 ...

注意要先乘后除,不然损失精度
回复 支持 0 反对 1

使用道具 举报

发表于 2016-12-5 21:06:02 | 显示全部楼层
我爱萝丽爱萝丽 发表于 2016-12-4 23:25
你还是用最简单的电阻串联分压测量电阻吧,比你这个简单10倍

恒流电路主要用于二极管测量,并且可以测量电阻。

下面是我用旧仪表改的简易数字万用表
旧仪表电路由测量芯片7106和7660升压电路组成,可用锂电池供电。
改成简易万用表,实现常用功能0.2V 20V 200V。

增加用431组成的1ma恒流电路,测量元件的压降或电阻。
还可以增加一个电阻丝,测量2A电流。

跟你学习了一些单片机知识,我感觉单片机功能强大,应该能够实现这些功能,并且实现小型化。
第十三课:扩展课!电压变成数字  作者:长寿烙铁 9960
回复 支持 1 反对 0

使用道具 举报

发表于 2016-12-5 21:28:19 | 显示全部楼层
我爱萝丽爱萝丽 发表于 2016-12-5 14:11
注意要先乘后除,不然损失精度

嗯,已经改了,
回复 支持 1 反对 0

使用道具 举报

发表于 2016-12-5 23:51:57 | 显示全部楼层
楼主讲解下怎样才能两路adc转换呗?比如说p1.7和P1.6一起转换,得到的数据分别保存为adc1和adc2
回复 支持 1 反对 0

使用道具 举报

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

本版积分规则

QQ|关于模吧|APP下载|广告报价|小黑屋|手机版|企业会员|商城入驻|联系我们|模吧 ( 冀公网安备13080502000084号 )

© 2013-2020 Moz8.com 模吧,玩出精彩!