功能介绍:
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.toymoban.com/news/detail-662584.html
实物演示视频:
https://www.bilibili.com/video/BV1fP41137BD/文章来源地址https://www.toymoban.com/news/detail-662584.html
到了这里,关于基于51单片机的数字电容容值测量仪proteus仿真原理图PCB的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!