• CH58X/CH57X/V208 Observer(观察者)例程讨论讲解


    使用的是沁恒的CH582M的Observer例程与官方的demo板。

    本例程的功能是主机扫描到从机的MAC地址并打印出来。

    先对宏定义进行理解讨论。

     最大响应扫描数为8,在串口调试助手那里可以看到打印出的8个MAC地址。

    这里的白名单是默认关闭的。

     

    接下来对初始化进行讨论。

    复制代码
    void Observer_Init()
    {
        ObserverTaskId = TMOS_ProcessEventRegister(Observer_ProcessEvent);
    
        // Setup Observer Profile
        {
            uint8_t scanRes = DEFAULT_MAX_SCAN_RES;
            GAPRole_SetParameter(GAPROLE_MAX_SCAN_RES, sizeof(uint8_t), &scanRes);
        }
    
        // Setup GAP
        GAP_SetParamValue(TGAP_DISC_SCAN, DEFAULT_SCAN_DURATION);
    
        // Setup a delayed profile startup
        tmos_set_event(ObserverTaskId, START_DEVICE_EVT);
    }
    复制代码

    这里是初始化期间调用的功能,这里的详解可以参照CH58X/CH57X/V208的Broadcaster(广播者)例程讲解 - 小舟从此逝_1 - 博客园 (cnblogs.com)这篇文章。

    接下来是对任务的管理调度,这里用的是TMOS事件管理。关于TMOS的理解具体可以参照WCH TMOS用法详解 - debugdabiaoge - 博客园 (cnblogs.com)

    再次之前我们要了解一下TMOS任务的调度,在这里TMOS任务可以定义16个其中有15个自定义,1个系统任务。

    广播者的例程里共写了两个任务,首先看到第一个任务

    复制代码
        if(events & SYS_EVENT_MSG)
        {
            uint8_t *pMsg;
    
            if((pMsg = tmos_msg_receive(ObserverTaskId)) != NULL)
            {
                Observer_ProcessTMOSMsg((tmos_event_hdr_t *)pMsg);
    
                // Release the TMOS message
                tmos_msg_deallocate(pMsg);
            }
    
            // return unprocessed events
            return (events ^ SYS_EVENT_MSG);
        }
    复制代码

    这个任务就是唯一的一个系统任务,这里是在各层协议栈之间传递数据,这这里是接收消息。同时还有这几个函数用于内部数据的传递。这部分可以参考CH579/CH57x 的TMOS系统使用 - iot-fan - 博客园 (cnblogs.com)对这部分进行更详尽的了解。

    extern bStatus_t tmos_msg_send( tmosTaskID taskID, uint8_t *msg_ptr );
    extern uint8_t *tmos_msg_receive( tmosTaskID taskID );
    extern uint8_t *tmos_msg_allocate( uint16_t len );
    extern bStatus_t tmos_msg_deallocate( uint8_t *msg_ptr );

    第二个任务则是用户自定义事件,本例程中只使用了这一个自定义事件;

    复制代码
        if(events & START_DEVICE_EVT)
        {
            // Start the Device
            GAPRole_ObserverStartDevice((gapRoleObserverCB_t *)&ObserverRoleCB);
            return (events ^ START_DEVICE_EVT);
        }
        // Discard unknown events
        return 0;
    }
    复制代码
     GAPRole_ObserverStartDevice((gapRoleObserverCB_t *)&ObserverRoleCB);此函数是观察者角色启动设备,在系统启动期间调用一次。 

    下面讨论的是对自定义任务的回调函数。
    复制代码
    static void ObserverEventCB(gapRoleEvent_t *pEvent)
    {
        switch(pEvent->gap.opcode)
        {
    //事件初始化完成之后发送
    case GAP_DEVICE_INIT_DONE_EVENT:
    {
    GAPRole_ObserverStartDiscovery(DEFAULT_DISCOVERY_MODE,
    DEFAULT_DISCOVERY_ACTIVE_SCAN,
    DEFAULT_DISCOVERY_WHITE_LIST);
                PRINT("Discovering...\n");
            }
            break;
       //将设备添加到设备发现结果列表
    case GAP_DEVICE_INFO_EVENT: { ObserverAddDeviceInfo(pEvent->deviceInfo.addr, pEvent->deviceInfo.addrType); } break;      //设备发现完成将设备罗列出来 case GAP_DEVICE_DISCOVERY_EVENT: { PRINT("Discovery over...\n"); // Display discovery results if(pEvent->discCmpl.numDevs > 0) { int i, j; // Increment index of current result (with wraparound) for(j = 0; j < pEvent->discCmpl.numDevs; j++) { PRINT("Device %d : ", j); for(i = 0; i < 6; i++) { PRINT("%x ", pEvent->discCmpl.pDevList[j].addr[i]); } PRINT("\n"); } } GAPRole_ObserverStartDiscovery(DEFAULT_DISCOVERY_MODE, DEFAULT_DISCOVERY_ACTIVE_SCAN, DEFAULT_DISCOVERY_WHITE_LIST); PRINT("Discovering...\n "); } break; default: break; } }
    复制代码

    上述程序中的

    GAPRole_ObserverStartDiscovery(DEFAULT_DISCOVERY_MODE,
    DEFAULT_DISCOVERY_ACTIVE_SCAN,
    DEFAULT_DISCOVERY_WHITE_LIST); 我们可以看到可以看到本函数的定义

    extern bStatus_t GAPRole_ObserverStartDiscovery( uint8_t mode, uint8_t activeScan, uint8_t whiteList );

    uint8_t mode:发现模式   uint8_t activeScan:如果为TRUE执行主动扫描    uint8_t whiteList:仅扫描白名单中的设备

    这三个参数在本例程的定义分别是:

    #define DEFAULT_DISCOVERY_MODE           DEVDISC_MODE_ALL

    #define DEFAULT_DISCOVERY_ACTIVE_SCAN    TRUE

    #define DEFAULT_DISCOVERY_WHITE_LIST FALSE

    ObserverAddDeviceInfo(pEvent->deviceInfo.addr, pEvent->deviceInfo.addrType);调用的函数为 

    复制代码
    static void ObserverAddDeviceInfo(uint8_t *pAddr, uint8_t addrType)
    {
        uint8_t i;
    
        // If result count not at max
        if(ObserverScanRes < DEFAULT_MAX_SCAN_RES) //如果未达到最大扫描数量,扫描个数由自己设置(大约可扫描的数量是40左右)
        {
            // Check if device is already in scan results
            for(i = 0; i < ObserverScanRes; i++)
            {
                if(tmos_memcmp(pAddr, ObserverDevList[i].addr, B_ADDR_LEN))
                {
                    return;
                }
            }
            // Add addr to scan result list
            tmos_memcpy(ObserverDevList[ObserverScanRes].addr, pAddr, B_ADDR_LEN);
            ObserverDevList[ObserverScanRes].addrType = addrType;
    
            // Increment scan result count
            ObserverScanRes++;
        }
    }

    复制代码

     

    这只是最基础的讨论,如有问题请指正!

     如转载请标明出处!文章可能被无良网站搬运。某些网站拿着别人的文章写着“我的编程学习分享”。

    禁止soolco-博客易学编程网 - 易学编程网 (yixuebiancheng.com)转载。

  • 相关阅读:
    火山引擎云原生存储加速实践
    英伟达显卡【NVIDIA GeForece RTX3060 laptop GPU】装深度学习环境,学习框架为Pytorch
    ArcGIS JS 地图内外网环境判断问题
    项目进展(九)-完善ADS1285代码
    Spring同时集成JPA与Mybatis
    webrtc媒体服务器介绍
    FineReport 动态图表表格软件-函数计算组成和语法
    Elasticsearch 和 Arduino:一起变得更好!
    springboot整合MeiliSearch轻量级搜索引擎
    AcWing第78场周赛
  • 原文地址:https://www.cnblogs.com/frontier/p/16860673.html