1. 程式人生 > >時間觸發嵌入式系統設計模式 第19章 筆記 按鍵開關

時間觸發嵌入式系統設計模式 第19章 筆記 按鍵開關

時間觸發嵌入式系統設計模式 第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();
   }