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

 找回密碼
 立即注冊

QQ登錄

只需一步,快速開始

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

單片機--放下Delay,立地成佛

[復制鏈接]
跳轉到指定樓層
樓主
ID:59284 發表于 2014-2-26 19:29 | 只看該作者 回帖獎勵 |倒序瀏覽 |閱讀模式
最近通過專業綜合實驗接觸單片機編程。對歷程中的Delay函數有所疑問,最終在大神們的幫助下解決。寫了筆記備忘一下。

問題的出現:不管是郭天祥的單片機教程,還是開發板配套資料,都會用到類似函數來完成延時:
void Delay(unsigned int t)
{                             
unsigned int k;
while(t--)
{
for(k=0; k<80; k++)
;
}
}

例如在按鍵檢測中,線delay一會兒來完成去抖動,檢測按下后再delay一會兒來完成等待彈起。再比如在數碼管顯示中,控制第一個數碼管顯示,delay一會再控制第二個,否則就會導致整個數碼管都被刷亮,一直顯示8。再比如步進電機控制,先發110000再發011000之間用delay來控制轉速,delay的久轉的慢。

但是如果需要程序通過按鍵來控制步進電機的速度,同時將控制參數顯示在數碼管上。這時問題就出現了:在檢測按鍵的時候電機不轉了,數碼管也不現實了,因為CPU在delay,在做沒有用的空運算。同樣的,控制電機轉的時候數碼管也不亮了,按鍵也不能檢測了。控制數碼管也是同理。可見歷程中每個模塊的代碼都是不可復用的,不可擴展的。那么怎么寫出可復用、可擴展的單片機程序呢。

問題的解決:先把這種方法起個名字就叫帶計數的輪詢模式吧。
    CPU.h中:
    unsigned int CPU_Count = 0;  //全局變量CPU循環計數
    main.cpp中:
    #include "CPU.h"
    #include "...  //其他設備控制
    void main()
    {
         while(1)
         {
              CPU_Count ++ ;


              ProcessingMotor(); //電機控制

              ProcessingLED();   //LED顯示

              ProcessingKey();   //按鍵檢測
         }   
    }


下面看具體的ProcessingMotor的實現。
    在Motor.h中
    #define GPIO_MOTOR P1
    unsigned char code FFW[8]={0xf1,0xf3,0xf2,0xf6,0xf4,0xfc,0xf8,0xf9}; //反轉順序
    unsigned char code FFZ[8]={0xf9,0xf8,0xfc,0xf4,0xf6,0xf2,0xf3,0xf1}; //正轉順序
    unsigned char Direction,Speed;
    void  Motor()
    {
if(Speed == 0)
return;
if(CPU_Count%Speed == 0)
{
if(Direction==1)
GPIO_MOTOR = FFW[(CPU_Count/Speed)%8]&0x1f;  //取數據
if(Direction==2)
GPIO_MOTOR = FFZ[(CPU_Count/Speed)%8]&0x1f;
}                 
     }

我們可以通過CPU_Count%Speed==0來控制while循環幾次來進行一次脈沖發送,同時可以通過(CPU_Count/Speed)%8的值來得到該發地幾個波了。這樣CPU就可以得到充分的利用。

LED的控制也是類似,這里就不再贅述。


可復用可擴展的按鍵檢測
其實按鍵檢測關鍵就在兩個地方,一個是按鍵接在哪個引腳上,一個是按鍵按下應該響應那個函數。如果我們能通過一些后臺機制,最終實現一個接口:connectButton(uchar PX,uchar PMask,(*SLOT)());以后再需要用到按鍵的檢測,只需要寫一個按鍵按下對應的函數,并調用connectButton即可。

那么怎么樣實現這樣一個借口呢?

首先我們使用這樣一種檢測按鍵的方法。在CPU的while循環中每次都去讀按鍵的狀態,如果按鍵按下測PressCount++;如果按鍵沒有按下則unPressCount++;在pressCount加到一個臨界值說明按鍵按下,同時將unPressCount清零。unPressCount加到一個臨界值,說明按鍵彈起,將pressCount清零。

下面是代碼實現:
     typedef void(*SLOT)();
     #define B_CNT 4
     unsigned char listSize = 0;
     typedef struct ButtonNode
     {
unsigned char isPressed;    //是否被按下
unsigned char px; // 標記P0等
unsigned char pmask;    // 標記P0等第幾個管腳
unsigned int pressCount; //cpu一次輪轉中,如果被按下則加一
unsigned int unPressCount; //cpu一次輪轉中,如果彈起則加一
SLOT func;                      //回調函數
      }ButtonNode;
      ButtonNode Button[B_CNT]

這里用的是結構體的數組來保存需要的檢測的按鍵,其實最好用鏈表動態申請空間,因為用鏈表才能真正實現開閉性,不用對代碼做任何修改。而我們這里為了節約內存,每次都要修改檢測的按鍵個數B_CNT。

然后實現ProcessingKey,對保存的按鍵信息進行循環檢測。
void ProcessingKey()
{
unsigned char num = CPU_Count%BUTTON_NUM;
unsigned char p;
if( num >= listSize)
return;
switch (Button[num].px)
       {
        case P0_X:
            p = P0;
        break;
        case P1_X:
             p = P1;
        break;
        case P2_X:
            p = P2;
        break;
        case P3_X:
            p = P3;
        break;
    }
if(!((p >> Button[num].pmask) & 1))
{
Button[num].pressCount ++ ;
if(Button[num].pressCount==150)
{
Button[num].pressCount=0;
if(Button[num].isPressed==0)
{
Button[num].func();
Button[num].isPressed = 1;
Button[num].unPressCount=0;
}
}
}else
{
Button[num].unPressCount ++;
if(Button[num].unPressCount==150)
{
Button[num].unPressCount=0;
if(Button[num].isPressed==1)
{
Button[num].isPressed = 0;
Button[num].pressCount=0;
}
}
}
    }

這里我們使用150次作為臨界值。

最后我們來實現最想要的接口connectButton:
void connectButton(unsigned char _px,unsigned char _pmask,SLOT _func)
{
Button[listSize].isPressed = 0;
Button[listSize].px = _px;
Button[listSize].pmask = _pmask;
Button[listSize].pressCount = 0;
Button[listSize].unPressCount = 0;
Button[listSize].func = _func;
listSize ++;
     }
大功告成。該enjoy it了。
以后我們的單片機程序要使用某個按鍵按下執行一些內容時,只需要這樣
實現按下后的響應
void onP3_0Pressed(){  ...  }
調用connectButton(P3_X,0,onP3_0Pressed)
只要你使用的是計數輪詢模式,那么按鍵檢測就可以直接實現了。

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

使用道具 舉報

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

本版積分規則

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

Powered by 單片機教程網

快速回復 返回頂部 返回列表
主站蜘蛛池模板: 九九免费在线视频 | 国产黄色大片在线免费观看 | 日韩免费一区二区 | 日日拍夜夜 | 亚洲综合久久久 | 亚洲国产免费 | 欧美日韩在线免费观看 | 精品欧美一区二区久久久伦 | 午夜免费视频 | 国产 日韩 欧美 在线 | 天天综合成人网 | 国产色在线 | 亚洲一区二区三区观看 | 日韩高清一区二区 | 国产精品视频在线观看 | 国产黄色精品在线观看 | 国产亚洲一区二区在线观看 | 欧美a∨ | 成人精品毛片 | 久久夜色精品国产 | 亚洲精品欧美一区二区三区 | 9999国产精品欧美久久久久久 | 欧美激情一区二区三区 | 在线欧美亚洲 | 一区二区三区四区在线视频 | 91视频亚洲 | 97人人超碰 | 久久国产精品视频免费看 | 91伊人| 中文字幕成人av | 日韩欧美在线视频 | 欧美不卡一区二区三区 | 99av成人精品国语自产拍 | aaa综合国产 | 欧美乱操 | 日本精品久久 | 欧洲一区二区三区 | 中文字幕在线国产 | 日韩在线不卡 | 亚洲精品区 | 羞羞视频在线观免费观看 |