功能介紹:
0.本系統(tǒng)采用STC89C52作為單片機
1.系統(tǒng)支持15pF~450uF電容測量
2.按鍵可更改測量量程
3.除了采用LCD1602可以實時顯示測量參數(shù),同時具有LED可以顯示各個檔位
4.該方案電容容值測量原理是基于NE555振蕩電路來設計的
原理圖:
PCB:
主程序:
#include <reg52.h>
#include "lcd1602.h"
#include "delay.h"
sbit VO = P3^2; // 用于檢測P3.2口的值,計算時間。 計時器0的開與斷
sbit TR = P3^7; // 產(chǎn)生一個低電平脈沖
// 超量程提示燈
sbit BUZZER = P2^0;
sbit RELAY1 = P1^5; // 用于控制繼電器,實現(xiàn)檔位選擇
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; // 用于獲取定時器的數(shù)值
float ftemp = 0; // 用于計算電容值的中間變量
unsigned long int c = 0; // 存放電容值
bit measureFlag = 0; // 需要測量時置1,一次測量結(jié)束置0
unsigned char R = 1; // 表示不同的檔位
unsigned char finishFlag = 0; // 數(shù)據(jù)處理結(jié)束置1
unsigned char temp[8]; // 存放電容值的各個位
void Timer0_Init(); // 定時器0 初始化
void Ext1_Init(); // 外部中斷1 初始化
void Process(unsigned long int c); // 數(shù)據(jù)處理函數(shù)
void Key_Scan(); // 鍵盤掃描函數(shù)
void Mode_Select(unsigned char R); // 量程指示燈函數(shù)
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時檢測計數(shù)器的值可能還沒開始計數(shù),可能計數(shù)結(jié)束
{
if (TH0 != 0x00 || TL0 != 0x00) // 是計數(shù)結(jié)束 若有讀數(shù),用tw 存下
{
tw = TH0 << 8;
tw = tw | TL0;
TH0 = 0x00; // 一次結(jié)束,計時器清零
TL0 = 0x00;
measureFlag = 0; // 需要再次測量時,measureFlag置1.避免tw的值被更//改 即不需要測量時,一直保持
EX1 = 1; // 開外部中斷1
}
else // 反之,證明沒有計數(shù),無電容,默認值tw置0
{
tw = 0;
}
}
ftemp = tw / 1.0; // 計算電容值 根據(jù)公式 tw = 1.0 * R * C
c = (unsigned long int)(ftemp)*100; //擴大了一百倍 便于后續(xù)程序
//取兩位小數(shù)點
Process(c); // 調(diào)用數(shù)據(jù)處理函數(shù),根據(jù)不同的R值進行處理
}
DelayMs(10);
if (finishFlag == 1) // 數(shù)據(jù)處理結(jié)束 每次處理結(jié)束,證明需要更新顯示的數(shù)據(jù)
{
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; // 下降沿觸發(fā)
EX1 = 1;
}
void Timer0_Interrupt() interrupt 1 // 定時器0中斷 用于超量程提示
{
BUZZER = 0;
}
void Ext1_Interrupt() interrupt 2 // 外部中斷1 啟動測量按鍵按下,用于產(chǎn)生低脈沖,啟動555定時器
{
unsigned char a;
TR = 1; // tr端一個負脈沖
a = 1;
while (--a)
;
TR = 0;
a = 20;
while (--a)
;
TR = 1; // tr端負脈沖結(jié)束 大約40us的負脈沖
measureFlag = 1; // 表示需要測量
BUZZER = 1; // 關閉先前的超量程提示
EX1 = 0; // 暫時關閉外部中斷,一次測量結(jié)束,再開放外部中斷
}
void Disp(unsigned char *p) // 顯示數(shù)據(jù)
{
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/文章來源:http://www.zghlxwxcb.cn/news/detail-662584.html
實物演示視頻:
https://www.bilibili.com/video/BV1fP41137BD/文章來源地址http://www.zghlxwxcb.cn/news/detail-662584.html
到了這里,關于基于51單片機的數(shù)字電容容值測量儀proteus仿真原理圖PCB的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關文章,希望大家以后多多支持TOY模板網(wǎng)!