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

 找回密碼
 立即注冊

QQ登錄

只需一步,快速開始

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

關于矩陣鍵盤代碼優化問題

[復制鏈接]
跳轉到指定樓層
樓主
我是 51 單片機新手,在學習 [bilibili 51教程[6-1] 矩陣鍵盤] (https://www.bilibili.com/video/B ... eopod.episodes&p=15) 時發現這段代碼有點冗余,可以優化一下嗎?

原視頻代碼類似以下:

```c
# ifndef MATRIX_H
# define MATRIX_H

# include "8051.h"
# include "delay.h"

unsigned char matrix_keydown()
{
  /*
  unsigned char i;
  for (i = 3; i > 0; --i)
  {
    P1 = 0xff;
    // 我好煩啊,這個P1到底怎么回事
    P1 = P1 ^ (0x01 << i + 4);

    if (P1_7 == 0) {delay(3); while (P1_7 == 0); delay(3); return 1 + (3 - i);}
    if (P1_6 == 0) {delay(3); while (P1_6 == 0); delay(3); return 5 + (3 - i);}
    if (P1_5 == 0) {delay(3); while (P1_5 == 0); delay(3); return 9 + (3 - i);}
    if (P1_4 == 0) {delay(3); while (P1_4 == 0); delay(3); return 13 + (3 - i);}
  }
  */
  P1 = 0xff;
  P1_3 = 0;
  if (P1_7 == 0) {delay(3); while (P1_7 == 0); delay(3); return 1;}
  if (P1_6 == 0) {delay(3); while (P1_6 == 0); delay(3); return 5;}
  if (P1_5 == 0) {delay(3); while (P1_5 == 0); delay(3); return 9;}
  if (P1_4 == 0) {delay(3); while (P1_4 == 0); delay(3); return 13;}

  P1 = 0xff;
  P1_2 = 0;
  if (P1_7 == 0) {delay(3); while (P1_7 == 0); delay(3); return 2;}
  if (P1_6 == 0) {delay(3); while (P1_6 == 0); delay(3); return 6;}
  if (P1_5 == 0) {delay(3); while (P1_5 == 0); delay(3); return 10;}
  if (P1_4 == 0) {delay(3); while (P1_4 == 0); delay(3); return 14;}

  P1 = 0xff;
  P1_1 = 0;
  if (P1_7 == 0) {delay(3); while (P1_7 == 0); delay(3); return 3;}
  if (P1_6 == 0) {delay(3); while (P1_6 == 0); delay(3); return 7;}
  if (P1_5 == 0) {delay(3); while (P1_5 == 0); delay(3); return 11;}
  if (P1_4 == 0) {delay(3); while (P1_4 == 0); delay(3); return 15;}

  P1 = 0xff;
  P1_0 = 0;
  if (P1_7 == 0) {delay(3); while (P1_7 == 0); delay(3); return 4;}
  if (P1_6 == 0) {delay(3); while (P1_6 == 0); delay(3); return 8;}
  if (P1_5 == 0) {delay(3); while (P1_5 == 0); delay(3); return 12;}
  if (P1_4 == 0) {delay(3); while (P1_4 == 0); delay(3); return 16;}

  return 0;
}

# endif

```
可以看出代碼量太長了。

我想進行優化類似以下:
```C
# ifndef MATRIX_H
# define MATRIX_H

# include "delay.h"

unsigned char math_key()
{
  // 簡單的算法在哪里?
  // 不能將 P1 預設為 0x0f
  // 先暴力過了
  unsigned char S2, S1;
  S2 = P1 & 0x0f;
  S2 = P1 - 1 << 2 | 1;
  S1 = P1 & 0xf0 >> 4;
  return S2 + S1;
  // return ((P1 & 0x0f) - 1 << 2 | 1) + (P1 & 0xf0 >> 4);
}

unsigned char matrix_keydown()
{
  unsigned char key_number = 0;
  // 當 P1 被按下時用 math_key() 算出按鍵位置分別對應 1-16
  if (P1 != 0xff)
  {
    delay(3);
    key_number = math_key();
  }
  return key_number;
}

# endif
```
可惜失敗了。。。
自己試錯了許久,有點似懂非懂原因,覺得這個失敗有點知識的缺陷,可以有版友幫助解答一下嗎?
可以指點一下優化的方向嗎?


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

使用道具 舉報

沙發
ID:1109793 發表于 2024-11-29 16:14 | 只看該作者
不是有個反轉法嗎?
回復

使用道具 舉報

板凳
ID:161164 發表于 2024-11-29 16:35 | 只看該作者
  1.                         switch(Keypad)
  2.                         {
  3.                                 case 0x0E:KeyVal=1;break;
  4.                                 case 0x0D:KeyVal=2;break;
  5.                                 case 0x0B:KeyVal=3;break;
  6.                                 case 0x07:KeyVal=4;break;
  7.                         }
  8.                         Keypad = 0xF0;
  9.                         _nop_();_nop_();_nop_();_nop_();_nop_();_nop_();
  10.                         switch(Keypad)
  11.                         {
  12.                                 case 0xE0:KeyVal+=0;break;
  13.                                 case 0xD0:KeyVal+=4;break;
  14.                                 case 0xB0:KeyVal+=8;break;
  15.                                 case 0x70:KeyVal+=12;break;
  16.                         }
復制代碼
回復

使用道具 舉報

地板
ID:1133081 發表于 2024-11-29 21:41 | 只看該作者
給你一個簡單的4*4矩陣按鍵示例參考


  1. #include <reg51.h>
  2. #define uint unsigned int
  3. #define uchar unsigned char
  4. uchar  code table[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f};
  5. uchar KeyValue=0;//鍵值變量


  6. void delayms(uint k)
  7. {
  8.         uint i,j;
  9.         for(i=k;i>0;i--)
  10.                 for(j=115;j>0;j--);
  11. }

  12. void key_scan()                                        //按鍵掃描程序
  13. {
  14.         static bit sign=0;                        //位變量
  15.         static unsigned int count=0;//計數變量
  16.         P3=0xf0;                                        //賦值P3 1111 0000
  17.         if(P3!=0xf0)                                //檢測有按鍵按下
  18.         {
  19.                 if(++count>=20 && sign==0)//計數消抖
  20.                 {                       
  21.                         sign=1;                        //按鍵自鎖標志置1
  22.                         switch(P3)
  23.                         {
  24.                                 case(0Xe0):KeyValue = 1;break;
  25.                                 case(0Xd0):KeyValue = 2;break;
  26.                                 case(0Xb0):KeyValue = 3;break;
  27.                                 case(0X70):KeyValue = 4;break;
  28.                         }
  29.                         P3=0x0f;                        //賦值P3 0000 1111
  30.                         switch(P3)
  31.                         {
  32.                                 case(0X0e):KeyValue+= 0;break;
  33.                                 case(0X0d):KeyValue+= 4;break;
  34.                                 case(0X0b):KeyValue+= 8;break;
  35.                                 case(0X07):KeyValue+=12;break;
  36.                         }
  37.                 }
  38.         }
  39.         else                                                //鍵抬起
  40.         {
  41.                 sign=0;                                //按鍵自鎖標志清0
  42.                 count=0;                                //消抖計數清0
  43.         }
  44. }

  45. void display()                                        //數碼管顯示程序
  46. {
  47.         static uchar i=0;
  48.         P0=0x00;
  49.         P2=~(0x01<<i);
  50.         if(i)P0=table[KeyValue%10];
  51.         else P0=table[KeyValue/10];
  52.         i=++i%2;
  53. }

  54. void main()                                                //主函數
  55. {
  56.         while(1)
  57.         {
  58.                 key_scan();                                //按鍵掃描程序
  59.                 display();                                //數碼管顯示鍵值1~16
  60.                 delayms(1);                                //延時控制主循環周期約1ms
  61.         }
  62. }
復制代碼



回復

使用道具 舉報

5#
ID:583948 發表于 2024-12-2 09:15 | 只看該作者
#include <stdint.h>

// 假設你有一個適當的 delay 函數
void delay(uint16_t ms);

// 假設 P1 和 P1_x (x = 0, 1, 2, 3, 4, 5, 6, 7) 已經被定義并連接到相應的硬件
#define ROW_COUNT 4
#define COL_COUNT 4

// 矩陣鍵盤掃描函數
unsigned char matrix_keydown()
{
    uint8_t row, col;
    static const uint8_t rowPins[] = {P1_0, P1_1, P1_2, P1_3};
    static const uint8_t colPins[] = {P1_4, P1_5, P1_6, P1_7};
    static const uint8_t keyMap[ROW_COUNT][COL_COUNT] = {
        {1, 5, 9, 13},
        {2, 6, 10, 14},
        {3, 7, 11, 15},
        {4, 8, 12, 16}
    };

    for (row = 0; row < ROW_COUNT; ++row)
    {
        P1 = 0xFF; // 設置所有列為高電平
        rowPins[row] = 0; // 將當前行設為低電平

        for (col = 0; col < COL_COUNT; ++col)
        {
            if (colPins[col] == 0) // 檢查是否有列被拉低
            {
                delay(3); // 消抖
                while (colPins[col] == 0); // 等待按鍵釋放
                delay(3); // 消抖
                return keyMap[row][col]; // 返回按鍵值
            }
        }

        rowPins[row] = 1; // 恢復當前行為高電平,為下一行做準備
    }

    return 0; // 沒有按鍵被按下
}
可以嘗試一下這個方法,沒驗證過,
回復

使用道具 舉報

6#
ID:446156 發表于 2024-12-5 13:47 | 只看該作者
代碼量長不是問題,問題是代碼里while阻塞,這樣你的單片機再跑其他任務就非常受影響
回復

使用道具 舉報

7#
ID:1138698 發表于 2024-12-5 18:30 | 只看該作者
#ifndef MATRIX_H
#define MATRIX_H

#include "8051.h"
#include "delay.h"

unsigned char matrix_keydown() {
    unsigned char row, col;
    unsigned char key_code = 0;

    for (row = 0; row < 4; ++row) {
        P1 = 0xff; // Set all rows high
        P1_3 = (row & 0x01) ? 1 : 0; // Select row
        P1_2 = (row & 0x02) ? 1 : 0;
        P1_1 = (row & 0x04) ? 1 : 0;
        P1_0 = (row & 0x08) ? 1 : 0;

        for (col = 0; col < 4; ++col) {
            if ((P1 >> (col + 4)) & 0x01) { // Check column
                delay(3); // Debounce
                if ((P1 >> (col + 4)) & 0x01) { // Double check
                    key_code = 1 + row * 4 + col; // Calculate key code
                    while ((P1 >> (col + 4)) & 0x01); // Wait for key release
                    delay(3); // Debounce
                    return key_code;
                }
            }
        }
    }

    return 0; // No key pressed
}

#endif
這樣會好一點,你參考一下
回復

使用道具 舉報

8#
ID:752878 發表于 2024-12-6 10:05 | 只看該作者
為什么不放在定時器里去做按鍵掃描,阻塞的程序浪費資源啊,既然是優化那么實時行也是程序要考慮的點啊,不太贊同阻塞的做法
回復

使用道具 舉報

9#
ID:446156 發表于 2024-12-7 09:44 | 只看該作者
空白名 發表于 2024-12-6 10:05
為什么不放在定時器里去做按鍵掃描,阻塞的程序浪費資源啊,既然是優化那么實時行也是程序要考慮的點啊,不 ...

小伙子我看好你
回復

使用道具 舉報

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

本版積分規則

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

Powered by 單片機教程網

快速回復 返回頂部 返回列表
主站蜘蛛池模板: 亚洲精品视频网站在线观看 | 男女视频在线观看 | 成人1区 | 91在线精品秘密一区二区 | av资源中文在线 | 国产精品久久久久久久久免费丝袜 | 在线看91 | 亚洲国产高清高潮精品美女 | 9久久婷婷国产综合精品性色 | 久久精品国产一区老色匹 | 福利视频网 | 日韩视频一区二区 | 亚洲国产一区二区在线 | 亚洲精品一区中文字幕乱码 | 国产精品国产a | 精品一区二区在线观看 | 一道本在线 | 久久久久久久久久久久一区二区 | 欧美久久一区二区 | 亚洲视频三| 一区二区三区免费在线观看 | 狠狠做深爱婷婷综合一区 | 久久一区二区免费视频 | 欧美一区二区三区在线观看 | 久久久久成人精品亚洲国产 | 中文字幕国产精品 | 日本免费黄色 | 久久一区二区精品 | 免费观看www7722午夜电影 | 婷婷五月色综合 | 免费在线观看91 | 黄网站涩免费蜜桃网站 | 草久久 | 久久国产精品一区二区三区 | www中文字幕| 国产精品久久久久久久久久三级 | 欧美成年人| 欧美成人二区 | 播放一级黄色片 | 国产区精品在线观看 | 日本韩国电影免费观看 |