單片機開發中應用NTC
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];
}
}