ble开发-按键启动控制LED与简易蓝牙数据发送
小白初次接触ble开发,网上相关教程较为复杂混乱,因此在此系统讲解ble开发相关流程并记录本人开发过程,有何错误欢迎评论指正。
嵌入式学习第一步,点个灯先
嵌入式学习第二步,搞个按键
嵌入式学习第三步,按键点个灯
1.本工程所使用SDK为伦茨官方提供按键例程
伦茨17Hxx开发文档中ST17H66_SDK_3.1.1.2_key工程
2.本工程按键部分代码已基本实现,接下来阐述一下按键实现的具体流程
请首先参考其他文献对OSAL系统有初步了解,以方便进一步理解。首先是按键初始化,定义引脚状态并使能与注册中断。当按键按下后进入中断 user_key_handler
void userKey_Init(uint8 task_id) { userKeyTaskID = task_id; hal_gpio_pin_init(P0, GPIO_OUTPUT);//P0为输出状态 hal_gpio_pull_set(P0, PULL_DOWN);//下拉
hal_gpio_pin_init(P24, GPIO_OUTPUT);//P24为LED hal_gpio_pull_set(P0, PULL_DOWN); hal_gpio_pin_init(PIN_TOUCH_KEY, IE);//P14为输入状态 hal_gpio_pull_set(PIN_TOUCH_KEY, STRONG_PULL_UP);//上拉 hal_gpioin_enable(PIN_TOUCH_KEY);//使能中断 hal_gpioin_register(PIN_TOUCH_KEY, NULL,user_key_handler);//注册中断处理#endif }
中断 user_key_handler,其主要功能为当触发中断是开启按键任务中的按键扫描事件
void __ATTR_SECTION_SRAM__ __attribute__((used)) user_key_handler(gpio_pin_e pin,gpio_polarity_e type) { if(pin == PIN_TOUCH_KEY) { hal_gpioin_register(PIN_TOUCH_KEY, NULL, NULL); hal_gpioin_register(PIN_TOUCH_KEY1, NULL, NULL); key_time_timeout = KEY_TIMEOUT_MAX; osal_start_timerEx(userKeyTaskID, USER_KEY_SCAN_EVT, KEY_SCAN_INTERVAL); //启动KEY_SCAN_INTERVAL事件
KEY_SCAN_INTERVAL
} }
按键扫描事件,其主要功能为调用key_scan()函数
if(events & USER_KEY_SCAN_EVT) { key_scan(); return (events ^USER_KEY_SCAN_EVT); }
key_scan()函数主要功能即为按键扫描,包括长按、短按、连续按。当任务没超时即!key_time_timeout 时继续执行扫描事件,超时后便将引脚重新赋予中断(超时即长时间未按下按键)并且不在执行本任务。当按键按下后我们可以添加按键触发动作执行相关程序。其内容在key_do()函数中。
void key_scan( { static uint8 key_last_val; static uint32 key_release_tick,key_press_tick; static uint32 key_short_cnt,key_long_time_cnt; uint8 key_cur_val = get_cur_key(P14,P0); //LOG("P0:%d P14:%d",hal_gpio_read(P0),hal_gpio_read(P14)); if(key_cur_val != key_last_val) { if(key_cur_val) { //按下 key_time_timeout = KEY_TIMEOUT_MAX; key_press_tick = rtc_get_counter(); key_long_time_cnt = 0; LOG("Key_Down"); key_do(0,1); } else {//松开 key_release_tick = rtc_get_counter(); uint32 key_tick_diff = key_release_tick > key_press_tick? (key_release_tick-key_press_tick):0; LOG("Key_press"); key_do(0,2); if(key_tick_diff && (key_tick_diff< RTC_nMs(350)&& (key_tick_diff > RTC_nMs(20)))) { key_short_cnt++;//连按次数 if( key_short_cnt >= 2) { key_do(0,3); } static int last_tick; // LOG("\n %8d tick = %8d dif= %8d",key_short_cnt, (key_release_tick*1000/32768), (key_release_tick-last_tick)*1000/32768); last_tick = key_release_tick; } } key_last_val = key_cur_val; } else { if(key_cur_val) {//长按 key_time_timeout = KEY_TIMEOUT_MAX; if(key_long_time_cnt < 254) { key_long_time_cnt++; // LOG("S"); if(key_long_time_cnt == (2200/50)) { } if(key_long_time_cnt == (6200/50)) { } } } else { } } if(key_time_timeout) { key_time_timeout--; if(key_time_timeout == (KEY_TIMEOUT_MAX-6)) { } if(key_time_timeout ==0) { key_short_cnt = 0; hal_gpioin_register(PIN_TOUCH_KEY, NULL,user_key_handler); } osal_start_timerEx(userKeyTaskID, USER_KEY_SCAN_EVT, KEY_SCAN_INTERVAL); } }
key_do(),本函数即为按键动作,所需按键功能可在本函数中进行编写。其中P24引脚为LED引脚,可通过其实现对LED的控制。sbpSerialAppSendNoti(a,3)为蓝牙发送,通过次函数蓝牙可发送长度为3的数据123到安卓端。对本函数的讲解留到之后,到此按键点灯功能实现。
void key_do(uint8 key_val,uint8 key_state)//按键执行事件 { if(key_val==0&&key_state==1) { hal_gpio_pull_set(P24,STRONG_PULL_UP);//点亮LED } if(key_val==0&&key_state==2) { hal_gpio_pull_set(P24,PULL_DOWN);//熄灭LED } if(key_val==0&&key_state==3) { if( get_ble_state()==GAPROLE_CONNECTED) { uint8 a[3]={1,2,3}; LOG("ble_send:%s",a); sbpSerialAppSendNoti(a,3); } } }
串口接收到的数据如下。
蓝牙接收到的数据如下