首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> 關於C語言

單片機編碼器掃描驅動程序:正反轉檢測與按鍵復位實現

     編輯:關於C語言

項目背景

本代碼實現單片機(可能為 STC/8051 系列)下的增量式旋轉編碼器掃描驅動。包含:

  • A/B 相正交信號解碼(判斷正/反轉)
  • 按鍵(C 相)長按復位計數器
  • 去抖動延時處理
  • 計數值顯示接口

硬件接口定義


// 編碼器 A 相 -> P4.2,需外接 680Ω 上拉電阻
sbit BMA = P4^2;
// 編碼器 B 相 -> P4.3,需外接 680Ω 上拉電阻
sbit BMB = P4^3;
// 編碼器公共端 -> 接地
// 編碼器按鍵 (C 相) -> P1.6
sbit BMC = P1^6;

unsigned int counter = 0;  // 編碼器脈衝計數值

正交編碼原理

增量式編碼器輸出 A、B 兩路相位差 90° 的方波:

方向AB狀態序列
正轉 (CW)1→0→0→11→1→0→011 → 10 → 00 → 01 → 11...
反轉 (CCW)11 → 01 → 00 → 10 → 11...

核心邏輯:從 `00` 狀態出發,檢測下一狀態:

  • `01` → 正轉,計數 +1
  • `10` → 反轉,計數 -1
  • `11` → 異常(抖動/干擾),忽略

核心掃描函數解析


void scan_encoder(void) {
    unsigned int i;

    while (1) {
        // 等待穩定在 00 狀態
        if (BMA == 0 && BMB == 0) {
            // 去抖動延時:若持續 00 則繼續等待
            for (i = 0; i < 0xFFF0; i++) {
                if (BMA == 0 && BMB == 0) {
                    yans(1);  // 微秒級延時
                } else if (BMA == 0 && BMB == 1) {  // 01 -> 正轉
                    counter++;
                    return;
                } else if (BMA == 1 && BMB == 0) {  // 10 -> 反轉
                    counter--;
                    return;
                }
                // 若變為 11,for 循環自然結束,外層 while 重新檢測
            }
        }
        // 按鍵檢測:低電平有效,復位計數器
        else if (BMC == 0) {
            counter = 0;
            return;
        }
        // 其他狀態:直接返回,等待下次掃描
        else {
            return;
        }
    }
}

關鍵設計點分析

1. 狀態機設計

採用「等待 00 → 延時檢測轉移」的簡易狀態機,避免複雜的狀態表,資源佔用極小。

2. 去抖動策略

  • 外層 `while(1)` 配合內層 `for` 循環實現「等待穩態」
  • `yans(1)` 提供微秒級延時,總延時約 65ms(`0xFFF0` 次),可根據機械特性調整
  • 若轉動極快,可減小循環上限;極慢則增大

3. 按鍵復位優先級

編碼器處理優先於按鍵檢測。若需按鍵最高優先級,應將 `BMC` 判斷前置。

4. 計數器類型

`unsigned int` 16 位,範圍 0~65535。長時間運行需考慮溢出處理或改用 `unsigned long`。

顯示與主循環


// 顯示計數值(假設 LCD/數碼管驅動)
void xszs(void) {
    unsigned int code db[] = {0, 0};
    fsfont55();       // 設置字體
    fsszxy(4, db);    // 設置坐標
    printf("%5u\n", counter);  // 輸出 5 位無符號整數
    txjs();           // 刷新顯示
}

// 主程序
void testmain(void) {
    yans(3000);       // 上電延時 3秒,等待外設穩定
    while (1) {
        xszs();       // 刷新顯示
        scan_encoder(); // 掃描編碼器
    }
}

優化建議

  1. 中斷驅動:將 A/B 相接外部中斷腳,邊沿觸發讀取另一相,零 CPU 佔用、零抖動
  2. 查表法解碼:預計算 4 狀態轉移表,`state = (state << 2) | (A<<1|B); counter += table[state & 0xF];`
  3. 硬件去抖動:RC 濾波或施密特觸發器
  4. 計數器原子性:主循環讀取 `counter` 時關中斷,或使用雙緩衝
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved