找回密碼
 立即注冊(cè)

QQ登錄

只需一步,快速開始

搜索
查看: 2464|回復(fù): 13
打印 上一主題 下一主題
收起左側(cè)

求助單片機(jī)菜單程序

  [復(fù)制鏈接]
跳轉(zhuǎn)到指定樓層
樓主
ID:579174 發(fā)表于 2024-7-25 21:23 | 只看該作者 回帖獎(jiǎng)勵(lì) |倒序?yàn)g覽 |閱讀模式
200黑幣
51單片機(jī)初學(xué)者,想用4個(gè)按鍵實(shí)現(xiàn)菜單設(shè)置,K1為菜單翻頁,K2/K3為數(shù)值的加減,K4為保存退出,2個(gè)數(shù)碼管顯示,一個(gè)數(shù)碼管顯示菜單頁面如P01,另一個(gè)數(shù)碼管顯示菜單對(duì)應(yīng)的值,如數(shù)字123或ON和OFF。困惑的是  進(jìn)入對(duì)應(yīng)頁面如何獲取菜單對(duì)應(yīng)的初值,求大神指導(dǎo)!

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

使用道具 舉報(bào)

沙發(fā)
ID:404160 發(fā)表于 2024-7-26 11:20 | 只看該作者
編寫一個(gè)使用C51單片機(jī)的程序,實(shí)現(xiàn)按鍵控制菜單設(shè)置的功能,需要考慮以下幾個(gè)方面:

1. 按鍵的初始化和防抖動(dòng)處理。
2. 數(shù)碼管的驅(qū)動(dòng)和顯示。
3. 菜單邏輯的設(shè)計(jì),包括翻頁、數(shù)值加減和保存退出。
4. 程序結(jié)構(gòu)的安排,確保代碼的可讀性和可維護(hù)性。

下面是一個(gè)簡單的示例代碼,用于實(shí)現(xiàn)上述功能。請(qǐng)注意,這只是一個(gè)基礎(chǔ)示例,實(shí)際應(yīng)用中可能需要根據(jù)具體的硬件連接和需求進(jìn)行調(diào)整。

```c
#include <reg51.h>

#define KEY1 P3_0
#define KEY2 P3_1
#define KEY3 P3_2
#define KEY4 P3_3

#define SEGMENT_PORT P0 // 數(shù)碼管的段選端口
#define DIGIT_PORT P1  // 數(shù)碼管的位選端口

// 假設(shè)菜單有3個(gè)頁面,每個(gè)頁面有2個(gè)可設(shè)置的值
#define MAX_PAGE 3
#define MAX_VALUE 2

unsigned char currentPage = 0;
unsigned char currentValIndex = 0;
unsigned int values[MAX_PAGE][MAX_VALUE] = {
    {100, 200}, // 第一個(gè)頁面的兩個(gè)值
    {300, 400}, // 第二個(gè)頁面的兩個(gè)值
    {500, 600}  // 第三個(gè)頁面的兩個(gè)值
};

// 延時(shí)函數(shù)
void delay(unsigned int ms) {
    unsigned int i, j;
    for (i = 0; i < ms; i++)
        for (j = 0; j < 123; j++);
}

// 按鍵掃描函數(shù)
unsigned char keyScan() {
    if (KEY1 == 0) {
        delay(20); // 簡單的消抖
        if (KEY1 == 0) {
            currentPage = (currentPage + 1) % MAX_PAGE; // 翻頁
            return 1;
        }
    }
    if (KEY2 == 0) {
        delay(20);
        if (KEY2 == 0) {
            values[currentPage][currentValIndex]++; // 增加數(shù)值
            return 2;
        }
    }
    if (KEY3 == 0) {
        delay(20);
        if (KEY3 == 0) {
            values[currentPage][currentValIndex]--; // 減少數(shù)值
            return 3;
        }
    }
    if (KEY4 == 0) {
        delay(20);
        if (KEY4 == 0) {
            return 4; // 保存退出
        }
    }
    return 0;
}

// 數(shù)碼管顯示函數(shù)
void display(unsigned char page, unsigned int value) {
    // 這里需要根據(jù)實(shí)際的數(shù)碼管硬件連接來編寫顯示邏輯
    // 以下代碼僅為示例
    SEGMENT_PORT = 0xFF; // 關(guān)閉所有段
    DIGIT_PORT = ~(1 << page); // 選擇當(dāng)前顯示的數(shù)碼管

    // 將數(shù)值轉(zhuǎn)換為數(shù)碼管可以顯示的格式
    // 這里需要編寫轉(zhuǎn)換邏輯,例如將數(shù)值轉(zhuǎn)換為BCD碼等
    unsigned char displayValue = value % 10; // 僅顯示個(gè)位數(shù)作為示例

    SEGMENT_PORT = ~displayValue; // 打開相應(yīng)的段
}

void main() {
    while (1) {
        unsigned char key = keyScan();
        if (key == 1) {
            // 翻頁
            display(0, currentPage + 1); // 顯示頁面號(hào)
        } else if (key == 2 || key == 3) {
            // 數(shù)值加減
            display(1, values[currentPage][currentValIndex]); // 顯示當(dāng)前值
        } else if (key == 4) {
            // 保存退出
            // 這里可以添加保存邏輯,例如寫入EEPROM等
            break;
        }
    }
}
```

請(qǐng)注意,這個(gè)示例代碼沒有包含所有的硬件細(xì)節(jié),例如數(shù)碼管的驅(qū)動(dòng)邏輯和按鍵的防抖動(dòng)處理。在實(shí)際應(yīng)用中,你可能需要根據(jù)具體的硬件連接和需求來編寫相應(yīng)的驅(qū)動(dòng)代碼。此外,對(duì)于數(shù)值的顯示,你可能需要將數(shù)值轉(zhuǎn)換為BCD碼或其他格式,以便數(shù)碼管可以正確顯示。
回復(fù)

使用道具 舉報(bào)

板凳
ID:548322 發(fā)表于 2024-7-26 15:00 | 只看該作者
樓上用chatgpt回復(fù)也挺⑥的,不過這邊建議作為51單片機(jī)初學(xué)者,可以先嘗試兩個(gè)界面如何顯示不同數(shù)據(jù),再做菜單界面,一般STM32的菜單界面都是通過鏈表的方式實(shí)現(xiàn),可以用stc試試枚舉+結(jié)構(gòu)體的方式去做。如果等人給你一個(gè)開源工程,基本上很難。
回復(fù)

使用道具 舉報(bào)

地板
ID:1116913 發(fā)表于 2024-7-26 15:31 | 只看該作者
回復(fù)

使用道具 舉報(bào)

5#
ID:579174 發(fā)表于 2024-7-26 19:48 | 只看該作者
2300606886 發(fā)表于 2024-7-26 15:31
http://www.torrancerestoration.com/bbs/dpj-232305-1.html可以看看他的程序

感謝!
回復(fù)

使用道具 舉報(bào)

6#
ID:579174 發(fā)表于 2024-7-26 19:48 | 只看該作者
小盼666 發(fā)表于 2024-7-26 15:00
樓上用chatgpt回復(fù)也挺⑥的,不過這邊建議作為51單片機(jī)初學(xué)者,可以先嘗試兩個(gè)界面如何顯示不同數(shù)據(jù),再做 ...

非常感謝!
回復(fù)

使用道具 舉報(bào)

7#
ID:1129675 發(fā)表于 2024-7-27 00:07 | 只看該作者
可以用狀態(tài)機(jī)做
回復(fù)

使用道具 舉報(bào)

8#
ID:982617 發(fā)表于 2024-8-7 17:13 | 只看該作者
要實(shí)現(xiàn)這個(gè)功能,你需要構(gòu)建一個(gè)狀態(tài)機(jī)以管理不同菜單頁面的控制流程。下面是一個(gè)基于51單片機(jī)的簡單實(shí)現(xiàn)思路:

### 步驟分解:

#### 1. 定義菜單頁面和狀態(tài):

- **菜單頁面**:假設(shè)你有3個(gè)主要菜單頁面,可以是:
  - 頁面1:初值為0的數(shù)值設(shè)置。
  - 頁面2:初值為ON或OFF的狀態(tài)設(shè)置。
  - 頁面3:初值為123的數(shù)值設(shè)置。
  
- **狀態(tài)**:需要的狀態(tài)包括但不限于:
  - 狀態(tài)1:顯示頁面1,并顯示對(duì)應(yīng)的數(shù)值或狀態(tài)。
  - 狀態(tài)2:顯示頁面2,并顯示ON或OFF狀態(tài)。
  - 狀態(tài)3:顯示頁面3,并顯示數(shù)值123。

#### 2. 初始化:

- 設(shè)置數(shù)碼管顯示模式,如使用動(dòng)態(tài)掃描顯示。
- 初始化按鍵輸入,如使用中斷或循環(huán)檢查按鍵狀態(tài)。
- 將所有菜單頁的初始值存儲(chǔ)在存儲(chǔ)器中,例如在特殊功能寄存器(SFR)或程序存儲(chǔ)器中。

#### 3. 狀態(tài)機(jī)設(shè)計(jì):

- **狀態(tài)機(jī)**使用狀態(tài)寄存器來跟蹤當(dāng)前的菜單頁面和狀態(tài)。
- **狀態(tài)轉(zhuǎn)移**通過按鍵輸入來觸發(fā),例如,K1按鍵用于翻頁,K2/K3按鍵用于數(shù)值加減,K4按鍵用于保存設(shè)置并退出當(dāng)前頁面或保存設(shè)置后返回上一頁。

#### 4. 編寫程序:

以下是一個(gè)基于簡單假設(shè)的偽代碼示例:

```c
#include <reg51.h> // 51單片機(jī)頭文件

#define LCD_DATA_PORT P0 // LCD數(shù)據(jù)端口
#define LCD_CMD_PORT P2 // LCD命令端口
#define SENSOR_PORT P1 // 按鍵端口
#define PAGE1_INIT_VALUE 0 // 初始值為0
#define PAGE2_INIT_VALUE "ON" // 初始狀態(tài)為ON
#define PAGE3_INIT_VALUE 123 // 初始值為123
#define PAGE_COUNT 3 // 3個(gè)菜單頁面

void setup() {
    // 初始化數(shù)碼管,按鍵,和LCD
}

unsigned char currentState = 1; // 菜單頁面狀態(tài)
unsigned char currentValue = PAGE1_INIT_VALUE; // 當(dāng)前菜單的值
unsigned char currentDisplay = PAGE1_INIT_VALUE; // 當(dāng)前顯示的值
char displayValue[2]; // 用于顯示的數(shù)值字符串

void loop() {
    // 檢查按鍵狀態(tài)并根據(jù)狀態(tài)機(jī)更新
    if (K1) {
        // 翻頁操作
    } else if (K2) {
        // 數(shù)值加操作
    } else if (K3) {
        // 數(shù)值減操作
    } else if (K4) {
        // 保存退出操作
    }

    // 顯示操作
    displayCurrentPage();
   
    // 根據(jù)狀態(tài)更改顯示
    if (currentState == 1) {
        // 顯示頁面1
    } else if (currentState == 2) {
        // 顯示頁面2
    } else if (currentState == 3) {
        // 顯示頁面3
    }
}

void displayCurrentPage() {
    // 顯示當(dāng)前值或狀態(tài)到數(shù)碼管
}

// 更多細(xì)節(jié)和邏輯填充...
```

### 實(shí)現(xiàn)細(xì)節(jié):

- **按鍵輸入**:使用中斷或者循環(huán)檢查按鍵狀態(tài)。
- **數(shù)碼管顯示**:使用動(dòng)態(tài)掃描或靜態(tài)顯示方法更新數(shù)碼管顯示。
- **狀態(tài)機(jī)邏輯**:根據(jù)按鍵輸入更新狀態(tài)寄存器,從而控制數(shù)碼管顯示的內(nèi)容和執(zhí)行相應(yīng)的操作。

這個(gè)框架提供了基本的思路和結(jié)構(gòu),你需要根據(jù)實(shí)際的硬件和軟件環(huán)境進(jìn)一步完善代碼。特別是按鍵的處理和數(shù)碼管顯示的具體實(shí)現(xiàn),可能需要參考具體硬件的驅(qū)動(dòng)庫或參考資料。
回復(fù)

使用道具 舉報(bào)

9#
ID:579174 發(fā)表于 2024-8-12 10:04 | 只看該作者
hezezeze 發(fā)表于 2024-8-7 17:13
要實(shí)現(xiàn)這個(gè)功能,你需要構(gòu)建一個(gè)狀態(tài)機(jī)以管理不同菜單頁面的控制流程。下面是一個(gè)基于51單片機(jī)的簡單實(shí)現(xiàn)思 ...

受教!
回復(fù)

使用道具 舉報(bào)

10#
ID:123917 發(fā)表于 2024-8-12 19:16 | 只看該作者
思路,R0的值對(duì)應(yīng)菜單號(hào)碼,比如R0=1,顯示P01,R0=2,顯示P02
回復(fù)

使用道具 舉報(bào)

11#
ID:309610 發(fā)表于 2024-8-18 09:46 | 只看該作者
先做一個(gè)按鍵掃描函數(shù)返回值 0,無按鍵,1菜單按鍵、2上翻、3下翻、4確定保存、5超時(shí)60s無按鍵.具體程序很多可以參考其他
做一個(gè)顯示函數(shù),disp_menu(u8 menu)顯示菜單,disp_datp(u8 data)顯示菜單內(nèi)容
如果菜單參數(shù)是同類型,定義菜單數(shù)組就行。不同類型要定義結(jié)構(gòu)體。
#define XX  10      //XX菜單數(shù)目
u8 menu=0; //菜單號(hào)   0為運(yùn)行顯示內(nèi)容,非0菜單調(diào)整
u8 menu_last=0; //歷史菜單號(hào)
u8 datp_temp=0;// 菜單臨時(shí)寄存
u8 datp_menu[XX];//菜單參數(shù)表

void main()
{
  while(1)
  {
    u8 key=keyscan();//讀取按鍵
       
    if(key==1)                      //菜單鍵 循環(huán)菜單
          { menu++; if(menu>XX)menu=0;}
        else if(key==2)                //上翻 臨時(shí)參數(shù)加
          { datp_temp++;}         
    else if(key==3)                //下翻 臨時(shí)參數(shù)減
          { datp_temp--;}                
        else if(key==4)                //保存 臨時(shí)參數(shù)保存
                { if(menu>0)
                     {datp_menu[menu-1]=datp_temp;}         
                                 }
        else if(key==5)                 //超時(shí)退出菜單
                {menu=0;}         

        if ((menu!=menu_last)&&(menu>0)) //菜單改變讀取菜單保存到臨時(shí)寄存
            { datp_temp=datp_menu[menu-1]
        menu_last=menu;                   //菜單號(hào)寄存
               
         if (menu==0) { disp();}          //正常顯示程序
         else {  disp_menu( menu);       //顯示菜單號(hào)
                 disp_datp(datp_temp);    // 顯示菜單內(nèi)容
                         }
        }
}
  此程序適合參數(shù)較少,參數(shù)不大的簡易菜單或調(diào)試學(xué)習(xí)。進(jìn)一步上翻鍵改為移位鍵增加一轉(zhuǎn)換函數(shù)把指定參數(shù)
  整形拆分為個(gè)、 十、百、千、萬 、小數(shù)。存儲(chǔ)到臨時(shí)數(shù)組內(nèi),移位鍵修改指針地址。兼修改位的閃爍顯示標(biāo)志、
  下翻修改制定臨時(shí)數(shù)組內(nèi)容。這樣可以設(shè)定多種類型參數(shù),可以設(shè)定較大數(shù)值。按保存鍵再把臨時(shí)數(shù)組內(nèi)內(nèi)容整合
  保存到所讀參數(shù)內(nèi)。
回復(fù)

使用道具 舉報(bào)

12#
ID:1125252 發(fā)表于 2024-8-20 18:44 | 只看該作者
if(K1==0)
{
  num++;
  if(num>=4)
  {

  }
}
回復(fù)

使用道具 舉報(bào)

13#
ID:1125252 發(fā)表于 2024-8-20 18:52 | 只看該作者
if(k1==0)
{
num++;
if(num>=4){num=0;}
}
if(num==0){讀取eeprom的addr對(duì)應(yīng)值作為初值;
                if(k2==0){addr++;}
                if(k3==0){addr--;}
                if(k4==0){addr值寫入eeprom;}
                display(addr);
}
if(num==1){同上操作,顯示和讀取eeprom值可以在c51教程找到}
if(num==2){同上操作}
if(num==3){同上操作}
回復(fù)

使用道具 舉報(bào)

14#
ID:982617 發(fā)表于 2024-8-23 14:30 | 只看該作者
在使用51單片機(jī)進(jìn)行按鍵輸入和數(shù)碼管顯示時(shí),可以設(shè)計(jì)一個(gè)簡單的狀態(tài)機(jī)來處理按鍵輸入和菜單的顯示。以下是一個(gè)基本的實(shí)現(xiàn)步驟:

### 1. 菜單結(jié)構(gòu)與變量定義
首先,定義菜單的頁面和對(duì)應(yīng)的參數(shù)值。假設(shè)你的菜單有以下頁面:
- **P01**: 設(shè)置為初始頁面,對(duì)應(yīng)的值可能是0(或OFF)。
- **P02**: 設(shè)置為頁面2,對(duì)應(yīng)的值可能是123或ON。
- **P03**: 設(shè)置為頁面3,對(duì)應(yīng)的值可能是特定數(shù)字或狀態(tài)(如OFF)。
- **P04**: 設(shè)置為頁面4,對(duì)應(yīng)的值可能是特定數(shù)字或狀態(tài)(如ON)。

定義菜單頁面和值的變量:
```c
#define MENU_PAGE_SIZE 4
#define OFF "OFF"
#define ON "ON"

char menuPage = P01;
char menuValue[MENU_PAGE_SIZE][10] = {"", "0", "123", "OFF", "ON"};
int currentValue = 0;
```

### 2. 初始化
在程序開始時(shí),初始化數(shù)碼管LED顯示和LCD顯示模塊(如果使用)。

### 3. 狀態(tài)機(jī)
使用狀態(tài)機(jī)來處理按鍵輸入和菜單顯示。定義幾個(gè)狀態(tài):
- **STATE_INIT**:初始狀態(tài),用于初始化和顯示菜單頁面。
- **STATE_NUM_UP**:值增加狀態(tài)。
- **STATE_NUM_DOWN**:值減小狀態(tài)。
- **STATE_CONFIRM**:確認(rèn)狀態(tài),用于保存當(dāng)前值并退出菜單。

狀態(tài)機(jī)可以通過一個(gè)變量(如`currentState`)來跟蹤當(dāng)前狀態(tài),并根據(jù)按鍵輸入改變狀態(tài)。

### 4. 按鍵處理函數(shù)
```c
void processK1() {
    if (currentState == STATE_INIT) {
        // 菜單翻頁
        if (menuPage < MENU_PAGE_SIZE) {
            menuPage++;
        } else {
            menuPage = P01;
        }
        displayMenuPage();
    }
}

void processK2() {
    switch (currentState) {
        case STATE_INIT:
            // 菜單值增加
            if (menuPage == 1) {
                currentValue++;
                if (currentValue > 9) {
                    currentValue = 0;
                }
                displayValue();
            }
            break;
        case STATE_NUM_UP:
            currentValue++;
            if (currentValue > 9) {
                currentValue = 0;
            }
            displayValue();
            break;
        case STATE_CONFIRM:
            // 保存值并退出
            displayValue();
            currentState = STATE_INIT;
        // 重置菜單值
        menuValue[menuPage] = menuValue[menuPage][0] + (char)(currentValue + '0');
        displayMenuValue();
        currentState = STATE_INIT;
    }
}

void processK3() {
    switch (currentState) {
        case STATE_INIT:
            // 菜單值減小
            if (menuPage == 1) {
                currentValue--;
                if (currentValue < 0) {
                    currentValue = 9;
                }
                displayValue();
            }
            break;
        case STATE_NUM_DOWN:
            currentValue--;
            if (currentValue < 0) {
                currentValue = 9;
            }
            displayValue();
            break;
        case STATE_CONFIRM:
            // 無需處理
            break;
    }
}

void processK4() {
    if (currentState == STATE_INIT) {
        currentState = STATE_CONFIRM;
        displayConfirmation();
    }
}
```

### 5. 顯示函數(shù)
定義函數(shù)來更新數(shù)碼管的顯示。這通常涉及到硬件接口的使用,如定時(shí)器、串行通信等。

### 6. 主循環(huán)
在主循環(huán)中調(diào)用上述函數(shù),并根據(jù)當(dāng)前狀態(tài)執(zhí)行操作。

### 7. 運(yùn)行流程
- 程序開始時(shí),進(jìn)入`STATE_INIT`狀態(tài),數(shù)碼管顯示菜單頁面。
- 當(dāng)按下K1時(shí),切換菜單頁面。
- 按下K2或K3時(shí),在對(duì)應(yīng)菜單值上加減。
- 按下K4時(shí),確認(rèn)當(dāng)前值并退出菜單。

通過這些步驟,你可以實(shí)現(xiàn)一個(gè)基本的菜單設(shè)置功能,從按鍵輸入到菜單頁面和值的顯示都有詳細(xì)的處理邏輯。根據(jù)實(shí)際硬件和環(huán)境調(diào)整上述代碼中的接口和細(xì)節(jié)部分。
回復(fù)

使用道具 舉報(bào)

本版積分規(guī)則

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

Powered by 單片機(jī)教程網(wǎng)

快速回復(fù) 返回頂部 返回列表