目录
- 项目介绍
- 硬件介绍
- 项目设计
- 开发环境
- 总体流程图
- BLE HID
- 触摸按键与滑条
- 功能展示
- 项目总结
👉 【Funpack4-1】基于CY8CKIT-149 BLE HID设备实现及PC控制功能开发
👉 Github: EmbeddedCamerata/CY8CKIT-149_ble_hid_keyboard
项目介绍
基于英飞凌 CY8CKIT-149 开发板,通过 BLE HID 实现了一个蓝牙键盘设备,可通过蓝牙与 PC 连接,通过板载的触摸按键与滑条实现对 PC 音量、亮度、翻页控制:触摸按键 BTN0/1 控制亮度+/-、BTN2 音量+;触摸滑条左/右滑动控制上/下翻页。
硬件介绍
CY8CKIT-149 是 PSoC™ 4100S Plus 原型开发套件,用户能够通过该款板卡来评估 PSoC™ 4100S Plus 器件。 PSoC™ 4100S Plus 器件是英飞凌的 PSoC™ 4,具有一个 Arm Cortex-M0+ 内核和高达 128KB 闪存、16KB SRAM、9 个可编程模拟块、13 个可编程数字块以及 54 个通用 I/O,包括 24 个智能 I/O。
它还采用英飞凌第四代低功耗 CAPSENSE™ 解决方案,超可靠的低功耗电容式感应解决方案,可在嘈杂环境和液体中“正常工作”。 该套件使您能够使用两块电容式电路板快速评估和开发 CAPSENSE™,其中一块具有三个电容式按钮,另一块具有一个六段电容式滑块,这两块电路板都能够对按钮进行自电容式感应和互电容式感应。
项目设计
开发环境
本项目需要为 MCU 与 蓝牙模组两个模块编程。由于要用到板卡上较老的蓝牙模块,用英飞凌的 ModusToolbox 无法对其进行编程,因此只能使用老的 PSoC Creator 开发。
总体流程图
MCU 与蓝牙模块通过 EZI2C 通信,MCU 作为从设备,通过在循环中解码滑条的手势、扫描触摸按键,将信息保存在 buffer 中。使用现成的示例程序,蓝牙模组将作为 BLE HID 键盘设备连接 PC,通过读取相应 I2C buffer,获取触摸按键与滑条手势的按下信息,通过预先设定的 PC 亮度、音量、上下翻页的快捷键编码为 HID 报告发送至 PC。
BLE HID
参考 CYBLE-022001-00 的 BLE HID Keyboard 示例,在硬件模块中添加 I2CHW 用于读取按键信息寄存器,读取的从设备地址为 0x08,引脚设置如下:
PIN | 功能 |
---|---|
P5[1] | SCL |
P5[0] | SDA |
BLE HID 硬件模块" width="500" />
该示例已经实现了一个 BLE HID 键盘设备(其余无关模块可根据需求移除)。在初始化阶段,使用库函数初始化 I2C 设备,并在主循环中读取寄存器并根据对应信息发送对应的操作的 HID 报告即可。读取的 I2C 寄存器 0 位为滑条手势信息,0x54/0x5c 表示左/右滑动(从设备约定),第 2 位 uint8 BIT 0/1/2 分别代表触摸按键 0/1/2 是否按下。
#define SLIDER_GESTURE_INDEX (0u)
#define BUTTON_COUNT_INDEX (1u)
#define BUTTON_STATUS_INDEX1 (2u)
#define BUTTON_STATUS_INDEX2 (3u)
#define SLIDER_FLICK_RIGHT (0x54u)
#define SLIDER_FLICK_LEFT (0x5Cu)
/* I2C buffer for storing the data read from I2C slave device */
uint8 i2cBuffer[] = {0, 0, 0, 0};int main()
{CyGlobalIntEnable; .../* Begin I2C master component operation */I2CHW_Start();...while(1) { /* CyBle_ProcessEvents() allows BLE stack to process pending events */CyBle_ProcessEvents();/* To achieve low power in the device */LowPowerImplementation();if((CyBle_GetState() == CYBLE_STATE_CONNECTED) && (suspend != CYBLE_HIDS_CP_SUSPEND)){ ...if((CyBle_GetBleSsState() == CYBLE_BLESS_STATE_ECO_STABLE) &&(keyboardSimulation == ENABLED)){/*Check for CapSense data change and report to BLE central device*/HandleCapSense();}...
其中,HandleCapSense()
实现对寄存器读取、发送 HID 设备报告:
void HandleCapSense(void)
{static uint8 sliderGesture = 0;static uint8 buttonValue = 0; static uint8 prevButtonStat = 0;/* Read entire data buffer from the slave device */I2CHW_I2CMasterReadBuf(I2C_SLAVE_ADDRESS, i2cBuffer, I2C_BUF_SIZE, I2CHW_I2C_MODE_COMPLETE_XFER); while (0u == (I2CHW_I2CMasterStatus() & I2CHW_I2C_MSTAT_RD_CMPLT)){CyBle_ProcessEvents();}sliderGesture = i2cBuffer[SLIDER_GESTURE_INDEX];DBG_PRINTF("Slider moved: %u \r\n", sliderGesture);if(sliderGesture == SLIDER_FLICK_LEFT){SendPageCtrl(1u); // page up}else if(sliderGesture == SLIDER_FLICK_RIGHT){SendPageCtrl(0u); // page down}buttonValue = i2cBuffer[BUTTON_STATUS_INDEX1];if(prevButtonStat != buttonValue){DBG_PRINTF("Button moved: %u -> %u\r\n", prevButtonStat, buttonValue);prevButtonStat = buttonValue;if(buttonValue & 0x01) // btn0{SendLightCtrl(1u); // light brighter}if(buttonValue & 0x02) // btn1{SendLightCtrl(0u); // light lower}if(buttonValue & 0x04) // btn2{SendSoundCtrl(1u); // sound higher}}
}
在示例中,参考 hids.c
中定义的 SimulateKeyboard()
即可实现发送一次 HID 设备报告的功能。PC 快捷键对应的功能如下,根据这些键位即可实现上述代码中的 SendPageCtrl()
、SendLightCtrl()
、SendSoundCtrl()
。
快捷键 | 功能 |
---|---|
F2 | 音量- |
F3 | 音量+ |
F5 | 亮度- |
F6 | 亮度+ |
Page Up | 向上翻页 |
Page Down | 向下翻页 |
触摸按键与滑条
参考 PSoC 4100S Plus CapSense 与 蓝牙模块 CapSense Linear Slider and Buttons 的 MCU 端示例程序,在硬件模块中添加 EZI2C 模块作为从设备,地址设置为 0x08(与主设备读取的地址保持一致)。几个 LED 灯用于指示触摸按键按下与滑动动作。在 CapSense 模块中,设置三个按键与滑条,BTN0/1/2_Tx 均设置为 BTN0_Tx;在“Gesture”栏中打开“One-finger Flick”以检测滑条左右滑动手势,其余设置保持默认即可。
CapSense 硬件模块" width="500" />
引脚设置如下:
初始化阶段,额外初始化 EZI2C 需写入的 buffer:
#define GESTURE_TIMEOUT (180u)
uint8 i2cBuffer[] = {0,3,0,0};int main(void)
{.../* Set up communication data buffer with CapSense slider centroid position and button status to be exposed to EZ-BLE Module on CY8CKIT-149 PSoC 4100S Plus Prototyping Kit */EZI2C_EzI2CSetBuffer1(sizeof(i2cBuffer), sizeof(i2cBuffer), i2cBuffer);CapSense_ScanAllWidgets();...
在主循环中,检测滑条手势与触摸按键,并保存至 buffer 中:
for(;;)
{ /* Checks to make sure that the scan is done before processing data */if(CapSense_NOT_BUSY == CapSense_IsBusy()){ .../* Stores the current detected gesture */detectedGesture = CapSense_DecodeWidgetGestures(CapSense_LINEARSLIDER0_WDGT_ID);/* Turns a specific LED on or off depending on the gesture */if((detectedGesture == CapSense_ONE_FINGER_FLICK_RIGHT) || (detectedGesture == CapSense_ONE_FINGER_FLICK_LEFT)){gestureDetected = 1;cnt = 0;i2cBuffer[SLIDER_GESTURE_INDEX] = (uint8) detectedGesture;...}if(gestureDetected == 1){if(cnt >= GESTURE_TIMEOUT){gestureDetected = 0;cnt = 0;i2cBuffer[SLIDER_GESTURE_INDEX] = (uint8) CapSense_NO_GESTURE;}cnt++;}/* Calculate the button status mask and update the I2C bufferbit0= BTN0 status, bit1 = BTN1 status, bit2 = BTN2 status */for(widgetID = 0; widgetID < TOTAL_CAPSENSE_BUTTONS; widgetID++){if(CapSense_IsWidgetActive(widgetID)){SET_BIT(buttonStatus, widgetID);}else{CLEAR_BIT(buttonStatus, widgetID);}} i2cBuffer[BUTTON_STATUS_INDEX1] = buttonStatus;...}
}
当读到一次左/右滑动手势后,BLE HID 会发送对应快捷键。若在手指离开后的下次键盘扫描后未复位为“无动作”,则 BLE HID 端仍会解码为左/右滑动,这导致操作会变为“左左左左左右右右右右左左左……”,显然是不合理的。因此,需在识别到左/右滑动后随即将 buffer 对应位复位为“无动作”。但是,由于 MCU 侧无法知道何时 BLE HID 读取到此次的动作,且 I2C 速率只有400k,若立刻复位,可能会导致 BLE HID 无法读取到有效动作。
一种解决方法是在 BLE HID 端读取到一次有效动作后复位对应 buffer,但这样依然要求 MCU 需要适时地为 buffer 复位“无动作”,难以控制。另一种方案是仅在 MCU 侧让有效的左右滑动动作持续一段时间后再复位“无动作”,这样虽会导致左右滑动动作被连续多次识别,且左、右滑动动作的切换存在间隔,但可确保 BLE HID 准确识别到动作。用一计数器记录有效手势的持续时间,当达到 GESTURE_TIMEOUT
后复位,持续时间可根据实际效果调整。
功能展示
下载程序后连接 PC,可以发现 PC 识别该 BLE HID 键盘设备。按下触摸按键 BTN0/1/2,分别控制音量+、亮度-/+,且对应 LED 灯亮一下;左/右滑动滑条(从滑条中间向两边,向 USB 端口侧滑动为左划),对应侧 LED 翻转,分别控制上/下翻页。
BLE HID 设备" width="400" />
👉 详细展示参见:B站:基于CY8CKIT-149 BLE HID设备实现及PC控制功能开发
项目总结
本次项目基于 CY8CKIT-149 实现了 BLE HID 键盘设备的模拟,并且通过触摸按键与滑条实现了按下操作、左右滑动手势识别,将动作信息通过 I2C 传输至 BLE 模块,并生成 HID 报告对 PC 执行相应快捷键按下操作。