<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                合規國際互聯網加速 OSASE為企業客戶提供高速穩定SD-WAN國際加速解決方案。 廣告
                # 第一百一十一節: 工業自動化設備的開關信號的運動控制 ## 【111.1 開關信號的運動控制。】 ![](https://img.kancloud.cn/a2/3d/a23df87ac21f61d2182864f67461b009_359x103.png) 上圖 111.1.1 獨立按鍵 ![](https://img.kancloud.cn/68/91/6891d9a9e89ee7345b1505221de5c26b_252x282.png) 上圖 111.1.2 LED 電路 ![](https://img.kancloud.cn/89/70/8970513a066fe0726b2997dcb0329ce0_194x190.png) 上圖 111.1.3 有源蜂鳴器的電路 本節涉及的知識點有,switch 的過程控制,時間延時,開關感應器的軟件濾波,工件計數器,以及整體的軟件框架。 現在有一臺設備,水平方向有一個滑塊,能左右移動,滑塊上安裝了一個能垂直伸縮的 “機械手”。按下啟動按鍵后,滑塊先從左邊往右邊移動,移到最右邊碰到 “右感應器” 后,滑塊上的 “機械手” 開始往下移動 2 秒,移動 2 秒后開始原路返回,“機械手” 向上移動,碰到 “上感應器” 后,滑塊開始往左邊移動,移動 3 秒后默認已經回到原位最左邊,此時 “計數器” 累加 1,完成一次過程,如果再按下啟動按鍵,繼續重復這個過程。 這個設備用了 2 個氣缸。1 個 “水平氣缸” 驅動滑塊水平方向的左右移動,當控制 “水平氣缸” 的輸出信號為 0 時往左邊跑,當控制 “水平氣缸” 的輸出信號為 1 時往右邊跑。另 1 個 “垂直氣缸” 驅動 “機械手” 的上下移動,當控制 “垂直氣缸” 的輸出信號為 0 時往上邊跑,當控制 “垂直氣缸” 的輸出信號為 1 時往下邊跑。 這個設備用了 2 個開關感應器。分別是 “右感應器” 和 “上感應器”。當感應器沒有被碰到的時候信號為 1,當感應器被碰到的時候信號為 0。 這個設備用了 1 個獨立按鍵。控制運動的啟動。 2 個氣缸是輸出信號,用 P1.4 和 P1.5 所控制的兩個 LED 模擬。2 個開關感應器是輸入信號,用 K2 和 K3 這兩個獨立按鍵模擬。1 個獨立按鍵用 K1 按鍵。如上圖。 ```c #include "REG52.H" #define KEY_VOICE_TIME 50 #define KEY_FILTER_TIME 25 #define SENSOR_TIME 20 //開關感應器的“濾波”時間 void T0_time(); void SystemInitial(void); void Delay(unsigned long u32DelayTime); void PeripheralInitial(void); void BeepOpen(void); void BeepClose(void); void GoLeft(void); //“水平氣缸”往左跑 void GoRight(void); //“水平氣缸”往右跑 void GoUp(void); //“垂直氣缸”往上跑 void GoDown(void); //“垂直氣缸”往下跑 void VoiceScan(void); void SensorScan(void); //開關感應器的消抖,在定時中斷里調用處理 void KeyScan(void); void KeyTask(void); void RunTask(void); //運動控制的任務函數 sbit P1_4 = P1^4; //水平氣缸的輸出 sbit P1_5 = P1^5; //垂直氣缸的輸出 sbit P3_4 = P3^4; //蜂鳴器的輸出口 sbit KEY_INPUT1 = P2^2; //【啟動】按鍵K1的輸入口。 sbit SensorRight_sr = P2^1; //右感應器的輸入口 sbit SensorUp_sr = P2^0; //上感應器的輸入口 volatile unsigned char vGu8SensorRight = 0; //右感應器經過濾波后的當前電平狀態。 volatile unsigned char vGu8SensorUp = 0; //上感應器經過濾波后的當前電平狀態。 volatile unsigned char vGu8BeepTimerFlag = 0; volatile unsigned int vGu16BeepTimerCnt = 0; volatile unsigned char vGu8KeySec = 0; unsigned char Gu8RunStart = 0; //啟動的總開關 unsigned char Gu8RunStatus = 0; //運動的狀態,0為停止,1為運行 unsigned int Gu16RunCnt = 0; //計數器 unsigned int Gu16ReturnLeftTime = 3000; //水平往左跑的延時變量,默認為3秒 unsigned int Gu16GoDownTime = 2000; //垂直往下跑的延時變量,默認為2秒 volatile unsigned char vGu8RunTimerFlag = 0; //用于控制運動過程中的延時的定時器 volatile unsigned int vGu16RunTimerCnt = 0; void main() { SystemInitial(); Delay(10000); PeripheralInitial(); while (1) { KeyTask(); //按鍵的任務函數 RunTask(); //運動控制的任務函數 } } /* 注釋一: * 兩個“計時器”相互“清零”相互“抗衡”,從而實現了開關感應器的“消抖”處理, * 專業術語也叫“軟件濾波”。這種濾波方式,不管是從“高轉成低”,還是“低轉成高”, * 如果在某個瞬間出現干擾抖動,某個計數器都會及時被“清零”,從而起到非常高效的消抖濾波作用。 */ void SensorScan(void) //此函數放在定時中斷里每1ms掃描一次,用來識別和濾波開關感應器 { static unsigned int Su16SensorRight_H_Cnt = 0; //判斷高電平的計時器 static unsigned int Su16SensorRight_L_Cnt = 0; //判斷低電平的計時器 static unsigned int Su16SensorUp_H_Cnt = 0; //判斷高電平的計時器 static unsigned int Su16SensorUp_L_Cnt = 0; //判斷低電平的計時器 //右感應器的濾波 if (0 == SensorRight_sr) { Su16SensorRight_H_Cnt = 0; //在判斷低電平的時候,高電平的計時器被清零,巧妙極了! Su16SensorRight_L_Cnt++; if (Su16SensorRight_L_Cnt >= SENSOR_TIME) { Su16SensorRight_L_Cnt = 0; vGu8SensorRight = 0; //此全局變量反饋經過濾波后“右感應器”當前電平的狀態 } } else { Su16SensorRight_L_Cnt = 0; //在判斷高電平的時候,低電平的計時器被清零,巧妙極了! Su16SensorRight_H_Cnt++; if (Su16SensorRight_H_Cnt >= SENSOR_TIME) { Su16SensorRight_H_Cnt = 0; vGu8SensorRight = 1; //此全局變量反饋經過濾波后“右感應器”當前電平的狀態 } } //上感應器的濾波 if (0 == SensorUp_sr) { Su16SensorUp_H_Cnt = 0; Su16SensorUp_L_Cnt++; if (Su16SensorUp_L_Cnt >= SENSOR_TIME) { Su16SensorUp_L_Cnt = 0; vGu8SensorUp = 0; //此全局變量反饋經過濾波后“上感應器”當前電平的狀態 } } else { Su16SensorUp_L_Cnt = 0; Su16SensorUp_H_Cnt++; if (Su16SensorUp_H_Cnt >= SENSOR_TIME) { Su16SensorUp_H_Cnt = 0; vGu8SensorUp = 1; //此全局變量反饋經過濾波后“上感應器”當前電平的狀態 } } } void T0_time() interrupt 1 { VoiceScan(); KeyScan(); SensorScan(); //用來識別和濾波開關感應器 if (1 == vGu8RunTimerFlag && vGu16RunTimerCnt > 0) //用于控制運動延時的定時器 { vGu16RunTimerCnt--; } TH0 = 0xfc; TL0 = 0x66; } void SystemInitial(void) { TMOD = 0x01; TH0 = 0xfc; TL0 = 0x66; EA = 1; ET0 = 1; TR0 = 1; } void Delay(unsigned long u32DelayTime) { for (; u32DelayTime > 0; u32DelayTime--) ; } void PeripheralInitial(void) { //上電初始化氣缸的開機位置 GoLeft(); //“水平氣缸”往左跑,上電初始化時滑塊處于左邊 GoUp(); //“垂直氣缸”往上跑,上電初始化時“機械臂”處于上方 } void BeepOpen(void) { P3_4 = 0; } void BeepClose(void) { P3_4 = 1; } void GoLeft(void) //“水平氣缸”往左跑 { P1_4 = 0; } void GoRight(void) //“水平氣缸”往右跑 { P1_4 = 1; } void GoUp(void) //“垂直氣缸”往上跑 { P1_5 = 0; } void GoDown(void) //“垂直氣缸”往下跑 { P1_5 = 1; } void VoiceScan(void) { static unsigned char Su8Lock = 0; if (1 == vGu8BeepTimerFlag && vGu16BeepTimerCnt > 0) { if (0 == Su8Lock) { Su8Lock = 1; BeepOpen(); } else { vGu16BeepTimerCnt--; if (0 == vGu16BeepTimerCnt) { Su8Lock = 0; BeepClose(); } } } } void KeyScan(void) //此函數放在定時中斷里每1ms掃描一次 { static unsigned char Su8KeyLock1; static unsigned int Su16KeyCnt1; //【啟動】按鍵K1的掃描識別 if (0 != KEY_INPUT1) { Su8KeyLock1 = 0; Su16KeyCnt1 = 0; } else if (0 == Su8KeyLock1) { Su16KeyCnt1++; if (Su16KeyCnt1 >= KEY_FILTER_TIME) { Su8KeyLock1 = 1; vGu8KeySec = 1; //觸發1號鍵 } } } /* 注釋二: * 在KeyTask中只改變Gu8RunStart的值,用于總啟動開關。而運動狀態Gu8RunStatus是在運動函數 * RunTask中改變,用于對外反饋實時的運動狀態。 */ void KeyTask(void) //按鍵的任務函數,放在主函數內 { if (0 == vGu8KeySec) { return; //按鍵的觸發序號是0意味著無按鍵觸發,直接退出當前函數,不執行此函數下面的代碼 } switch (vGu8KeySec) //根據不同的按鍵觸發序號執行對應的代碼 { case 1: // 1號按鍵。【啟動】按鍵K1 if (0 == Gu8RunStatus) //根據當前運動的狀態來決定“總開關”是否能受按鍵的控制 { Gu8RunStart = 1; //總開關“打開”。 } vGu8BeepTimerFlag = 0; vGu16BeepTimerCnt = KEY_VOICE_TIME; //觸發按鍵后,發出固定長度的聲音 vGu8BeepTimerFlag = 1; vGu8KeySec = 0; //響應按鍵服務處理程序后,按鍵編號必須清零,避免一直觸發 break; default: vGu8KeySec = 0; //響應按鍵服務處理程序后,按鍵編號必須清零,避免一直觸發 break; } } /* 注釋三: * 本節故意引入三個變量:計數器Gu16RunCnt,左延時Gu16ReturnLeftTime,下延時Gu16GoDownTime。 * 在人機界面的場合,這三個變量可以用來擴展實現設置參數的功能。比如,如果有數碼管,可以通過 * 顯示Gu16RunCnt的數值來讓客戶看到當前設備的計數器。如果有數碼管和按鍵,可以通過切換到某個 * 界面下,修改Gu16ReturnLeftTime和Gu16GoDownTime的數值,讓客戶對設備進行延時參數的設置。 */ void RunTask(void) //運動控制的任務函數,放在主函數內 { static unsigned char Su8RunStep = 0; //運行的步驟 //當總開關處于“停止”并且“步驟不為0”時,強制把步驟歸零。 if (0 != Su8RunStep && 0 == Gu8RunStart) { Su8RunStep = 0; //步驟歸零 } switch (Su8RunStep) //屢見屢愛的switch又來了 { case 0: if (1 == Gu8RunStart) //總開關“打開” { Gu8RunStatus = 1; //及時設置Gu8RunStatus的運動狀態為“運行” GoRight(); //“水平氣缸”往右跑。P1.4的LED燈“滅”。 Su8RunStep = 1; //切換到下一步 } break; case 1: if (0 == vGu8SensorRight) //直到碰到了“右感應器”(按下K2),“機械臂”才往下移動。 { GoDown(); //“垂直氣缸”往下跑。P1.5的LED燈“滅”。 vGu8RunTimerFlag = 0; vGu16RunTimerCnt = Gu16GoDownTime; //向下移動3秒的延時賦值 vGu8RunTimerFlag = 1; //啟動定時器 Su8RunStep = 2; //切換到下一步 } break; case 2: if (0 == vGu16RunTimerCnt) //當定時的3秒時間到,“機械臂”才往上移動,開始原路返回。 { GoUp(); //“垂直氣缸”往上跑。P1.5的LED燈“亮”。 Su8RunStep = 3; //切換到下一步 } break; case 3: if (0 == vGu8SensorUp) //直到碰到了“上感應器”(按下K3),滑塊才往左移動。 { GoLeft(); //“水平氣缸”往左跑。P1.4的LED燈“亮”。 vGu8RunTimerFlag = 0; vGu16RunTimerCnt = Gu16ReturnLeftTime; //向左移動2秒的延時賦值 vGu8RunTimerFlag = 1; //啟動定時器 Su8RunStep = 4; //切換到下一步 } break; case 4: if (0 == vGu16RunTimerCnt) //當定時的2秒時間到,完成一次過程。 { Gu16RunCnt++; //計數器加1,統計設備運行的次數 Gu8RunStatus = 0; //及時設置Gu8RunStatus的運動狀態為“停止” Gu8RunStart = 0; //總開關“關閉”,為下一次啟動作準備 Su8RunStep = 0; //步驟變量清零,為下一次啟動作準備 } break; } } ```
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看