時間觸發嵌入式系統設計模式 第19章 筆記 按鍵開關
阿新 • • 發佈:2018-11-10
時間觸發嵌入式系統設計模式 第19章 筆記 按鍵開關
E:\Nu_LB_Nuc140\Nu_LB_NUC140_BSP\SampleCode\Nu-LB-NUC140\Sched_LED_SWITCH\KEIL
程式碼:
// // GPIO_LED : GPIO output to control an on-board red LED // // EVB : Nu-LB-NUC140 // MCU : NUC140VE3CN // low-active output control by GPC12 #include <stdio.h> #include "NUC100Series.h" #include "MCU_init.h" #include "SYS_init.h" #include "scheduler.h" extern void SCH_Init(void) ; extern void SCH_Update(void) ; void SysTick_Handler(void) { SCH_Update(); } void InitSysTickClk() { SCH_Init(); SysTick->LOAD = 1000 *CyclesPerUs -1; SysTick->VAL = (0x00); NVIC_EnableIRQ(SysTick_IRQn); SysTick->CTRL = SysTick_CTRL_CLKSOURCE_Msk | SysTick_CTRL_ENABLE_Msk |SysTick_CTRL_TICKINT_Msk; } void LED_Flash_Update(void) { GPIO_TOGGLE(PC14); } void LED_Flash_UpdateD(void) { GPIO_TOGGLE(PC12); } unsigned char Sw_pressed_G = 0; // 當前的開關狀態 // ------ 私有的常數 ---------------------------------------- // 可以使用常開或常閉開關(或其他接線變化) #define SW_PRESSED (0) // 要得到正確的消抖特性,SW_THERS必須>1 #define SW_THRES (3) /*------------------------------------------------------------------*- SWITCH_Update() 這是主要的開關函式 必須每隔50~500ms排程一次 -*------------------------------------------------------------------*/ void SWITCH_Update(void) { static unsigned char Duration; static int flag = 0 ; if(PB15 == SW_PRESSED) { PC15 = 0 ; Duration += 1; if (Duration > SW_THRES) { Duration = SW_THRES; Sw_pressed_G = 1; // 開關被按下... return; }else{ printf("%d\r\n",Duration); } //開關被按下,然而時間不夠長 Sw_pressed_G = 0; flag = 1 ; return; }else{ // 開關沒有被按下-復位計數 if(flag == 1){ flag =0 ; printf("a\r\n"); } Duration = 0; Sw_pressed_G = 0; // 開關沒有被按下... PC15 = 1 ; } } /*------------------------------------------------------------------*- LED_Flash_Switch_Init() - See below. -*------------------------------------------------------------------*/ /*------------------------------------------------------------------*- LED_Flash_Switch_Update() 在指定埠引腳上閃爍LED(或產生脈衝給蜂鳴器,等等) 必須按需要的閃爍頻率的兩倍計時,這樣,對於1HZ的閃爍(0.5秒亮,0.5秒滅) 必須以2HZ計時 -*------------------------------------------------------------------*/ void LED_Flash_Switch_Update(void) { // 如果開關沒有被按下,則什麼也不做 //GPIO_TOGGLE(PC14); if (!Sw_pressed_G) { return; } GPIO_TOGGLE(PC12); } int main(void) { SYS_Init(); UART_Open(UART0, 115200); printf("Hello World \r\n"); GPIO_SetMode(PC, BIT12, GPIO_MODE_OUTPUT); GPIO_SetMode(PC, BIT14, GPIO_MODE_OUTPUT); GPIO_SetMode(PC, BIT15, GPIO_MODE_OUTPUT); GPIO_SetMode(PB, BIT15, GPIO_MODE_INPUT); InitSysTickClk(); // SCH_Add_Task(LED_Flash_Update, 0, 1000); // SCH_Add_Task(LED_Flash_UpdateD, 0, 2000); // 新增一個 'SWITCH_Update' 任務, 每隔200 ms. // 排程器定時單位為時標 // [1 ms 時間間隔 - 參見 Sch '初始化'函式] SCH_Add_Task(SWITCH_Update, 0, 200); // 新增 LED 任務 // 這裡, LED將只在開關被按下時閃爍... SCH_Add_Task(LED_Flash_Switch_Update, 5, 1000); while(1) { SCH_Dispatch_Tasks(); } }
定時器Tick 有點問題,需要仔細研究一下,
2 通斷開關
3 多狀態開關
程式碼:
/*------------------------------------------------------------------*- SWITCH_MS_Update() 這是主要的開關函式,應該每隔 50 - 500 ms排程一次. Sw_press_duration_G 的改變取決於開關按下的延續時間 -*------------------------------------------------------------------*/ void SWITCH_MS_Update(void) { if (Sw_pin == SW_PRESSED) { Sw_press_duration_G += 1; if (Sw_press_duration_G > (SW_THRES_X3)) { Sw_press_duration_G = SW_THRES_X3; Sw_status_G = 3; // 開關被按下很長時間... return; } if (Sw_press_duration_G > (SW_THRES_X2)) { Sw_status_G = 2; // 開關被按下中等時間... return; } // SW_THRES 必須 > 1 用於軟體消除抖動 if (Sw_press_duration_G > SW_THRES) { Sw_status_G = 1; // 開關被按下較短時間 ... return; } // 開關被按下,然而時間不夠長 Sw_status_G = 0; return; } // 開關沒有被按下--復位計數 Sw_press_duration_G = 0; Sw_status_G = 0; // 開關沒有被按下。。.. }
顯示狀態值
/*------------------------------------------------------------------*- COUNTER_Update() 簡單的計數函式(用於演示) -*------------------------------------------------------------------*/ void COUNTER_Update(void) { Data_G += Sw_status_G; if (Data_G > BARGRAPH_MAX) { Data_G = 0; } BARGRAPH_Update(); }