找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 1802|回复: 3
收起左侧

请各位朋友帮忙指正下我单片机电容值测试程序的错误

[复制链接]
ID:344887 发表于 2019-4-9 23:27 | 显示全部楼层 |阅读模式
50黑币
我的仿真只有第一档能够准确测量出电容容值,其余三挡不准确。请问是程序哪里出现错误了?能帮我指正一下吗?谢谢!

具体可查看附件。

1.png


档位        阻值                           量程

一档       R=77.2                        1~50微法
                              
二挡       R=772                         0.1~5微法

三挡       R=7720                       0.01~0.5微法

四挡       R=77200                    0.00~0.05微法

单片机源程序如下:
  1. #include <reg51.h>
  2. #include<intrins.h>//库函数

  3. #define DATA P0
  4. sbit RW=P2^1;//1602写数据
  5. sbit RS=P2^0;//1602写地址
  6. sbit EN=P2^2; //1602工作使能
  7. sbit b_test=P3^7;   //开始测量电容的按键输入
  8. sbit _reset=P3^5;   //555时基芯片工作控制信号
  9. unsigned int T_flag,N,C,i,Dis1,Dis0;
  10. unsigned int b[6]={0X13,0X0D,0X00,0X00,0X25,0X16};   //显示C=00UF

  11. /***********延时1MS******************/
  12. void Delay1ms(unsigned int mm)
  13. {unsigned int i;
  14. for(mm;mm>0;mm--)
  15.    for(i=100;i>0;i--);
  16. }
  17. /***************检查忙否*****************/
  18. void Checkstates()
  19. {
  20. unsigned char dat;
  21. RS=0;
  22. RW=1;
  23. do{EN=1;//下降沿
  24.     _nop_();//NOP为单周期指令,延时1微妙
  25.         _nop_();
  26.     dat=DATA;
  27.     _nop_();
  28.         _nop_();
  29.     EN=0;
  30. }while((dat&0x80)==1);
  31. }
  32. /**************LCD写命令函数*********/
  33. void wcomd(unsigned char cmd)
  34. {
  35. Checkstates();         //判忙
  36. RS=0;        //命令
  37. RW=0;         //写
  38. DATA=cmd; //准备发送命令
  39. EN=1;         //使能端为1时 ,允许数据交换
  40. _nop_();
  41. _nop_();
  42. _nop_();
  43. _nop_();
  44. EN=0;         //完成数据交换,使能端电位拉低
  45. }
  46. /**********LCD写数据函数**************/
  47. void wdata(unsigned char dat)
  48. {
  49. Checkstates();                 //判忙
  50. RS=1;                //数据
  51. RW=0;           //写
  52. DATA=dat;
  53. EN=1;
  54. _nop_();
  55. _nop_();
  56. _nop_();
  57. _nop_();
  58. EN=0;
  59. }
  60. /*****************初始化********************/
  61. void LCDINIT()
  62. {
  63. Delay1ms(5);
  64. wcomd(0x38);//显示功能设置
  65. Delay1ms(5);
  66. wcomd(0x38);
  67. Delay1ms(5);
  68. wcomd(0x01);//清屏
  69. Delay1ms(5);
  70. wcomd(0x08);//关显示
  71. Delay1ms(5);
  72. wcomd(0x0c);//开显示,不开光标

  73. }

  74. /***********显示函数**************/
  75. void Display(void) //显示函数
  76. {
  77. unsigned char i,j;
  78. unsigned char a[12]={0X4D,0X45,0X41,0X53,0X55,0X52,0X45,0X4D,0X45,0X4E,0X54,0X53};//显示measurements
  79. LCDINIT();
  80. for(i=0;i<12;i++)//写显示第一行
  81.   { wcomd(0x80+i);         //0x80di第一行第一个字符的地址
  82.     Delay1ms(1);
  83.     wdata(a[i]);
  84.     Delay1ms(1);
  85.    }

  86. for(j=0;j<6;j++)//写显示第二行
  87. {
  88.   wcomd(0xc0+j); //第二行第二个字符地址
  89.   Delay1ms(1);
  90.   wdata(0x30+b[j]);
  91.   Delay1ms(1);
  92.   }
  93. Delay1ms(150);

  94. }
  95. void main()
  96. {
  97.   EA=1;                          //打开全部的中断控制,并开启外部中断允许
  98.   TMOD=0x09;                        //T0为16位计数工作方式1
  99.   IT0=1;                            //设置外部中断的触发的方式为脉冲触发
  100.   TH0=0x00;
  101.   TL0=0x00;
  102.   T_flag=0;
  103.   _reset=0;
  104.   while(1)
  105.   {
  106.     while(!b_test)                   //如果有测量按键输入就往下执行
  107.     {
  108.      i=0;
  109.      _reset=1;                      //启动555时基芯片
  110.      EX0=1;          //开启中断0
  111.      while(_reset)   //超出等待时间,中断还没有过来,就退出
  112.       {
  113.        i++;
  114.        if(i>5000)   //设置最长等待时间
  115.         {
  116.          _reset=0;  //最长等待时间到还没有中断,停止555
  117.         }
  118.       }
  119.      if(N<100)         //如果计数值小于100,显示SM,表示应换用小一点的量程
  120.       {
  121.        b[3]=0X1D;
  122.        b[2]=0X23;
  123.       }
  124.      if(N>5000)        //如果计数值大于5000,显示LA,表示应换用大一点的量程
  125.       {
  126.        b[3]=0X11;
  127.        b[2]=0X1C;
  128.       }
  129.      if(N>=100 && N<=5000)
  130.       {
  131.        C=N/100;         //计算电容的大小
  132.        b[2]=C/10;       //计算电容值的十位
  133.        b[3]=C-b[2]*10;  //计算电容值的各位
  134.       }
  135.      }
  136.     Display(); //显示电容的大小
  137.    }
  138. }
  139. void int0(void) interrupt 0   //第一次中断开始计数,第二个中断停止计数
  140. {
  141.   T_flag=!T_flag;
  142.   if(T_flag==1)
  143.   {
  144.    TR0=1;         //开始计时
  145.   }
  146.   if(T_flag==0)
  147.   {
  148.    TR0=0;         //停止计时
  149.    EX0=0;         //关闭中断
  150.    _reset=0;      //停止发出方波
  151.    N=TH0*256+TL0; //计算计数器的值
  152.    N=N*5/3;
  153.    TH0=0x00;      //恢复初值
  154.    TL0=0x00;
  155.   }
  156. }
复制代码


C语言.docx

87.99 KB, 下载次数: 4

回复

使用道具 举报

ID:123289 发表于 2019-4-10 11:04 | 显示全部楼层
问一下:你是如何保证:开始与结束刚好是一个周期?
提示:振荡第一个波的周期,与其它的周期可能存在不同。
回复

使用道具 举报

ID:344887 发表于 2019-4-10 23:51 | 显示全部楼层
yzwzfyz 发表于 2019-4-10 11:04
问一下:你是如何保证:开始与结束刚好是一个周期?
提示:振荡第一个波的周期,与其它的周期可能存在不同 ...

利用电容充放电,然后555芯片输出方波控制中断0,同时计数器对方波进行计数,由此算出方波的频率。
回复

使用道具 举报

ID:344887 发表于 2019-4-11 10:38 | 显示全部楼层
yzwzfyz 发表于 2019-4-10 11:04
问一下:你是如何保证:开始与结束刚好是一个周期?
提示:振荡第一个波的周期,与其它的周期可能存在不同 ...

基于AT89C51单片机和555芯片构成的多谐振荡电路设计一电容测量电路,这种测量方法主要是通过一块555芯片来测量电容大小。让555芯片工作在直接反馈无稳态的状态下,555芯片输出一定频率的方波,其频率的大小跟被测量的电容之间的关系是:f=0.772/(R*Cx) ,固定R的大小,其公式就可以写为:f=k/Cx,只要能够测量出555芯片输出的频率,就可以计算出测量的电容。计算频率的方法可以利用单片机的计数器T0和中断INT0配合使用来进行测量。
回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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