基于51单片机的数字电容容值测量仪proteus仿真原理图PCB

功能介绍:
0.本系统采用STC89C52作为单片机
1.系统支持15pF~450uF电容测量
2.按键可更改测量量程
3.除了采用LCD1602可以实时显示测量参数,同时具有LED可以显示各个档位
4.该方案电容容值测量原理是基于NE555振荡电路来设计的

原理图:
在这里插入图片描述
在这里插入图片描述

PCB:
在这里插入图片描述

主程序:

#include <reg52.h>
#include "lcd1602.h"
#include "delay.h"

sbit VO = P3^2; // 用于检测P3.2口的值,计算时间。  计时器0的开与断
sbit TR = P3^7; // 产生一个低电平脉冲
                  // 超量程提示灯
sbit BUZZER = P2^0;

sbit RELAY1 = P1^5; // 用于控制继电器,实现档位选择
sbit RELAY2 = P1^6;
sbit RELAY3 = P1^7;

sbit KEY1 = P3^4; // 独立按键部分,用于用户选择量程

sbit LED1 = P2^1; // 量程提示灯
sbit LED2 = P2^2;
sbit LED3 = P2^3;
sbit LED4 = P2^4;

unsigned int tw = 0; // 用于获取定时器的数值

float ftemp = 0; // 用于计算电容值的中间变量

unsigned long int c = 0; // 存放电容值

bit measureFlag = 0;                        // 需要测量时置1,一次测量结束置0
unsigned char R = 1;                        // 表示不同的档位
unsigned char finishFlag = 0;                   // 数据处理结束置1
unsigned char temp[8];                      // 存放电容值的各个位

void Timer0_Init(); // 定时器0  初始化
void Ext1_Init(); // 外部中断1  初始化
void Process(unsigned long int c); // 数据处理函数
void Key_Scan();                   // 键盘扫描函数
void Mode_Select(unsigned char R);   //	量程指示灯函数
void Disp(unsigned char *p);


void main()
{
    BUZZER = 1;      // 超量程蜂鸣器关闭
    TR = 1;
    measureFlag = 0; // 一开始无需测量
    finishFlag = 0;

    Timer0_Init(); // 初始化
    Ext1_Init();
    LCD_Init();
    LCD_DispStr(0, 0, "please press key");
    LCD_DispStr(0, 1, "     to measure ");
    Mode_Select(R);
    while (1)
    {
        if (measureFlag == 1)
        {                // 当需要测量时
            if (VO == 0) // VO == 0时检测计数器的值可能还没开始计数,可能计数结束
            {
                if (TH0 != 0x00 || TL0 != 0x00) // 是计数结束 若有读数,用tw 存下
                {
                    tw = TH0 << 8;
                    tw = tw | TL0;
                    TH0 = 0x00; // 一次结束,计时器清零
                    TL0 = 0x00;
                    measureFlag = 0; // 需要再次测量时,measureFlag置1.避免tw的值被更//改   即不需要测量时,一直保持
                    EX1 = 1;         // 开外部中断1
                }
                else // 反之,证明没有计数,无电容,默认值tw置0
                {
                    tw = 0;
                }
            }

            ftemp = tw / 1.0; // 计算电容值   根据公式 tw = 1.0 * R * C

            c = (unsigned long int)(ftemp)*100; //扩大了一百倍   便于后续程序
                                                //取两位小数点
            Process(c);                         // 调用数据处理函数,根据不同的R值进行处理
        }
        DelayMs(10);
        if (finishFlag == 1) // 数据处理结束   每次处理结束,证明需要更新显示的数据
        {
            
            if (tw >= 50000 || BUZZER == 0) // 量程超出
            {
                LCD_DispStr(0, 0, " range is higher");
                LCD_DispStr(0, 1, "                ");
                BUZZER = 0;
            }
            else if (tw <= 100 && BUZZER == 1) //量程太低
            {
                LCD_DispStr(0, 0, " range is lower ");
                LCD_DispStr(0, 1, "                ");
                BUZZER = 0;
            }
            else
            {
                LCD_DispStr(0, 0, "The value of Cap");
                Disp(temp);
            }
            finishFlag = 0;
        }
        
        Key_Scan();
    }
}

void Timer0_Init() // 定时器0  初始化
{
    TMOD = 0x09; // gate置1,方式1,16位计时,定时器由P3.2控制开断
    TH0 = 0x00;
    TL0 = 0x00;
    EA = 1;
    ET0 = 1;
    TR0 = 1;
}

void Ext1_Init() // 外部中断1  初始化
{
    EA = 1;
    IT1 = 1; // 下降沿触发
    EX1 = 1;
}

void Timer0_Interrupt() interrupt 1 // 定时器0中断  用于超量程提示
{
    BUZZER = 0;
}

void Ext1_Interrupt() interrupt 2 // 外部中断1  启动测量按键按下,用于产生低脉冲,启动555定时器
{
    unsigned char a;
    TR = 1; // tr端一个负脉冲
    a = 1;
    while (--a)
        ;
    TR = 0;
    a = 20;
    while (--a)
        ;
    TR = 1;          // tr端负脉冲结束	   大约40us的负脉冲
    measureFlag = 1; // 表示需要测量
    BUZZER = 1;      // 关闭先前的超量程提示
    EX1 = 0;         // 暂时关闭外部中断,一次测量结束,再开放外部中断
}

void Disp(unsigned char *p) // 显示数据
{
	unsigned char i;
	LCD_LocateXY(3, 1);
	for (i = 0; i < 6; i++)
	{
		if (4 == i)
		{
			LCD_WriteData(0x2e);
		}
		LCD_WriteData('0' + (*p));
		p++;
	}
}

void Process(unsigned long int c)
{
    if (R == 1) // 10M	 的电阻		   量程10pf ~ 5000pf
    {
        c = c / 10;
        LCD_LocateXY(10, 1);
        LCD_WriteData(' ');
        LCD_WriteData('p');
        LCD_WriteData('f');
        LCD_WriteData(' ');
        LCD_WriteData(' ');
    }
    if (R == 2) // 100k 的电阻	       量程5nf~ 500nf
    {
        c = c / 100;
        LCD_LocateXY(10, 1);
        LCD_WriteData(' ');
        LCD_WriteData('n');
        LCD_WriteData('f');
        LCD_WriteData(' ');
        LCD_WriteData(' ');
    }
    if (R == 3) // 1k欧姆 的电阻		   量程0.5uf ~ 50uf
    {
        c = c / 1000; // 扩大了一百倍 单位  c = tw/500   uf
        LCD_LocateXY(10, 1);
        LCD_WriteData(' ');
        LCD_WriteData('u');
        LCD_WriteData('f');
        LCD_WriteData(' ');
        LCD_WriteData(' ');
    }
    if (R == 4) // 100欧姆 的电阻		   量程50uf ~ 500uf
    {
        c = c / 100; // 扩大了一百倍 单位  c = tw/500   uf
        LCD_LocateXY(10, 1);
        LCD_WriteData(' ');
        LCD_WriteData('u');
        LCD_WriteData('f');
        LCD_WriteData(' ');
        LCD_WriteData(' ');
    }
    temp[0] = c / 100000;     // 千位
    temp[1] = c / 10000 % 10; // 百位
    temp[2] = c / 1000 % 10;  // 十位
    temp[3] = c / 100 % 10;   // 个位
    temp[4] = c / 10 % 10;
    temp[5] = c % 10;
    finishFlag = 1;
}
void Key_Scan()
{
    if (KEY1 == 0)
    {
        DelayMs(10);
        if (KEY1 == 0) //  b3按下
        {
            while (KEY1 == 0)
                ;

            if (R == 4)
            {
                R = 0;
            }
            R++;
            Mode_Select(R);

            BUZZER = 1;
            LCD_DispStr(0, 0, "please press key");
            LCD_DispStr(0, 1, "     to measure ");
        }
    }
}
void Mode_Select(unsigned char R)
{
    if (1 == R)
    {
        LED1 = 1;
        LED2 = 1;
        LED3 = 1;
        LED4 = 0;
        RELAY1 = 0;
        RELAY2 = 0;
        RELAY3 = 0;
    }
    if (2 == R)
    {
        LED1 = 1;
        LED2 = 1;
        LED3 = 0;
        LED4 = 1;
        RELAY1 = 1;
        RELAY2 = 1;
        RELAY3 = 0;
    }
    if (3 == R)
    {
        LED1 = 1;
        LED2 = 0;
        LED3 = 1;
        LED4 = 1;
        RELAY1 = 0;
        RELAY2 = 0;
        RELAY3 = 1;
    }
    if (4 == R)
    {
        LED1 = 0;
        LED2 = 1;
        LED3 = 1;
        LED4 = 1;
        RELAY1 = 0;
        RELAY2 = 1;
        RELAY3 = 1;
    }
}

仿真演示视频:
https://www.bilibili.com/video/BV1jd4y1M7Dy/

实物演示视频:
https://www.bilibili.com/video/BV1fP41137BD/

  • 6
    点赞
  • 51
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值