久久久久久久999_99精品久久精品一区二区爱城_成人欧美一区二区三区在线播放_国产精品日本一区二区不卡视频_国产午夜视频_欧美精品在线观看免费

 找回密碼
 立即注冊

QQ登錄

只需一步,快速開始

搜索
查看: 242|回復: 3
打印 上一主題 下一主題
收起左側

求助大佬:設置了按鍵長按切換顯示畫面,但長按后卻不切換

[復制鏈接]
跳轉到指定樓層
樓主
ID:963566 發表于 2025-4-1 16:41 | 只看該作者 回帖獎勵 |倒序瀏覽 |閱讀模式
原本是一個酸度實時檢測的模塊,單片機用的是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掃描一次按鍵
    }
}

分享到:  QQ好友和群QQ好友和群 QQ空間QQ空間 騰訊微博騰訊微博 騰訊朋友騰訊朋友
收藏收藏 分享淘帖 頂 踩
回復

使用道具 舉報

沙發
ID:879809 發表于 2025-4-1 19:31 | 只看該作者
長按是在KEY1_Scan()函數里面判斷的,如果是長按返回2,但是你調用這個函數根本就不判斷返回值,所以你根本就不知道長按。
回復

使用道具 舉報

板凳
ID:74687 發表于 2025-4-1 20:22 | 只看該作者
按鍵用狀態機最好
回復

使用道具 舉報

地板
ID:320097 發表于 2025-4-4 21:41 | 只看該作者
我一般是在按鍵函數里面直接判斷是長按還是短按
bit key;
unsigned z;
if(k==0&&key==0)
    {
     delay_ms(5);     if(k==0)                              //確認有按鍵信號
             {
              z=0;
               while(k==0&&z<1000)                    
                         {
                           delay_ms(1);                       // 1ms加1
                           z++;
                         }
               if(z<1000)                                      //在1秒之內松手的判定為短按
                         {
                           key=1;
                            .................
                          }
               else                                              //反之則是長按
                         {
                           key=1;
                           ..................
                          }
              }
     }
if(key==1)                   //松手檢測
    {
      if(k==1)
           {
              delay_ms(5);
              if(k==1)
                       {
                         key=0;                 //檢測通過,清除按鍵標志
                       }
           }
    }
回復

使用道具 舉報

您需要登錄后才可以回帖 登錄 | 立即注冊

本版積分規則

手機版|小黑屋|51黑電子論壇 |51黑電子論壇6群 QQ 管理員QQ:125739409;技術交流QQ群281945664

Powered by 單片機教程網

快速回復 返回頂部 返回列表
主站蜘蛛池模板: 国产成人精品午夜 | 99视频入口 | 国产精品国产精品国产专区不卡 | 精品久久久久久久久久久 | 国产不卡视频 | 欧美激情亚洲 | 日韩免费1区二区电影 | 中文字幕在线精品 | 久久美女视频 | 一区二区高清 | 国产丝袜一区二区三区免费视频 | 天堂亚洲 | 九九在线视频 | 亚洲男人的天堂网站 | 日韩高清国产一区在线 | 欧美一级在线观看 | 羞羞色网站 | 日本一区二区高清不卡 | 国产高潮好爽受不了了夜色 | 欧美日韩在线看 | 欧美精品日韩精品 | 天天艹逼网 | 91中文在线观看 | 中文字幕高清视频 | 午夜视频网| 国产精品高潮呻吟久久 | 国产一区二区在线91 | 亚洲精品91| 欧美中文| 欧美成人猛片aaaaaaa | 性色网站| 午夜激情国产 | 91中文字幕在线观看 | 91欧美精品 | 久久国产高清视频 | 国产欧美一区二区久久性色99 | 久久久激情 | 亚洲天堂久久 | 精品国产免费人成在线观看 | 久久久久久黄 | 亚洲一区二区三区高清 |