這個代碼實現了 STC8H8K64U 芯片控制 T12-K 電烙鐵的基本功能,包括:
溫度檢測與顯示(通過 ADC 讀取溫度傳感器,三位數碼管顯示)
溫度調節(通過上下按鍵調整設定溫度)
恒溫控制(采用 PID 算法保持設定溫度)
空閑休眠(5 分鐘無操作自動降低溫度)
代碼使用了定時器 0 來實現數碼管的動態掃描和 PWM 輸出,使用 ADC 通道 0 來讀取溫度傳感器的值。PID 控制參數 (Kp=20, Ki=0.1, Kd=5) 需要根據實際情況調整以獲得最佳的溫度控制效果。
硬件連接方面,代碼假設溫度傳感器連接到 P1.0,加熱器控制連接到 P1.1,三個按鍵分別連接到 P3.2-P3.4,數碼管段選連接到 P2 口,位選連接到 P4.0-P4.2。實際應用中請根據具體電路連接調整引腳定義。
#include <STC8H8K64U.h>
#include <intrins.h>
// 引腳定義
#define TEMP_SENSOR_PIN P1.0 // 溫度傳感器輸入引腳
#define HEATER_PIN P1.1 // 加熱器控制引腳
#define KEY_UP_PIN P3.2 // 溫度上升按鍵
#define KEY_DOWN_PIN P3.3 // 溫度下降按鍵
#define KEY_POWER_PIN P3.4 // 電源/模式切換按鍵
#define LED_A P2.0 // 數碼管段A
#define LED_B P2.1 // 數碼管段B
#define LED_C P2.2 // 數碼管段C
#define LED_D P2.3 // 數碼管段D
#define LED_E P2.4 // 數碼管段E
#define LED_F P2.5 // 數碼管段F
#define LED_G P2.6 // 數碼管段G
#define LED_DP P2.7 // 數碼管小數點
#define DIG1 P4.0 // 數碼管位選1
#define DIG2 P4.1 // 數碼管位選2
#define DIG3 P4.2 // 數碼管位選3
// 全局變量
unsigned int setTemperature = 300; // 默認設定溫度300℃
unsigned int currentTemperature = 0; // 當前溫度
unsigned char displayValue[3] = {0}; // 顯示緩沖區
unsigned char displayIndex = 0; // 當前顯示位
unsigned char workingMode = 0; // 工作模式:0-正常,1-休眠
unsigned int idleTime = 0; // 空閑計時器
unsigned int pwmDuty = 0; // PWM占空比
// 數碼管段碼表(0-9)
code unsigned char segTable[10] = {
0x3F, // 0
0x06, // 1
0x5B, // 2
0x4F, // 3
0x66, // 4
0x6D, // 5
0x7D, // 6
0x07, // 7
0x7F, // 8
0x6F // 9
};
// 函數聲明
void SystemInit();
void Timer0Init();
void ADCInit();
void KeyScan();
void DisplayUpdate();
void DisplayDigit(unsigned char pos, unsigned char num);
unsigned int ReadTemperature();
void PIDControl();
void PWMOutput(unsigned int duty);
void main() {
SystemInit(); // 系統初始化
Timer0Init(); // 定時器0初始化(用于數碼管掃描和PID控制)
ADCInit(); // ADC初始化(用于溫度采集)
EA = 1; // 開總中斷
while(1) {
KeyScan(); // 按鍵掃描
// 空閑計時
if (idleTime < 60000) // 最大計時約10分鐘(60000/1000*100ms)
idleTime++;
// 休眠判斷
if (idleTime >= 30000 && workingMode == 0) { // 5分鐘無操作進入休眠
workingMode = 1;
setTemperature = 200; // 休眠溫度設為200℃
}
// 溫度讀取和控制
currentTemperature = ReadTemperature();
PIDControl();
// 顯示更新
DisplayUpdate();
// 延時
Delay1ms(100); // 100ms循環
}
}
// 系統初始化
void SystemInit() {
// 設置IO口模式
P1M1 = 0x00; P1M0 = 0x02; // P1.0輸入,P1.1推挽輸出
P2M1 = 0x00; P2M0 = 0xFF; // P2口全部推挽輸出(數碼管段選)
P3M1 = 0x00; P3M0 = 0x00; // P3口全部準雙向口(按鍵輸入)
P4M1 = 0x00; P4M0 = 0x07; // P4.0-P4.2推挽輸出(數碼管位選)
// 其他初始化
HEATER_PIN = 0; // 初始關閉加熱器
}
// 定時器0初始化(用于數碼管掃描和PID控制)
void Timer0Init() {
TMOD &= 0xF0; // 清除定時器0模式位
TMOD |= 0x01; // 設置定時器0為模式1(16位定時器)
TH0 = 0xFC; // 設置定時初值
TL0 = 0x66; // 設置定時初值(1ms@11.0592MHz)
ET0 = 1; // 使能定時器0中斷
TR0 = 1; // 啟動定時器0
}
// ADC初始化(用于溫度采集)
void ADCInit() {
ADC_CONTR = 0x80; // 開啟ADC,ADC時鐘為系統時鐘/2
ADC_RES = 0; // 清除ADC結果寄存器
ADC_RESL = 0;
}
// 按鍵掃描
void KeyScan() {
static unsigned char keyUpState = 1;
static unsigned char keyDownState = 1;
static unsigned char keyPowerState = 1;
// 檢測溫度上升按鍵
if (KEY_UP_PIN == 0 && keyUpState == 1) {
Delay1ms(20); // 消抖
if (KEY_UP_PIN == 0) {
if (workingMode == 0) { // 僅在正常模式下可調節溫度
if (setTemperature < 450)
setTemperature += 5;
} else { // 休眠模式下按任意鍵喚醒
workingMode = 0;
setTemperature = 300; // 恢復默認溫度
}
idleTime = 0; // 重置空閑計時
}
while (KEY_UP_PIN == 0); // 等待按鍵釋放
keyUpState = 0;
} else if (KEY_UP_PIN == 1) {
keyUpState = 1;
}
// 檢測溫度下降按鍵
if (KEY_DOWN_PIN == 0 && keyDownState == 1) {
Delay1ms(20); // 消抖
if (KEY_DOWN_PIN == 0) {
if (workingMode == 0) { // 僅在正常模式下可調節溫度
if (setTemperature > 150)
setTemperature -= 5;
} else { // 休眠模式下按任意鍵喚醒
workingMode = 0;
setTemperature = 300; // 恢復默認溫度
}
idleTime = 0; // 重置空閑計時
}
while (KEY_DOWN_PIN == 0); // 等待按鍵釋放
keyDownState = 0;
} else if (KEY_DOWN_PIN == 1) {
keyDownState = 1;
}
// 檢測電源/模式切換按鍵
if (KEY_POWER_PIN == 0 && keyPowerState == 1) {
Delay1ms(20); // 消抖
if (KEY_POWER_PIN == 0) {
workingMode = !workingMode; // 切換工作模式
if (workingMode == 0)
setTemperature = 300; // 恢復默認溫度
idleTime = 0; // 重置空閑計時
}
while (KEY_POWER_PIN == 0); // 等待按鍵釋放
keyPowerState = 0;
} else if (KEY_POWER_PIN == 1) {
keyPowerState = 1;
}
}
// 顯示更新
void DisplayUpdate() {
// 更新顯示緩沖區
displayValue[0] = currentTemperature / 100;
displayValue[1] = (currentTemperature % 100) / 10;
displayValue[2] = currentTemperature % 10;
}
// 數碼管顯示函數
void DisplayDigit(unsigned char pos, unsigned char num) {
// 關閉所有數碼管
DIG1 = 1;
DIG2 = 1;
DIG3 = 1;
// 清除段選
LED_A = 0;
LED_B = 0;
LED_C = 0;
LED_D = 0;
LED_E = 0;
LED_F = 0;
LED_G = 0;
LED_DP = 0;
// 設置位選
switch(pos) {
case 0: DIG1 = 0; break;
case 1: DIG2 = 0; break;
case 2: DIG3 = 0; break;
}
// 設置段選
unsigned char segData = segTable[num];
LED_A = (segData & 0x01) ? 1 : 0;
LED_B = (segData & 0x02) ? 1 : 0;
LED_C = (segData & 0x04) ? 1 : 0;
LED_D = (segData & 0x08) ? 1 : 0;
LED_E = (segData & 0x10) ? 1 : 0;
LED_F = (segData & 0x20) ? 1 : 0;
LED_G = (segData & 0x40) ? 1 : 0;
LED_DP = (segData & 0x80) ? 1 : 0;
}
// 讀取溫度
unsigned int ReadTemperature() {
unsigned int adcValue;
// 選擇ADC通道(P1.0)
ADC_CONTR &= 0xF8;
ADC_CONTR |= 0x00; // 通道0
// 啟動ADC轉換
ADC_CONTR |= 0x40;
_nop_();
_nop_();
// 等待轉換完成
while (!(ADC_CONTR & 0x20));
ADC_CONTR &= ~0x20; // 清除ADC完成標志
// 讀取ADC結果
adcValue = (ADC_RES << 2) | (ADC_RESL & 0x03);
// 簡單線性轉換(實際應用中需要根據溫度傳感器特性校準)
// 假設10位ADC (0-1023)對應0-500℃
return (adcValue * 500) / 1023;
}
// PID控制算法
void PIDControl() {
static int error, lastError = 0;
static int integral = 0;
int derivative;
int output;
// 計算誤差
error = setTemperature - currentTemperature;
// 積分項計算(帶積分限幅)
integral += error;
if (integral > 1000) integral = 1000;
if (integral < -1000) integral = -1000;
// 微分項計算
derivative = error - lastError;
// PID輸出計算(Kp=20, Ki=0.1, Kd=5,需要根據實際情況調整)
output = 20 * error + 0.1 * integral + 5 * derivative;
// 輸出限幅(0-1000對應PWM占空比0-100%)
if (output > 1000) output = 1000;
if (output < 0) output = 0;
// 更新PWM占空比
pwmDuty = output;
// 更新上一次誤差
lastError = error;
// 輸出PWM
PWMOutput(pwmDuty);
}
// PWM輸出控制
void PWMOutput(unsigned int duty) {
static unsigned int pwmCount = 0;
pwmCount++;
if (pwmCount > 1000) pwmCount = 0;
if (pwmCount < duty)
HEATER_PIN = 1; // 打開加熱器
else
HEATER_PIN = 0; // 關閉加熱器
}
// 定時器0中斷服務函數(用于數碼管掃描)
void Timer0_ISR() interrupt 1 {
TH0 = 0xFC; // 重新加載初值
TL0 = 0x66;
// 數碼管動態掃描
DisplayDigit(displayIndex, displayValue[displayIndex]);
displayIndex++;
if (displayIndex >= 3) displayIndex = 0;
}
// 延時函數(@11.0592MHz)
void Delay1ms(unsigned int ms) {
unsigned int i, j;
for (i = 0; i < ms; i++)
for (j = 0; j < 110; j++);
}
|