仿真原理图如下(proteus仿真工程文件可到本帖附件中下载)
单片机源程序如下:
- #include <reg51.h>
- sbit nF_check = P1^0; //测量电容(nF)
- sbit uF_check = P1^1; //测量电容(uF)
- sbit stop = P1^2; //停止测量按钮
- sbit P20 = P2^0; //百位控制
- sbit P21 = P2^1; //十位控制
- sbit P22 = P2^2; //个位及小数点控制
- sbit P23 = P2^3; //十分位控制
- sbit P24 = P2^4; //“n”或“u”显示控制
- sbit P25 = P2^5; //“F”显示控制
- sbit P26 = P2^6; //
- sbit P27 = P2^7; //
- sbit P30 = P3^0; //电阻电容测量继电器
- sbit P31 = P3^1; //
- sbit P32 = P3^2; //计时停止请求(中断0)
- sbit P33 = P3^3; //计时开始请求(中断1)及测量开始开关
- sbit P34 = P3^4;
- sbit P35 = P3^5;
- sbit P36 = P3^6;
- sbit P37 = P3^7;
- char code word[] = {0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,
- 0x7F,0x6F,0x37,0x3E,0x71,0x80};
- //'0'~'9'和n、u、F及小数点.等字形码
- long int N=0; //计数变量
- /********************************************************************
- 函数功能:延时函数
- 入口参数: us
- 出口参数:
- ********************************************************************/
- void delay(us)
- {
- while(us--);
- }
- /********************************************************************
- 函数功能:中断初始化
- 入口参数:
- 出口参数:
- ********************************************************************/
- void INT0_init()
- {
- IE = 0x87; //打开总中断及外部中断0、1,定时器中断0
- IT0 = 1; //下降沿触发
- IT1 = 1;
- }
- /********************************************************************
- 函数功能:外部中断0处理
- 入口参数:
- 出口参数:
- ********************************************************************/
- void INT0_pro(void) interrupt 0 //外部中断0
- {
- TR0 = 0; //T0停止计时
- }
- /********************************************************************
- 函数功能:外部中断1处理
- 入口参数:
- 出口参数:
- ********************************************************************/
- void INT1_pro(void) interrupt 2 //外部中断1
- {
- TR0 = 1; //T0开始计时
- }
- /********************************************************************
- 函数功能:定时器0初始化
- 入口参数:
- 出口参数:
- ********************************************************************/
- void Timer_init() {
-
- TMOD = 0x02; //定时器0工作于方式2(8位自动重装定时器)
- TH0 = 256-100; //定时器0设定时间为100us(假设晶振为12MHz,
- TL0 = 256-100; //则时钟周期为1/12us,机器周期为1us),频率为10kHz。
- }
- /********************************************************************
- 函数功能:定时器0中断处理(时基)
- 入口参数:
- 出口参数:
- ********************************************************************/
- void _Timer_clock(void) interrupt 1 //定时器0(溢出)中断,中断1
- {
- N++;
- }
- /********************************************************************
- 函数功能:数据显示函数
- 入口参数: CV
- 出口参数:
- ********************************************************************/
- void CV_disp(long int CV)
- {
- //数码管位选方式--灌电流//
- P2=0xff;
- P0=word[CV/1000]; P20=0; delay(60); //千位
- P2=0xff;
- P0=word[(CV/100)%10]; P21=0; delay(60); //百位
- P2=0xff;
- P0=word[(CV/10)%10]; P22=0; delay(60); //十位
- P2=0xff;
- P0=word[CV%10]; P23=0; delay(60); //个位
-
- }
- /********************************************************************
- 函数功能:主函数
- 入口参数:
- 出口参数:
- ********************************************************************/
- void main()
- {
- long int C=0;
- INT0_init();
- Timer_init();
- while(1){
-
- //数码管位选方式--灌电流//
- while(!nF_check) { //测量电容(nF)
- P30=1;
- if(TR0 && !P33) C=N*610/1000;//取R=10M,C为nF级,则时间常数t=RC=(10*10^6)*(C*10^-9)=C*10^-2;
- //若在t期间对已知脉冲进行计数,且选脉冲频率f=10k=10^4,
- else N=0; //则计数值N=f*t=100C(nF),所以C=N/100。
- //C=N*610/1000是算法修正
- P2=0xff;
- P0=word[10]; P24=0; delay(60); //第5位显示n
- P2=0xff;
- P0=word[12]; P25=0; delay(60); //第6位显示F
- P2=0xff;
- P0=word[13]; P22=0; delay(60); //第3位显示小数点
- CV_disp(C); //显示测量值
- if(!stop) TR0=0;
- }
-
- while(!uF_check) { //测量电容(uF)
- P30=0;
- if(TR0 && !P33) C=N*160/10000;//取R=100k,C为uF级,则时间常数t=RC=(100*10^3)*(C*10^-6)=C*10^-1;
- //若在t期间对已知脉冲进行计数,且选脉冲频率f=10k=10^4,
- else N=0; //则计数值N=f*t=1000C(uF),于是应有C=N/1000。
- //C=N*160/10000是为消除误差所进行的补偿运算
- P2=0xff;
- P0=word[11]; P24=0; delay(60); //第5位显示u
- P2=0xff;
- P0=word[12]; P25=0; delay(60); //第6位显示F
- P2=0xff;
- P0=word[13]; P22=0; delay(60); //第3位显示小数点
- CV_disp(C); //显示测量值
- if(!stop) TR0=0;
- }
- }
- }
复制代码
所有资料51hei附件下载:
电容测量.7z
(113.41 KB, 下载次数: 98)
|