找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 4199|回复: 1
打印 上一主题 下一主题
收起左侧

自制万用表Proteus仿真(RLC检测电路+单片机程序)

[复制链接]
跳转到指定楼层
楼主
自制仪表仿真原理图如下(proteus仿真工程文件可到本帖附件中下载)

单片机源程序如下:
  1. #include<reg52.h>
  2. #define uchar unsigned char   //宏定义
  3. #define uint  unsigned int
  4. sbit RS=P2^6;                 //液晶控制端口
  5. sbit RW=P2^5;
  6. sbit E=P2^7;

  7. sbit R=P2^2;                  //RLC控制按键
  8. sbit C=P2^3;
  9. sbit L=P2^4;

  10. sbit A=P2^0; //控制IO口
  11. sbit B1=P2^1;


  12. sbit jd1=P1^0; //继电器1
  13. sbit jd2=P1^1; //继电器2


  14. sbit LED_R=P1^3;                  //RLC指示灯
  15. sbit LED_C=P1^4;
  16. sbit LED_L=P1^5;   
  17. uchar code table1[11]={"R=        R"};    //RLC显示数组
  18. uchar code table2[11]={"C=       pF"};
  19. uchar code table3[11]= {"L=       mH"};
  20. uchar code f_table[88]={13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100};
  21. uchar code f_correct[88]={9,10,11,12,12,12,13,14,15,16,17,18,18,18,19,20,21,21,22,23,24,25,25,26,26,27,28,29,29,30,30,31,32,33,33,34, 35,35,36,37,38,38,39,40,41,41,42,42,43,44,45,45,46,47,48,49,49,50,51,51,52,53,54,54,55,55,56,57,57,58,59,60,60,62,62,63,64,64,65,66,66,67,67,68,69,70,71,71,};
  22. uchar data7,data6,data5,data4,data3,data2,data1;    //数据变量
  23. uchar flag;                                   //转换完成标志位
  24. unsigned long cnt,cnt1;                       //长整形数据 记录振荡器计数的次数
  25. uchar f_cnt;                                  //时间溢出次数变量
  26. //函数声明
  27. void delay_us();          //us延时
  28. void delay_ms(uint);      //ms延时
  29. void lcd_init();          //1602初始化
  30. void lcd_write_com(uchar com);     //写命令
  31. void lcd_write_dat(uchar dat);     //写数据
  32. void lcd_display(uchar add,uchar dat);  //指定地址写数据
  33. void delay_us()             //us延时
  34. {
  35.         uchar x=6;
  36.         while(x--);
  37. }
  38. void delay_ms(uint aa)       //ms延时
  39. {
  40.         uint x,y;
  41.         for(x=0;x<aa;x++)
  42.                 for(y=0;y<110;y++);
  43. }
  44. void lcd_write_com(uchar com)    //写命令
  45. {
  46.   E=0;
  47.   RS=0;
  48.   RW=0;
  49.   delay_us();
  50.   P0=com;
  51.   E=1;           
  52.   delay_us();
  53.   E=0;
  54. }
  55. void lcd_write_dat(uchar dat)     //写数据
  56. {
  57.   E=0;
  58.   RS=1;
  59.   RW=0;
  60.   delay_us();
  61.   P0=dat;
  62.   E=1;            
  63.   delay_us();
  64.   E=0;
  65. }
  66. void lcd_init()                  //lcd初始化
  67. {
  68.    delay_ms(10);
  69.    lcd_write_com(0x38);         //设置显示模式
  70.    delay_ms(10);
  71.    lcd_write_com(0x0c);
  72.          lcd_write_com(0x06);
  73.          lcd_write_com(0x01);        //清屏指令
  74.          delay_ms(2);
  75. }

  76. void timer_init(void)  //定时器初始化函数
  77. {
  78.         TMOD=0X51;          //设置定时器工作模式
  79.         PT0=1;     
  80.         TH0=0x3c;           //给定时器0装设初值 50ms
  81.         TL0=0xb0;
  82.         TH1=0;              //不设初值
  83.         TL1=0;
  84.         ET0=1;              //开中断
  85.         ET1=1;
  86.         TR0=1;              //开定时器
  87.         TR1=1;
  88.         EA=1;               //开总中断
  89. }
  90. void lcd_display(uchar add,uchar dat)           //lcd指定地址写数据
  91. {
  92.         lcd_write_com(add);                  
  93.         lcd_write_dat(dat);
  94.         delay_us();
  95. }
  96. void real_display(void)                        //数据显示函数
  97. {
  98.   if(!R)                                        //检测的是电阻              
  99.    {     
  100.       A=0;B1=0;                 
  101.                         LED_R=0;
  102.       LED_L=1;
  103.       LED_C=1;                  
  104.                         lcd_display(0x80,table1[0]);
  105.                         lcd_display(0x80+1,table1[1]);
  106.                         lcd_display(0x80+9,table1[9]);
  107.                         lcd_display(0x80+10,table1[10]);               
  108.    }                  
  109.    else
  110.           if(!C)                                        //检测的是电容
  111.      {     
  112.         A=1;B1=0;                        
  113.        LED_C=0;
  114.        LED_L=1;
  115.        LED_R=1;      
  116.        lcd_display(0x80,table2[0]);
  117.        lcd_display(0x80+1,table2[1]);
  118.        lcd_display(0x80+9,table2[9]);
  119.        lcd_display(0x80+10,table2[10]);
  120.      }
  121.       else
  122.          if(!L)                                           //检测的是电感
  123.      {     
  124.          A=0;B1=1;                        
  125.         LED_L=0;
  126.         LED_R=1;
  127.         LED_C=1;                        
  128.         lcd_display(0x80,table3[0]);
  129.                                 lcd_display(0x80+1,table3[1]);
  130.                                 lcd_display(0x80+9,table3[9]);
  131.                                 lcd_display(0x80+10,table3[10]);
  132.      }
  133.                  else
  134.      {
  135.                    LED_L=1;
  136.        LED_R=1;
  137.        LED_C=1;
  138.                  }
  139.                 if(data7)
  140.      lcd_display(0x80+2,0x30+data7);         //最高位数据不等于零就显示
  141.     else
  142.      lcd_display(0x80+2,' ');             //否则显示空格     以下同样
  143.     if(data7||data6)
  144.      lcd_display(0x80+3,0x30+data6);         //最高位数据不等于零就显示
  145.     else
  146.      lcd_display(0x80+3,' ');             //否则显示空格     以下同样
  147.     if(data7||data6||data5)
  148.      lcd_display(0x80+4,0x30+data5);
  149.     else
  150.      lcd_display(0x80+4,' ');
  151.     if(data7||data6||data5||data4)
  152.      lcd_display(0x80+5,0x30+data4);   
  153.     else
  154.      lcd_display(0x80+5,' ');
  155.     if(data7||data6||data5||data4||data3)
  156.      lcd_display(0x80+6,0x30+data3);      
  157.     else
  158.      lcd_display(0x80+6,' ');
  159.     if(data7||data6||data5||data4||data3||data2)
  160.      lcd_display(0x80+7,0x30+data2);
  161.     else
  162.      lcd_display(0x80+7,' ');
  163.      lcd_display(0x80+8,0x30+data1);       //显示最低位
  164. }


  165. void correct(void)                   //误差修正函数               
  166. {
  167.   uchar i,k;
  168.         unsigned long wucha;
  169.         if(cnt<100000)                     //修正频率范围         
  170.          {            
  171.                  if(cnt>980&&cnt<2100)           //在不同频率对数据进行修改 经验值 资料参考
  172.                         cnt-=1;            
  173.                  if(cnt>=2100&&cnt<3900)
  174.                         cnt-=2;         
  175.                  if(cnt>=3900&&cnt<4800)  
  176.                         cnt-=3;      
  177.                  if(cnt>=4800&&cnt<5700)  
  178.                         cnt-=4;           
  179.                  if(cnt>=5700&&cnt<8000)  
  180.                         cnt-=5;               
  181.                  if(cnt>=8000&&cnt<9100)     
  182.                         cnt-=6;      
  183.                  if(cnt>=9100&&cnt<10900)
  184.                         cnt-=7;
  185.                  if(cnt>=10900&&cnt<11900)
  186.                         cnt-=8;
  187.                  if(cnt>=11900&&cnt<13000)
  188.                         cnt-=9;         
  189.                  if(cnt>=13000&&cnt<=100000)
  190.                          {
  191.                                  k=cnt/1000;
  192.                                  for(i=0;i<88;i++)
  193.                                         {
  194.                                                         if(k==f_table[i])
  195.                                                         {
  196.                                                          cnt-=f_correct[i];
  197.                                                         }
  198.                                         }
  199.                          }  
  200.   }
  201.          if(cnt>100000)                     
  202.          {
  203.                 wucha=(cnt/1000)*73065/100000;
  204.                 cnt-=wucha;   
  205.          }
  206. }

  207. void main()
  208. {
  209.         jd2=0;
  210.         timer_init();             //定时器初始化
  211.         lcd_init();               //液晶初始化
  212.         if(!C)                                        //检测的是电容
  213.      {     
  214.         A=1;B1=0;
  215.                  }else
  216.                  if(!R)                                        //检测的是电阻              
  217.    {     
  218.       A=0;B1=0;        
  219.          }else
  220.          if(!L)                                           //检测的是电感
  221.      {     
  222.          A=0;B1=1;        
  223.                  }
  224.   while(1)
  225.   {               
  226.                 if(flag==1)             //数据转化完成
  227.                 {
  228.                          real_display();       //数据处理并显示
  229.                          flag=0;
  230.                 }
  231.   }
  232. }
  233. void timer0() interrupt 1          //定时器0中断函数
  234. {
  235.         uchar timer0;
  236.         TH0=0x3c;          //50ms定时
  237.         TL0=0xb0;
  238.         timer0++;          //时间变量
  239.         if(timer0==20)     //1s进入一次
  240.          {
  241.                 timer0=0;
  242.                 TR1=0;                        //定时器1中断关闭
  243.                 EA=0;                         //总中断关闭
  244.                 cnt=TL1+TH1*256+f_cnt*65536;  //计算1S计数的个数
  245.                 correct();                   //修正一下数据
  246.                 cnt1=(1e+9)/(2*0.693 *cnt)-20000/2;  //如果开关都不按下 计算数值并且显示
  247.         if(!R)           
  248.         {
  249.                  A=0;B1=0;
  250.                 cnt1=(500000/(0.2*0.693*cnt))-120;    //计算电阻值 R1=T/(ln2*C-2R2)  此处电容200uf (ln2=0.693)
  251.         }                                      //1000000us=1s   此处是修正好的数据  
  252.         else
  253.         if(!C)
  254.         {
  255.                  A=1;B1=0;
  256.                 cnt1=100000000/(0.693*3*510*cnt);   //计算电容值 C=T/((R1+2R2)ln2) 此处        R1=R2=5100
  257.         }
  258.         else
  259.         if(!L)            
  260.         {   
  261.      A=0;B1=1;               
  262.                 cnt1=(1e+9)/(4*3.14*3.14*cnt*cnt*0.0463);  //计算电感值  L=T/(4*3.14*3.14*C)  C=(C1+C2)/(C1*2C)  电容三点式
  263.         }  
  264.         if(!R)  
  265.         {
  266.    if(cnt1>1000)        
  267.          {
  268.            jd1=1;
  269.          }
  270.          else
  271.          {jd1=0;}
  272.          }
  273.         if(!C)  
  274.         {
  275.    if(cnt1>1000)        
  276.          {
  277.            jd2=1;
  278.          }
  279.          else
  280.          {jd2=0;}
  281.          }
  282.     data7=cnt1/1000000;
  283.                 data6=cnt1%1000000/100000;          //将数据的各位取出
  284.                 data5=cnt1%100000/10000;
  285.                 data4=cnt1%10000/1000;
  286.                 data3=cnt1%1000/100;
  287.                 data2=cnt1%100/10;
  288.                 data1=cnt1%10;  
  289.                 flag=1;                    //测量完成标志位
  290.                 TH1=0;                     //给定时器装设初始值 T0 T1
  291.                 TL1=0;
  292.                 TH0=0x3c;                  //定时器0装设初值  50ms
  293.                 TL0=0xb0;
  294.                 cnt=0;                     //记录时间清零
  295.                 f_cnt=0;                   //记录时间清零
  296.                 EA=1;                      //打开总中断
  297.                 TR1=1;                     //打开定时器1中断
  298.         }
  299. }      
  300. void int1() interrupt 3        // 定时器1中断函数 计算时间(溢出次数)
  301. {
  302.   f_cnt++;
  303. }
复制代码

所有资料51hei提供下载:
仿真(RLC检测电路).zip (275.26 KB, 下载次数: 124)



分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏3 分享淘帖 顶 踩
回复

使用道具 举报

沙发
ID:727862 发表于 2020-4-15 16:13 | 只看该作者
用的仿真软件不是proteus??
回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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