6854|1

63

帖子

1

TA的资源

一粒金砂(中级)

楼主
 

【沁恒RISC-V内核 CH582】蓝牙HID键盘代码解读 [复制链接]

 

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,前面的是录屏之前输入的。

 

最新回复

蓝牙4.0跟蓝牙5.0的接收器都兼容接收吗?还有无线键盘,原来是有线的,供电考虑怎么解决呢?  详情 回复 发表于 2022-3-30 14:29
点赞 关注
 
 

回复
举报

6841

帖子

11

TA的资源

版主

沙发
 
蓝牙4.0跟蓝牙5.0的接收器都兼容接收吗?还有无线键盘,原来是有线的,供电考虑怎么解决呢?
 
 
 

回复
您需要登录后才可以回帖 登录 | 注册

随便看看
查找数据手册?

EEWorld Datasheet 技术支持

相关文章 更多>>
推荐帖子
CES评最佳创新产品奖 35款产品亮相(2)

本帖最后由 jameswangsynnex 于 2015-3-3 20:00 编辑

Linux使用技巧集

10756

[MSP430 学习笔记] 晶体振荡器的负载电容

最近有童靴在问如何确定MSP430的晶体负载电容,一般来讲,大家都是在用一些经验值,对其原理也不是特别清楚。 有兴趣的同学可以看 ...

从零开始点亮LED灯

本帖最后由 微末凡尘 于 2014-7-27 01:03 编辑 ...

Fly-Buck 转换器 PCB 布局技巧

同步降压转换器已作为隔离式偏置电源在通信及工业市场得到认可。隔离式降压转换器或者通常所谓的 Fly-Buck 转换器,采用一个耦合 ...

【拓普微智能显示模块】四:串口交互以及曲线、绘图板、动画控件的应用

本帖最后由 数码小叶 于 2021-11-21 12:00 编辑 上一篇已经使用SGTools产生了一个简单的界面,所以对于SGTools来说,简单使用 ...

功率变换开关技术(修订版)电力电子的核心理论

电力电子技术在电力系统、新能源发电、电动汽车、电力牵引以及家用电器等众多领域快速发展,电力电子化已成为一种发展趋势,然而 ...

功率放大器在水下主动电场物体形状成像系统的应用

功率放大器在水下主动电场物体形状成像系统的应用

器件选型——TVS管选型一般要注意哪些参数?

642279642280 这是我找的一份TVS的规格书, 问题1: 想请教一下大家平时在进行TVS选型的时候比较关注哪些参数? ...

Mecha Lab 防生手臂中的手指运动用的是什么方案?

好久之前看到了这个手臂演示,属实是惊艳到了我,我们公司也想搞一个活动的手臂,有人知道它这个手指运动用的是什么方案吗? ...

关闭
站长推荐上一条 1/10 下一条

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

About Us 关于我们 客户服务 联系方式 器件索引 网站地图 最新更新 手机版

站点相关: 国产芯 安防电子 汽车电子 手机便携 工业控制 家用电子 医疗电子 测试测量 网络通信 物联网

北京市海淀区中关村大街18号B座15层1530室 电话:(010)82350740 邮编:100190

电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved
快速回复 返回顶部 返回列表