本帖最后由 E08610225 于 2012-11-4 22:16 编辑
“版主评论:
此贴子质量不错哟~~~希望大家多发类似的仿真或实例哟~
这个小实例,比较适合于初级、中级之间的朋友们去做一下~~~
1.涉及到外围电路搭建,可以提高大家的单片机应用综合性水平。
2.学习外围常用芯片。
3.提供一些设计思路。单片机设计无非就是经验的综合~所以,积累类似的小经验是对设计很有用的~
由于可以仿真,所以,操作起来就更方便了。”
正文:
这种电容测量方法主要是通过一块555芯片来测量电容,让555芯片工作在直接反馈无稳态的状态下,555芯片输出一定频率的方波,其频率的大小跟被测量的电容之间的关系是:f=0.772/(R*Cx),我们固定R的大小,其公式就可以写为:f=k/Cx,只要我们能够测量出555芯片输出的频率,就可以计算出测量的电容。计算频率的方法可以利用单片机的计数器T0和中断INT0配合使用来测量。
555时基芯片的输出频率跟所使用的电阻R和电容Cx的关系是:f=0.772/(R*Cx), 又因为T=1/f,所以 T=R*Cx/0.772 即:Cx=0.772*T/R 如果单片机采用12M的晶振,计数器T0的值增加1,时间就增加1μS ,采用中断的方式来启动和停止计数器T0,中断的触发方式为脉冲下降沿触发,第一次中断到来启动T0,计数器的值为N1,第二次中断到来停止T0,
计数器器的值为N2,则测量方波的周期为 T=(N2-N1)*1μS,如开始时刻计数器的值N1=0,则
。 则
单片机的计数器的值N=0-65535,为了测量的精度,N的取值一般在100~5000,当电阻R越大,电容C的值就越小。取不同的电阻值,就得到不同的电容测量的量程,这里我因需测30pF左右的电容,取R=77200k,为了编写程序的方便,只计算N/100,后面的单位可以根据使用的量程自行添加.
proteus仿真电路截图如下:
proteus仿真结果:
51程序(keil):
- #include "reg51.h"
- #include"intrins.h"//库函数
- #define DATA P0
- sbit RW=P2^1;//1602写数据
- sbit RS=P2^0;//1602写地址
- sbit EN=P2^2; //1602工作使能
- sbit b_test=P3^7; //开始测量电容的按键输入
- sbit _reset=P3^5; //555时基芯片工作控制信号
- unsigned int T_flag,N,C,i,Dis1,Dis0;
- unsigned int b[6]={0X13,0X0D,0X00,0X00,0X40,0X16}; //显示C=00pF
- /***********延时1MS******************/
- void Delay1ms(unsigned int mm)
- {unsigned int i;
- for(mm;mm>0;mm--)
- for(i=100;i>0;i--);
- }
- /***************检查忙否*****************/
- void Checkstates()
- {
- unsigned char dat;
- RS=0;
- RW=1;
- do{EN=1;//下降沿
- _nop_();//保持一定间隔
- _nop_();
- dat=DATA;
- _nop_();
- _nop_();
- EN=0;
- }while((dat&0x80)==1);
- }
- /**************LCD写命令函数*********/
- void wcomd(unsigned char cmd)
- {
- Checkstates();
- RS=0;
- RW=0;
- DATA=cmd;
- EN=1;
- _nop_();
- _nop_();
- _nop_();
- _nop_();
- EN=0;
- }
- /**********LCD写数据函数**************/
- void wdata(unsigned char dat)
- {
- Checkstates();
- RS=1;
- RW=0;
- DATA=dat;
- EN=1;
- _nop_();
- _nop_();
- _nop_();
- _nop_();
- EN=0;
- }
- /*****************初始化********************/
- void LCDINIT()
- {
- Delay1ms(15);
- wcomd(0x38);//功能设置
- Delay1ms(5);
- wcomd(0x38);//功能设置
- Delay1ms(5);
- wcomd(0x01);//清屏
- Delay1ms(5);
- wcomd(0x08);//关显示
- Delay1ms(5);
- wcomd(0x0c);//开显示,不开光标
- }
- /***********显示函数**************/
- void Display(void) //显示函数
- {
- unsigned char i,j;
- unsigned char a[12]={0X4D,0X45,0X41,0X53,0X55,0X52,0X45,0X4D,0X45,0X4E,0X54,0X53};//显示measurements
- LCDINIT();
- for(i=0;i<12;i++)//写显示第一行
- { wcomd(0x80+i);
- Delay1ms(1);
- wdata(a[i]);
- Delay1ms(1);
- }
- for(j=0;j<6;j++)//写显示第二行
- {
- wcomd(0xc0+j);
- Delay1ms(1);
- wdata(0x30+b[j]);
- Delay1ms(1);
- }
- Delay1ms(150);
- }
- void main()
- {
- IE=0x81; //打开全部的中断控制,并开启外部中断允许
- TMOD=0x09; //T0为16位计数工作方式1
- IT0=1; //设置外部中断的触发的方式为脉冲触发
- TH0=0x00;
- TL0=0x00;
- T_flag=0;
- _reset=0;
- while(1)
- {
- while(!b_test) //如果有测量按键输入就往下执行
- {
- i=0;
- _reset=1; //启动555时基芯片
- EX0=1; //开启中断0
- while(_reset) //超出等待时间,中断还没有过来,就退出
- {
- i++;
- if(i>5000) //设置最长等待时间
- {
- _reset=0; //最长等待时间到还没有中断,停止555
- }
- }
- if(N<100) //如果计数值小于100,显示SM,表示应换用小一点的量程
- {
- b[3]=0X1D;
- b[2]=0X23;
- }
- if(N>5000) //如果计数值大于5000,显示LA,表示应换用大一点的量程
- {
- b[3]=0X11;
- b[2]=0X1C;
- }
- if(N>=100 && N<=5000)
- {
- C=N/100; //计算电容的大小
- b[2]=C/10; //计算电容值的十位
- b[3]=C-b[2]*10; //计算电容值的各位
- }
- }
- Display(); //显示电容的大小
- }
- }
- void int0(void) interrupt 0 //第一次中断开始计数,第二个中断停止计数
- {
- T_flag=!T_flag;
- if(T_flag==1)
- {
- TR0=1; //开始计时
- }
- if(T_flag==0)
- {
- TR0=0; //停止计时
- EX0=0; //关闭中断
- _reset=0; //停止发出方波
- N=TH0*256+TL0; //计算计数器的值
- N=N*5/3;
- TH0=0x00; //恢复初值
- TL0=0x00;
- }
- }
复制代码
|