版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/wowocpp/article/details/83012566
时间触发嵌入式系统设计模式 第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();
}