1、功能:实现温度的测量,温度达到或超过设定温度时,蜂鸣器发出报警声 。2、性能指标:温度范围:-40℃~300℃,分辨率 0.1℃,温度误差≤±2℃,转换时间:100ms
在上电之后,STC89C52 单片机进行相关的初始化,并启动 ADC,初始化完毕之后,进入 while 循环并不断通过串行口的移位寄存器功能扫描数码管,实时显示所控温度值和当前温度值,当达到所控温度时,蜂鸣器发出报警。
温度测量:当启动 ADC 之后,每间隔 100ms 进行一次测量,ADC 测量完毕之后产生一个下降沿触发,单片机的外部中断口检测到外部中断后立即通过一根时钟线和一根数据线完成 ADC 数据的读取,并计算出温敏电阻的压降和电流,根据欧姆定律再计算出温敏电阻的阻值,再通过该温敏电阻的温度计算公式计算出当前的温度,并更新温度值,更新报警标志。
键盘检测:按键的功能是增减所控温度,键盘检测由或非门和外部中断组成,当按下按键时产生一个下降沿,触发外部中断进入键盘处理函数,根据所按下的键位来确定温度的增减,与此同时启动定时器,检测按键是否处于长按状态,如果是则每隔一定时间增减一定的温度值。
仿真原理图如下
Altium Designer画的原理图和PCB图如下:
单片机程序:
#include
#include
#include
typedef unsigned int u16;
typedef unsigned char u8;
typedef char int8;
#define ENABLE 1
#define DISABLE 0
//-------------pin-define---------------
sbit STORE = P2 ^ 0;
sbit OE = P2 ^ 1;
sbit MR = P2 ^ 2;
sbit TRIG_DB = P3 ^ 3;
sbit PD_SCK = P3 ^ 4;
sbit ADC_CTRL = P3 ^ 5;
sbit DAT = P1 ^ 3;
sbit BUZZER = P2 ^ 4;
#define KEYBOARD P1
//-------------------------------------
#define ALARM_INIT_VALUE 25.0f
#define TABLE_SIZE 17
#define SYMBOL_NEGATIVE 16
#define POINT_MASK 0x7F //&
u8 segTable[TABLE_SIZE] = {0xc0, 0xf9, 0xa4, 0xb0, 0x99, 0x92, 0x82, 0xf8, 0x80, 0x90, 0x88, 0x83, 0xc6, 0xa1, 0x86, 0x8e, 0xbf};
u8 dispVal[8];
u8 t0_loopCount;
float alarmVal, currentVal;
//-------------------------
#define Delay10Us()
_nop_(), _nop_(), _nop_(), _nop_(), _nop_();
_nop_(), _nop_(), _nop_(), _nop_(), _nop_();
#define Delay50Us()
Delay10Us();
Delay10Us();
Delay10Us();
Delay10Us();
Delay10Us()
#define UpdateAlarmVal() UpdateValue(alarmVal, 0)
#define UpdateCurrentVal() UpdateValue(currentVal, 4)
#define SetOverflow()
dispVal[4] = dispVal[5] = dispVal[6] = dispVal[7] = segTable[SYMBOL_NEGATIVE]
//---------------------
#define BUZZER_CMD(val) BUZZER = (val)
#define SEG_INIT()
SCON = 0x00;
OE = 1
#define SEG_UPDATE(ledx, val)
OE = 1;
P0 = (val);
SBUF = 0x80U >> (ledx);
while (TI == 0)
;
TI = 0;
STORE = 0;
STORE = 1;
OE = 0
#define KEYBOARD_INIT()
KEYBOARD = 0x00;
IT0 = 1;
EX0 = 1
#define KEY_ADD() alarmVal = alarmVal < 300.0f ? (alarmVal + 0.5f) : alarmVal
#define KEY_DEC() alarmVal = alarmVal > -40.0f ? (alarmVal - 0.5f) : alarmVal
#define ADC_INIT()
currentVal = 0.0f;
ADC_CTRL = 1;
TRIG_DB = 1;
DAT = 1;
PD_SCK = 0;
IT1 = 1
#define ADC_IT_CMD(val) EX1 = (val)
#define ADC_START() ADC_CTRL = 0
#define T0_LOOP_MAX 6
#define T0_INIT()
TMOD = 0x01;
TH0 = 0x3C;
TL0 = 0xB0;
ET0 = 1;
t0_loopCount = 0
#define T0_CMD(val) TR0 = (val)
//----------------------
void DisplayAll(void);
void UpdateValue(float v, u8 offset) reentrant;
float ADC_Measure(void);
void Delay(u16 x);
void HandleKey(void) reentrant;
//----------------------
void main()
{
alarmVal = ALARM_INIT_VALUE; //报警值初始化
BUZZER_CMD(DISABLE); // 关闭蜂鸣器
SEG_INIT(); // 初始化串口
T0_INIT(); // 初始化定时器T0, 50ms
KEYBOARD_INIT(); // 初始化键盘,外部中断0,下降沿触发
UpdateAlarmVal(); // 温度报警值初始化
SetOverflow(); // 当前温度值初始化为 “----”
ADC_INIT(); // 初始化ADC的控制引脚
ADC_IT_CMD(ENABLE); // 使能ADC的触发中断(外部中断1)
EA = 1; // 开总中断
Delay(100);
ADC_START(); // 启动ADC
while (1)
{
EA = 0;
DisplayAll(); // 显示所有数码管
EA = 1;
Delay(4);
}
}
void HandleKey(void) reentrant
{
switch (KEYBOARD & 0x03)
{
case 0x01:
KEY_ADD();
UpdateAlarmVal();
T0_CMD(ENABLE);
break;
case 0x02:
KEY_DEC();
UpdateAlarmVal();
T0_CMD(ENABLE);
break;
default:
T0_CMD(DISABLE);
break;
}
}
void Delay(u16 x)
{
u16 i;
while (x--)
for (i = 0; i < 62; i++)
;
}
void DisplayAll()
{
u8 i;
for (i = 0; i < 8; i++)
{
SEG_UPDATE(i, dispVal[i]);
Delay(4);
}
}
void UpdateValue(float v, u8 offset) reentrant
{
u16 val = (v > 0.0f ? v : -v) * 10;
if (v > 0.0f)
{
dispVal[0 + offset] = segTable[val / 1000];
dispVal[1 + offset] = segTable[(val % 1000) / 100];
dispVal[2 + offset] = segTable[(val % 100) / 10] & POINT_MASK;
dispVal[3 + offset] = segTable[val % 10];
}
else
{
dispVal[0 + offset] = segTable[SYMBOL_NEGATIVE];
dispVal[1 + offset] = segTable[val / 100];
dispVal[2 + offset] = segTable[(val % 100) / 10] & POINT_MASK;
dispVal[3 + offset] = segTable[val % 10];
}
}
『本文转载自网络,版权归原作者所有,如有侵权请联系删除』