一、systick的使用技巧
按键可以响应了,那么怎么处理去抖呢? 包括处理长按,短按?我们上次用systick做了简单的去抖,可以在上次基础上增加长按,短按的识别。
这个操作之前,我们先把程序的文件组织方式调整下,增强程序的可读性和可维护性。
1)建立新的目录mydrivers, 新建led.c, button.c, 将led和button操作的函数都移入驱动文件
2)新建led.h, button.h头文件,将需要include的库和函数定义放入头文件
3)调整变量定义位置等
4)编译,纠错
驱动文件分离后,方便我们复用驱动和修改调试。
上次的systick程序有个bug发现么? 就是systick打印值的时候用的%d, 所以就会发现打印出来一会正数,一会负数,固定延时1000ms,应该都打印出正数啊。
这里有个printf的小知识点:
在变量值的值大于0x7FFFFFFF时,%d 格式符输出的结果会变成负数。
正确的程序应该为:
printf(“%u”, Value);
修改后的打印结果:
00> 52832 systick get value:12970321
00> 52832 systick get value:16075986
00> 52832 systick get value:2404433
00> 52832 systick get value:5510319
00> 52832 systick get value:8616077
00> 52832 systick get value:11721954
00> 52832 systick get value:14827618
00> 52832 systick get value:1156065
00> 52832 systick get value:4261953
00> 52832 systick get value:7367710
这里可以看到,固定的间隔基本在31xxxxx
也就是说1s的systick间隔在3105xxx,以这个为依据我们来设计长按,短按的时间。
但是这里发现一个前面程序的bug,就是溢出值, 开始设置的是32位整数的满值,8个F,其实查看systick相关头文件的定义,是6个F
去抖,短按,长按,就需要计数器对按键状态改变来进行计时,,我们来看看使用Timer来处理长按,短按。
定义不同的阈值
#define KEY_TRIGGER 310000 // about 0.1s
#define Long_Press 6200000 // about 2s
在程序中做分支判断:
while (true)
{
// Do Nothing - GPIO can be toggled without software intervention.
nrf_drv_systick_delay_ms(10);
if(reKeyTick>KEY_TRIGGER){
if (reKeyTick>Long_Press){
SEGGER_RTT_printf(0," pressed for long time, LED_2 toggle, %u. \r\n",reKeyTick);
nrf_drv_gpiote_out_task_trigger(LED_2);
reKeyTick=0;
}
else{
nrf_drv_gpiote_out_task_trigger(LED_1);
SEGGER_RTT_printf(0,"pressed normal , LED_2 toggle, %u. \r\n",reKeyTick);
reKeyTick=0;
}
}
}
编译下载后,三个按键短按LED1状态变化,长按LED2状态变化
二、nrf52832 定时器部分学习使用
定时器可被配置为两种模式:定时模式和计数模式。nrf52832有5个定时器,分别为timer0~time4,使用蓝牙协议栈时timer0会被占用。
其信号来源及工作模式如下图所示。
定时器分成了软件定时器和硬件定时器,其初始化、定义、创建、启动及关闭分别如下表所示。
软件定时器使用在其他例子里说明,这个试验先学习硬件定时器使用。
1.根据时钟频率自动选择时钟源,无需手动指定选择哪个时钟源。ftimer<1M时选择1M时钟,否则选择16M时钟
2.时钟频率计算,ftimer=16M/(2^分频),无论时钟源是1M还是16M都是按照16M计算。设置分频,位宽等参数时,必须先停止timer工作
3.定时模式下要设置比较/捕获的值,也就是定时时间。
说明:
nRF52840有5个定时器0,1,2有4个CC寄存器, 3,4有6个CC寄存器
定时/计数器有任务类型:
1)定时
2)计数
3)输入捕获Capture(有多少个CC就能捕获多少路信号)
4)输出比较(也是依赖CC)
5)任务定时触发
6)抢断清除任务,计数任务和停止任务
定时器有8 16 24 32位定时计数模式
我们先来看硬件定时器使用要做什么:
要在sdk_config.h中打开响应的开关
#ifndef NRFX_TIMER_ENABLED
#define NRFX_TIMER_ENABLED 1
#endif
#ifndef NRFX_TIMER0_ENABLED
#define NRFX_TIMER0_ENABLED 1
#endif
// <q> NRFX_TIMER1_ENABLED - Enable TIMER1 instance
#ifndef NRFX_TIMER1_ENABLED
#define NRFX_TIMER1_ENABLED 1
#endif
#ifndef TIMER0_ENABLED
#define TIMER0_ENABLED 1
#endif
/
然后指定handler,处理定时中断事件
void timer0_event_handler(nrf_timer_event_t event_type, void* p_context)
{
extern int32_t key_count;
switch (event_type)
{
case NRF_TIMER_EVENT_COMPARE0:
key_count+=1;
if (key_count>KEY_COUNT_LIMIT) {
key_count=0;
}
break;
default:
//Do nothing.
break;
}
}
定义初始化函数:
void timer0_init(){
uint32_t time_ms = 10; //Time(in miliseconds) between consecutive compare events.
uint32_t time_ticks;
nrf_drv_timer_config_t timer_cfg = NRF_DRV_TIMER_DEFAULT_CONFIG;
nrf_drv_timer_init(&KEY_TIMER, &timer_cfg, timer0_event_handler);
time_ticks = nrf_drv_timer_ms_to_ticks(&KEY_TIMER, time_ms);
nrf_drv_timer_extended_compare(
&KEY_TIMER, NRF_TIMER_CC_CHANNEL0, time_ticks, NRF_TIMER_SHORT_COMPARE0_CLEAR_MASK, true);
nrf_drv_timer_enable(&KEY_TIMER);
}
重新修改按键按下的处理:button.c
void BUTTON_handler(nrf_drv_gpiote_pin_t pin, nrf_gpiote_polarity_t action)
{
extern int32_t temp_count,press_count,key_count;
if (!nrf_drv_gpiote_in_is_set(pin)){
press_count=0;
temp_count=key_count;
}
else if(nrf_drv_gpiote_in_is_set(pin)){
if(key_count<temp_count){
press_count=key_count+KEY_COUNT_LIMIT-temp_count;
}
else{
press_count=key_count-temp_count;}
}
}
主函数检查计数器,区分长按短按
int main(void)
{
/* Configure board. */
led_blinking_setup();
button_setup();
timer0_init();
SEGGER_RTT_Init();
SEGGER_RTT_printf(0,"52832 SAMPLE: 1.8 check the button pressed via timer0. \r\n");
/* Toggle LEDs. */
while (true)
{
nrf_delay_ms(10);
if(press_count>10){
if(press_count>100){ // long pressed
nrf_drv_gpiote_out_task_trigger(LED_2);
SEGGER_RTT_printf(0,"long pressed. trigger LED2. \r\n");
}
else{
nrf_drv_gpiote_out_task_trigger(LED_1);
SEGGER_RTT_printf(0,"normal pressed. trigger LED1. \r\n");
}
press_count=0;
}
}
}
下载运行,RTT打印效果:
经测试,效果理想