CH582这款MCU的特点在蓝牙上面,所以我准备做一个有线键盘转蓝牙键盘的小东西,看到官方给的例程里面也有蓝牙HID键盘的例程,所以就研读一下。
官方的有main函数的代码如下:
/******************************************************************************/
/* 头文件包含 */
#include "CONFIG.h"
#include "HAL.h"
#include "hiddev.h"
#include "hidkbd.h"
/*********************************************************************
* GLOBAL TYPEDEFS
*/
__attribute__((aligned(4))) uint32_t MEM_BUF[BLE_MEMHEAP_SIZE / 4];
#if(defined(BLE_MAC)) && (BLE_MAC == TRUE)
const uint8_t MacAddr[6] = {0x84, 0xC2, 0xE4, 0x03, 0x02, 0x02};
#endif
/*********************************************************************
* @fn Main_Circulation
*
* [url=home.php?mod=space&uid=159083]@brief[/url] 主循环
*
* [url=home.php?mod=space&uid=784970]@return[/url] none
*/
__HIGH_CODE
void Main_Circulation()
{
while(1)
{
TMOS_SystemProcess();
}
}
/*********************************************************************
* @fn main
*
* @brief 主函数
*
* @return none
*/
int main(void)
{
#if(defined(DCDC_ENABLE)) && (DCDC_ENABLE == TRUE)
PWR_DCDCCfg(ENABLE);
#endif
SetSysClock(CLK_SOURCE_PLL_60MHz);
#if(defined(HAL_SLEEP)) && (HAL_SLEEP == TRUE)
GPIOA_ModeCfg(GPIO_Pin_All, GPIO_ModeIN_PU);
GPIOB_ModeCfg(GPIO_Pin_All, GPIO_ModeIN_PU);
#endif
#ifdef DEBUG
GPIOA_SetBits(bTXD1);
GPIOA_ModeCfg(bTXD1, GPIO_ModeOut_PP_5mA);
UART1_DefInit();
#endif
PRINT("%s\n", VER_LIB);
CH58X_BLEInit();
HAL_Init();
GAPRole_PeripheralInit();
HidDev_Init();
HidEmu_Init();
Main_Circulation();
}
看到了主循环的这段代码:
/*********************************************************************
* @fn Main_Circulation
*
* @brief 主循环
*
* @return none
*/
__HIGH_CODE
void Main_Circulation()
{
while(1)
{
TMOS_SystemProcess();
}
}
这段代码应该是一个用软件定时器实现的简单任务的轮询调度,跳转进来看到这段代码:
/**
* @brief tmos system timer initialization
*
* @note must initialization before call tmos task
*
* @param fnGetClock - 0:system clock select RTC timer
* valid:system clock select extend input
*
* @return Command Status.
*/
extern bStatus_t TMOS_TimerInit( pfnGetSysClock fnGetClock );
/**
* @brief Process system
*
* @param None.
*
* @return None.
*/
extern void TMOS_SystemProcess( void );
这个.h对应的.c文件是.a文件的形式,所以应该是闭源的,注释可以看出来的确是一个软件定时器,需要一个外部输入时钟做os的时钟源。所以具体的蓝牙键值上传代码应该是通过注册callback的方式实现的,然后找到hidkbd.c中的代码:
/*********************************************************************
* @fn HidEmu_ProcessEvent
*
* @brief HidEmuKbd Application Task event processor. This function
* is called to process all events for the task. Events
* include timers, messages and any other user defined events.
*
* @param task_id - The TMOS assigned task ID.
* @param events - events to process. This is a bit map and can
* contain more than one event.
*
* @return events not processed
*/
uint16_t HidEmu_ProcessEvent(uint8_t task_id, uint16_t events)
{
static uint8_t send_char = 4;
if(events & SYS_EVENT_MSG)
{
uint8_t *pMsg;
if((pMsg = tmos_msg_receive(hidEmuTaskId)) != NULL)
{
hidEmu_ProcessTMOSMsg((tmos_event_hdr_t *)pMsg);
// Release the TMOS message
tmos_msg_deallocate(pMsg);
}
// return unprocessed events
return (events ^ SYS_EVENT_MSG);
}
if(events & START_DEVICE_EVT)
{
return (events ^ START_DEVICE_EVT);
}
if(events & START_PARAM_UPDATE_EVT)
{
// Send connect param update request
GAPRole_PeripheralConnParamUpdateReq(hidEmuConnHandle,
DEFAULT_DESIRED_MIN_CONN_INTERVAL,
DEFAULT_DESIRED_MAX_CONN_INTERVAL,
DEFAULT_DESIRED_SLAVE_LATENCY,
DEFAULT_DESIRED_CONN_TIMEOUT,
hidEmuTaskId);
return (events ^ START_PARAM_UPDATE_EVT);
}
if(events & START_PHY_UPDATE_EVT)
{
// start phy update
PRINT("Send Phy Update %x...n", GAPRole_UpdatePHY(hidEmuConnHandle, 0, GAP_PHY_BIT_LE_2M,
GAP_PHY_BIT_LE_2M, 0));
return (events ^ START_PHY_UPDATE_EVT);
}
if(events & START_REPORT_EVT)
{
hidEmuSendKbdReport(send_char);
send_char++;
if(send_char >= 29)
send_char = 4;
hidEmuSendKbdReport(0x00);
tmos_start_task(hidEmuTaskId, START_REPORT_EVT, 2000);
return (events ^ START_REPORT_EVT);
}
return 0;
}
可以很明显的看到每隔2000ms会上传一次键值,然后看一下hid设备的键码表,可以知道键值是从a到z循环输入。
而且没有功能按键,只有字母的输入:
/*********************************************************************
* @fn hidEmuSendKbdReport
*
* @brief Build and send a HID keyboard report.
*
* @param keycode - HID keycode.
*
* @return none
*/
static void hidEmuSendKbdReport(uint8_t keycode)
{
uint8_t buf[HID_KEYBOARD_IN_RPT_LEN];
buf[0] = 0; // Modifier keys
buf[1] = 0; // Reserved
buf[2] = keycode; // Keycode 1
buf[3] = 0; // Keycode 2
buf[4] = 0; // Keycode 3
buf[5] = 0; // Keycode 4
buf[6] = 0; // Keycode 5
buf[7] = 0; // Keycode 6
HidDev_Report(HID_RPT_ID_KEY_IN, HID_REPORT_TYPE_INPUT,
HID_KEYBOARD_IN_RPT_LEN, buf);
}
烧录程序到开发板
打开设置蓝牙配对连接
打开串口终端查看,connected连接成功
可以看到依次输入26个字母,这里是l、m、n,前面的是录屏之前输入的。