?? 87c752.c
字號:
#include <reg752.h>
#include <stdio.h>
/**************************** 定義符號常數(shù) *******************************/
#define ZERO_K 2730 /* 0 攝氏度, 1/10 kelvin */
#define ONE_TENTH_CFM 4444444L /* 1/10 CFM 微秒 */
#define CORRECTION 0x11 /* 時鐘頻率為12MHz時計算CFM校正值 */
#define STD_TEMP 2980 /* 25 攝氏度, 1/10 kelvin */
#define STD_ATM 147 /* 一個大氣壓 1/10 PSI */
#define LOWEST_CFM 0x40 /* 轉(zhuǎn)速表的最大周期值 0x400000 */
#define START_ADC0 0x28 /* 各個通道A/D轉(zhuǎn)換啟動命令 */
#define START_ADC1 0x29
#define START_ADC2 0x2a
#define START_ADC3 0x2b
#define START_ADC4 0x2c
#define ADCI 0x10 /* A/D 轉(zhuǎn)換狀態(tài)標(biāo)志 */
#define ADCS 0x08
#define FREERUN_I 0x10
#define SEG_A 0x01 /* 七段LED中的 'a' 段 */
#define CFM 0x01 /* CFM LED */
#define SEG_B 0x02 /* 七段LED中的 'b' 段 */
#define DEGREES 0x02 /* DEGREES LED */
#define SEG_C 0x04 /* 七段LED中的 'c' 段 */
#define PSI 0x04 /* PSI LED */
#define SEG_D 0x08 /* 七段LED中的 'd' 段 */
#define SETPOINT 0x08 /* SETPOINT LED */
#define SEG_E 0x10 /* 七段LED中的 'e' 段 */
#define SEG_F 0x20 /* 七段LED中的 'f' 段 */
#define SEG_G 0x40 /* 七段LED中的 'g' 段 */
#define SEG_DP 0x80 /* 七段LED中的 'dp'段 */
typedef unsigned char byte; /* 8位無符號字節(jié)型數(shù)據(jù) */
typedef unsigned int word; /* 16位無符號字型數(shù)據(jù) */
typedef unsigned long I_word; /* 32位無符號長字型數(shù)據(jù) */
#define TRUE 1
#define FALSE 0
/********************** 定義七段LED的顯示段碼表 ***************************/
code byte segments []=
{
SEG_A | SEG_B | SEG_C | SEG_D | SEG_E | SEG_F , /* 0 */
SEG_B | SEG_C , /* 1 */
SEG_A | SEG_B | SEG_D | SEG_E , /* 2 */
SEG_A | SEG_B | SEG_C | SEG_D | SEG_G , /* 3 */
SEG_B | SEG_C | SEG_F | SEG_G , /* 4 */
SEG_A | SEG_C | SEG_D | SEG_F | SEG_G , /* 5 */
SEG_A | SEG_C | SEG_D | SEG_E | SEG_F | SEG_G , /* 6 */
SEG_A | SEG_B | SEG_C , /* 7 */
SEG_A | SEG_B | SEG_C | SEG_D | SEG_E | SEG_F | SEG_G , /* 8 */
SEG_A | SEG_B | SEG_C | SEG_D | SEG_F | SEG_G , /* 9 */
SEG_A | SEG_D | SEG_E | SEG_F | SEG_G , /* E */
};
/******************* 定義87C752中用于I/O線的特殊功能位 *******************/
sfr PWMP = 0x8F; /* 定義87C752的PWM預(yù)分頻寄存器 */
sbit RELAY = 0x96; /* 為高時閉合SETPOIN 繼電器 */
sbit STROBE_0 = 0x80; /* 為高時允許點(diǎn)亮各個狀態(tài)LED */
sbit STROBE_1 = 0x81; /* 為高時允許點(diǎn)亮cr15 (十分之一位) */
sbit STROBE_2 = 0x82; /* 為高時允許點(diǎn)亮cr14 (個位) */
sbit NO_FLOW = 0x83; /* 未檢測到氣流量時的標(biāo)志位 */
sbit STROBE_3 = 0x84; /* 為高時允許點(diǎn)亮cr13 (十位) */
sbit SEL_0 = 0x93; /* 為低時用于按鍵輸入, 選擇顯示模式 */
sbit SEL_1 = 0x94;
sbit INTR = 0x95;
sbit UPDATE = 0x97; /* 顯示更新標(biāo)志 */
/***************************** 定義內(nèi)存變量 ******************************/
data word cfm; /* 十分之一氣流量 CFM */
data word setpoint; /* 十分之一氣流量 CFM 的繼電器設(shè)定值 */
data word degree_c; /* 十分之一攝氏度 */
data I_word corr; /* 計算值 */
data word psi; /* 十分之一 PSI */
data byte display0; /* 顯示更新值 */
data byte display1; /* display0=status LEDs, display1=cr15,*/
data byte display2; /* display2=cr14, display3=cr13,*/
data byte display3;
data byte disp_pntr; /* 下一個要點(diǎn)亮的LED指針 */
data byte refresh; /* 顯示更新計數(shù) */
data byte high; /* 24位計數(shù)器的第16 - 23位 */
data byte middle; /* 24位計數(shù)器的第 8 - 15位 */
data byte low; /* 24位計數(shù)器的第 0 - 7 位 */
data byte ticks; /* 定時器溢出加一計數(shù) */
/**************************************************************************
* 函數(shù)原型 : void multiplex() interrupt 3;
* 功 能 : 利用自由運(yùn)行的定時器T1對顯示器進(jìn)行動態(tài)更新, 更新速度
* 約為1000Hz。
**************************************************************************/
void multiplex() interrupt 3 {
switch(disp_pntr) {
case 0x00:
STROBE_3 = FALSE; /* 關(guān)閉cr13 */
P3 = 0xff; /* 關(guān)閉七段LED */
P3 = display0; /* 裝入段碼 */
STROBE_0 = TRUE; /* 點(diǎn)亮狀態(tài) LEDs */
disp_pntr = 1; /* 指向下一個顯示器 */
break;
case 0x01:
STROBE_0 = FALSE; /* 關(guān)閉狀態(tài) LEDs */
P3 = 0xff; /* 關(guān)閉七段 LED */
P3 = display1; /* 裝入十分之一位LED段碼 */
STROBE_1 = TRUE; /* 點(diǎn)亮cr15 */
disp_pntr = 2; /* 指向下一個顯示器 */
break;
case 0x02:
STROBE_1 = FALSE; /* 關(guān)閉cr15 */
P3 = 0xff; /* 關(guān)閉七段 LED */
P3 = display2; /* 裝入個位LED段碼 */
STROBE_2 = TRUE; /* 點(diǎn)亮cr14 */
disp_pntr = 3; /* 指向下一個顯示器 */
break;
case 0x03:
STROBE_2 = FALSE; /* 關(guān)閉cr14 */
P3 = 0xff; /* 關(guān)閉七段 LED */
P3 = display3; /* 裝入十位LED段碼 */
STROBE_3 = TRUE; /* 點(diǎn)亮cr13*/
disp_pntr = 0; /* 指向下一個顯示器 */
}
}
/**************************************************************************
* 函數(shù)原型 : void read_switch() interrupt 6;
* 功 能 : 利用自由運(yùn)行的PWM預(yù)分頻器產(chǎn)生92Hz周期的中斷。每中斷
* 32次將UPDATE標(biāo)志置位, main()函數(shù)將根據(jù)該標(biāo)志位的狀
* 態(tài)來采樣按鍵并進(jìn)行顯示更新。
**************************************************************************/
void read_switch() interrupt 6 {
if (refresh++ == 32) {
UPDATE = TRUE;
refresh = 0;
}
}
/**************************************************************************
* 函數(shù)原型 : void overflow() interrupt 1;
* 功 能 : 每當(dāng)定時器T1溢出(從0xffff到0x0000)時將變量'ticks'的
* 值加1, 該值表示24位氣流量周期微秒計數(shù)器的高8位(16~
* 23位)。如果'ticks'的值太大則將NO_FLOW標(biāo)志置位, 從而
* 使main()函數(shù)在LED上顯示00.0。
**************************************************************************/
void overflow() interrupt 1 {
if (++ticks > LOWEST_CFM) {
cfm = 0;
ticks = 0;
NO_FLOW = TRUE;
}
}
/**************************************************************************
* 函數(shù)原型 : void cal_cfm() interrupt 0;
* 功 能 : 由轉(zhuǎn)速計脈沖產(chǎn)生的外部中斷(INT0)將定時器T0的當(dāng)前計
* 數(shù)值送到24位微秒計數(shù)器的'low'(低8位)和'middle'(中
* 8位), 同時復(fù)位定時器T0。將前面的'ticks'值拷貝到
* 'high'中同時使'ticks'復(fù)位為0。清除NO_FLOW標(biāo)志, 從而
* 使main()函數(shù)能在LED上顯示計算出的cfm值。
**************************************************************************/
void cal_cfm() interrupt 0 {
low = TL;
TL = 0;
middle = TH;
TH = 0;
high = ticks;
ticks = 0;
NO_FLOW = FALSE;
}
/**************************************************************************
* 函數(shù)原型 : void main();
* 功 能 : 在完成各個I/O引腳和變量的初始化之后進(jìn)入一個連續(xù)循
* 環(huán)并完成以下任務(wù):
* -根據(jù)轉(zhuǎn)速計脈沖、輸入的溫度值和壓力值計算氣流量;
* -將氣流量與設(shè)定輸入值進(jìn)行比較, 并控制繼電器的開、閉;
* -在UPDATE標(biāo)志置位時采樣按鍵狀態(tài)并進(jìn)行顯示更新。
**************************************************************************/
void main() {
RELAY = 0; /* 初始化輸出引腳 */
INTR = 1;
UPDATE = 1;
STROBE_0 = 0;
STROBE_1 = 0;
STROBE_2 = 0;
STROBE_3 = 0;
NO_FLOW = 0;
I2CFG = FREERUN_I; /* 不使用I2C, 定時器T1自由運(yùn)行 */
RTL = 0; /* 定時器T0裝入初值, 定時時間為0x10000 微秒 */
RTH = 0;
PWMP = 255; /* PWM 中斷周期約為 93 Hz */
TR = 1; /* 啟動定時器T0 */
IT0 = 1; /* 外部中斷INT0 為邊沿觸發(fā) */
ticks = 0; /* 變量初始化 */
cfm = 0;
low = 0 ;
middle = 0;
high = 0;
degree_c = 250;
psi = 147;
corr = 0;
refresh = 0;
disp_pntr = 0;
IE = 0xab; /* 開中斷 */
/* 進(jìn)入連續(xù)循環(huán) */
while(1) {
/* 計算氣流量CFM */
corr = high * 0x10000L;
corr += (middle * 0x100L);
corr = low;
corr -= CORRECTION;
corr = ONE_TENTH_CFM / corr;
/* 讀取溫度測量值 */
ADCON = START_ADC1;
while (ADCON & ADCS);
degree_c = ADAT;
degree_c *= 2;
/* 對CFM進(jìn)行溫度補(bǔ)償 */
corr *= STD_TEMP;
corr /= (ZERO_K + degree_c);
/* 讀取壓力測量值 */
ADCON = START_ADC0;
while (ADCON & ADCS);
psi = ADAT;
/* 對CFM進(jìn)行壓力補(bǔ)償 */
corr *= psi;
corr /= STD_ATM;
cfm = corr;
/* 讀取氣流量設(shè)定值 */
ADCON = START_ADC2;
while (ADCON & ADCS);
setpoint = ADAT;
/* 測試CFM速率是否大于或等于設(shè)定值, 若是則觸發(fā)控制繼電器 */
if (setpoint > cfm)
RELAY = 0;
else
RELAY = 1;
/* 測試UPDATE標(biāo)志是否置位, 若是則將其復(fù)位 */
if (UPDATE) {
UPDATE = 0;
/* 測試NO_FLOW標(biāo)志是否置位, 若是則顯示'00.0' */
if (NO_FLOW) {
display0 = ~CFM;
display1 = ~segments[0];
display2 = ~(segments[0] | SEG_DP);
display3 = ~segments[0];
}
/* 若NO_FLOW標(biāo)志未置位, 采樣按鍵并顯示合適的數(shù)據(jù) */
else if (SEL_0) {
if (SEL_1) {
/* 無鍵按下時則顯示氣流量值。若氣流量值大于或等于30cfm則顯示過
載信息'EEE', 否則以'××.×'格式顯示氣流量值 */
if (cfm <= 300) {
display0 = ~CFM;
display1 = ~segments[cfm % 10];
cfm /= 10;
display2 = ~(segments[cfm % 10]);
cfm /= 10;
display3 = ~segments[cfm % 10];
}
else {
display0 = ~CFM;
display1 = ~segments[10];
display2 = ~segments[10];
display3 = ~segments[10];
}
}
/* 若溫度鍵(SW1)按下則顯示氣體溫度測量值 */
else {
display0 = ~DEGREES;
display1 = ~segments[degree_c % 10];
degree_c /= 10;
display2 = ~(segments[degree_c % 10] | SEG_DP);
degree_c /= 10;
display3 = ~segments[degree_c % 10];
}
}
else {
/* 若PSI鍵(SW2)按下則顯示氣體壓力測量值 */
if (SEL_1) {
display0 = ~PSI;
display1 = ~segments[psi % 10];
psi /= 10;
display2 = ~(segments[psi %10] | SEG_DP);
psi /= 10;
display3 = ~segments[psi % 10];
}
/* 若設(shè)定值鍵(SW3)按下則顯示設(shè)定值 */
else {
display0 = ~SETPOINT;
display1 = ~segments[setpoint % 10];
setpoint /= 10;
display2 = ~(segments[setpoint % 10] | SEG_DP);
setpoint /= 10;
display3 = ~segments[setpoint % 10];
}
}
}
}
}
?? 快捷鍵說明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -