原本是一個酸度實時檢測的模塊,單片機用的是STC8H1K08,我想加一個報警設定頁面,規則是長按KEY1就切換界面,雖然能通過KEIL C51的編譯,但下載后運行,發現長按KEY1界面沒有切換,我是MCU引腳接按鍵再接地,同時并了一個0.1uf的電容做硬件消抖。請大神幫忙看下是哪里錯了。
#include "oled.h"
#include "STC8H_Delay.h"
#include "STC8H_UART.h"
#include "STC8H.H"
COMx_InitDefine COM2_InitStruct; // UART1 配置結構體
// 按鍵引腳定義
sbit KEY1 = P3^5;
sbit KEY2 = P3^6;
sbit KEY3 = P3^7;
// 添加全局變量
u8 current_interface = 0; // 0=主界面,1=設置界面
u16 key_press_time = 0; // 按鍵按下時間計數
// 按鍵檢測函數
#define SHORT_PRESS 100 // 短按閾值(100ms)
#define LONG_PRESS 1000 // 長按閾值(1000ms)
u8 KEY1_Scan(void)
{
static u8 key_release = 1; // 按鍵釋放標志
if(key_release && !KEY1) // 按鍵按下且之前是釋放狀態
{
delay_ms(10); // 消抖
if(!KEY1)
{
key_release = 0; // 清除釋放標志
key_press_time = 0; // 清零計時
return 0; // 開始計時
}
}
else if(!KEY1) // 按鍵持續按下
{
key_press_time++;
if(key_press_time >= LONG_PRESS/10) // 長按判斷
{
key_press_time = 0;
return 2; // 長按
}
}
else // 按鍵釋放
{
if(!key_release && key_press_time >= SHORT_PRESS/10) // 短按判斷
{
key_press_time = 0;
key_release = 1;
return 1; // 短按
}
key_press_time = 0;
key_release = 1;
}
return 0;
}
// 顯示設置界面
void showSettingInterface(void)
{
OLED_Clear();
OLED_ShowChinese(50, 0, 9, 16);
OLED_ShowChinese(66, 0, 10, 16);
OLED_ShowString(0, 3, "1.", 16);
OLED_ShowChinese(16, 3, 13, 16);
OLED_ShowChinese(32, 3, 14, 16);
OLED_ShowChinese(48, 3, 9, 16);
OLED_ShowChinese(64, 3, 10, 16);
OLED_ShowString(0, 6, "2.", 16);
OLED_ShowChinese(16, 6, 12, 16);
OLED_ShowChinese(32, 6, 14, 16);
OLED_ShowChinese(48, 6, 9, 16);
OLED_ShowChinese(64, 6, 10, 16);
}
// 初始化 UART2
void UART2_Init(void)
{
COM2_InitStruct.UART_Mode = UART_8bit_BRTx; // 8 位數據,可變波特率
COM2_InitStruct.UART_BRT_Use = BRT_Timer2; // 使用 Timer1 作為波特率發生器
COM2_InitStruct.UART_BaudRate = 9600; // 波特率 9600
COM2_InitStruct.Morecommunicate = DISABLE; // 不允許多機通信
COM2_InitStruct.UART_RxEnable = ENABLE; // 使能接收
COM2_InitStruct.BaudRateDouble = DISABLE; // 不加倍波特率
UART_Configuration(UART2, &COM2_InitStruct); // 配置 UART1
IE2 |= 0x01; // 使能 UART2 中斷
EA = 1; // 使能全局中斷
}
// 發送檢測指令
void sendDetectionCommand(void)
{
TX2_write2buff(0xA0);
TX2_write2buff(0x00);
TX2_write2buff(0x00);
TX2_write2buff(0x00);
TX2_write2buff(0x00);
TX2_write2buff(0xA0);
}
// 解析接收數據
void parseUARTData(u16 *pht, u16 *temp)
{
if (COM2.RX_Cnt >= 6) // 確保接收到 6 字節
{
if (RX2_Buffer[0] == 0xAA)
{
u8 sum = 0xAA + RX2_Buffer[1] + RX2_Buffer[2] + RX2_Buffer[3] + RX2_Buffer[4];
if ((sum & 0xFF) == RX2_Buffer[5]) // 校驗和驗證
{
*pht = (RX2_Buffer[1] << 8) | RX2_Buffer[2]; // 酸度值
*temp = (RX2_Buffer[3] << 8) | RX2_Buffer[4]; // 溫度 ADC 值
}
}
COM2.RX_Cnt = 0; // 清空接收計數器
}
}
// 清空動態顯示區域
void clearDynamicArea(void)
{
u8 i;
OLED_Set_Pos(51, 4); // 酸度 值區域
for (i = 0; i < 24; i++)
{
OLED_WR_Byte(0, OLED_DATA); // 清空 24 像素寬
}
OLED_Set_Pos(49, 6); // 水溫值區域
for (i = 0; i < 24; i++)
{
OLED_WR_Byte(0, OLED_DATA); // 清空 24 像素寬
}
}
// 顯示浮點數(例如 25.0)
void OLED_ShowFloat(u8 x, u8 y, float num, u8 size)
{
u16 int_part = (u16)num; // 整數部分
u16 dec_part = (u16)((num - int_part) * 10); // 小數部分(一位)
OLED_ShowNum(x, y, int_part, 2, size); // 顯示整數部分
OLED_ShowChar(x + 16, y, '.', size); // 顯示小數點
OLED_ShowNum(x + 24, y, dec_part, 1, size); // 顯示小數部分
}
int main(void)
{
u16 pht_value = 0; // 酸度 值
u16 temp_value = 0; // 溫度 ADC 值
float temp = 0.0; // 實際溫度值
P_SW2 |= 0x80; // 使能訪問 XFR
IRCBAND = 0x00; // 選擇 11.0592MHz
IRCDB = 0x00; // 頻率不翻倍
P_SW2 &= 0x7F; // 關閉訪問 XFR
P1M0 = 0x00; // 設置 P1 為準雙向口
P1M1 = 0x00;
OLED_Init(); // 初始化 OLED
OLED_ColorTurn(0); // 正常顯示(非反色)
OLED_DisplayTurn(0); // 正常顯示(非翻轉)
UART2_Init(); // 初始化 UART1
// 設置P3.5~P3.7為上拉輸入模式
P3M1 &= ~(0xE0); // P3.5~P3.7設為輸入模式
P3M0 &= ~(0xE0);
P3PU |= 0xE0; // P3.5~P3.7使能上拉電阻
// 顯示固定內容(只執行一次)
OLED_Clear(); // 清屏
OLED_ShowChinese(25, 0, 0, 16); // 顯示 “注”
OLED_ShowChinese(89, 0, 1, 16); // 顯示 “意”
OLED_ShowChinese(9, 2, 2, 16); // 顯示 “酸”
OLED_ShowChinese(33, 2, 3, 16); // 顯示 “度”
OLED_ShowChinese(57, 2, 4, 16); // 顯示 “檢”
OLED_ShowChinese(81, 2, 5, 16); // 顯示 “測”
OLED_ShowChinese(105, 2, 6, 16); // 顯示 “中”
OLED_ShowString(0, 4, "PHT", 16); // 顯示 "PHT"
OLED_ShowChinese(25, 4, 11, 16); // 顯示 “值”
OLED_ShowString(41, 4, ":", 16); // 顯示冒號
OLED_ShowString(80, 4, "pht", 16); // 顯示pht
OLED_ShowChinese(0, 6, 2, 16); // 顯示 “水”
OLED_ShowChinese(24, 6, 7, 16); // 顯示 “溫”
OLED_ShowString(41, 6, ":", 16); // 顯示冒號
OLED_ShowChinese(96, 6, 8, 16); // 顯示 “℃”
while (1)
{
u8 key_value = KEY1_Scan();
if(key_value == 2) // KEY1長按
{
current_interface = !current_interface; // 切換界面
if(current_interface)
{
showSettingInterface();
}
else
{
OLED_Clear(); // 切回主界面時清屏
// 重新顯示主界面固定內容
OLED_ShowChinese(25, 0, 0, 16); // 顯示 "注"
OLED_ShowChinese(89, 0, 1, 16); // 顯示 "意"
OLED_ShowChinese(9, 2, 2, 16); // 顯示 "酸"
OLED_ShowChinese(33, 2, 3, 16); // 顯示 "度"
OLED_ShowChinese(57, 2, 4, 16); // 顯示 "檢"
OLED_ShowChinese(81, 2, 5, 16); // 顯示 "測"
OLED_ShowChinese(105, 2, 6, 16); // 顯示 "中"
OLED_ShowString(0, 4, "PHT", 16); // 顯示 "PHT"
OLED_ShowChinese(25, 4, 11, 16); // 顯示 "值"
OLED_ShowString(41, 4, ":", 16); // 顯示冒號
OLED_ShowString(80, 4, "pht", 16); // 顯示pht
OLED_ShowChinese(0, 6, 2, 16); // 顯示 "水"
OLED_ShowChinese(24, 6, 7, 16); // 顯示 "溫"
OLED_ShowString(41, 6, ":", 16); // 顯示冒號
OLED_ShowChinese(96, 6, 8, 16); // 顯示 "℃"
}
while(!KEY1); // 等待按鍵釋放
delay_ms(100); // 防抖
}
if(!current_interface) // 主界面
{
sendDetectionCommand(); // 發送檢測指令
delay_ms(100); // 等待數據返回
parseUARTData(&pht_value, &temp_value); // 解析數據
temp = temp_value / 100.0; // 轉換溫度值為浮點數
clearDynamicArea(); // 清空動態顯示區域
OLED_ShowNum(51, 4, pht_value, 3, 16); // 顯示 酸度 值
OLED_ShowFloat(49, 6, temp, 16); // 顯示水溫值
}
delay_ms(10); // 10ms掃描一次按鍵
}
}
|