使用的是沁恒的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)转载。

CH58X/CH57X/V208 Observer(观察者)例程讨论讲解的更多相关文章

  1. CH58X/CH57X/V208的Broadcaster(广播者)例程讲解

    在对ble进行应用的时候,每个用户的需求可能不尽相同.这里着重介绍从机Broadcaster例程,只广播不连接. 使用该例程时可以在手机使用APP上对Broadcaster进行调试. 安卓端在应用市场 ...

  2. java: 观察者模式:Observable被观察者,Observer观察者

    java: 观察者模式:Observable被观察者,Observer观察者 以房子价格为例,卖房者为被观察者: import java.util.Observable; //被观察者子类化 publ ...

  3. Java Observer 观察者

    http://www.cnblogs.com/jaward/p/3277619.html 1.API 被观察者 java.util.Observable; public class Observabl ...

  4. Java设计模式——Observer(观察者)模式

    在多个对象之间建立一对多的关系,以便当一个对象状态改变的时候.其它全部依赖于这个对象的对象都能得到通知,并被自己主动更新. 适用情况: 当一个抽象模型有两个方面,当中一个方面依赖于还有一方面. 将这二 ...

  5. 十七、 Observer 观察者设计模式

    设计: 代码清单: Observer public interface Observer { void update(NumberGenerator generator); } DigitObserv ...

  6. Observer观察者设计模式

    Observer设计模式主要包括以下两种对象: (1)被观察对象:Subject,它往往包含其他对象感兴趣的东西,上面例子中热水器中就是Subject(被监视对象); (2)观察对象:Observer ...

  7. Observer 观察者

    意图 定义对象间的一种一对多的依赖关系 ,当一个对象的状态发生改变时, 所有依赖于它的对象都得到通知并被自动更新. 动机 一致性,松耦合 需要维护相关对象间的一致性.我们不希望为了维持一致性而使各类紧 ...

  8. Observer(观察者)设计模式[转]

    Observer设计模式中主要包括如下两类对象: Subject:监视对象,它往往包含着其他对象所感兴趣的内容.在本范例中,热水器就是一个监视对象,它包含的其他对象所感兴趣的内容,就是tempratu ...

  9. C#委托与事件之观察者Observer设计模式

    前言    委托: 委托是一种在对象里保存方法引用的类型,同时也是一种类型安全的函数指针. 或委托可以看成一种表示函数的数据类型,类似函数指针. 事件是特殊的委托 观察者模式:两种角色:(1)Subj ...

随机推荐

  1. C# 开发过程中常见错误记录及解决说明

    1.异常了类型: 1.1.1.1 异常错误信息:An error occurred while updating the entries. See the inner exception for de ...

  2. awk5个使用场景

    awk简介 首先要知道awk的使用场景,需了解awk有哪些优势与短板. 关于个人近期学习awk总结其优势: awk对文本的处理运算效率同比其他工具效率高很多(比shell的for循环高10倍以上,运算 ...

  3. 细数实现全景图VR的几种方式(panorama/cubemap/eac)

    Three.js系列: 在元宇宙看电影,享受 VR 视觉盛宴 Three.js系列: 造个海洋球池来学习物理引擎 Three.js系列: 游戏中的第一.三人称视角 Three.js系列: 数实现全景图 ...

  4. Java基础——02

    今日学习 Java API Scanner package cn.lsl.day03.demo01; //导包 import java.util.Scanner; public class demo0 ...

  5. Taurus.MVC 微服务框架 入门开发教程:项目集成:6、微服务间的调用方式:Rpc.StartTaskAsync。

    系统目录: 本系列分为项目集成.项目部署.架构演进三个方向,后续会根据情况调整文章目录. 开源地址:https://github.com/cyq1162/Taurus.MVC 本系列第一篇:Tauru ...

  6. Rust-函数

    函数结构 函数要点 函数名和变量名使用蛇形命名法(snake case),例如 fn add_two() -> {} 函数的位置可以随便放,Rust 不关心我们在哪里定义了函数,只要有定义即可 ...

  7. Echarts中tooltip解决显示指定数据

    今天开发中遇到一个问题,echarts图表触摸x轴触发tooltip会将x轴上所有的数据展示出来,但是有些场合只需要展示某些数据就可以,并不需要全部展示,如下图: 这里警戒线因为需要开关,所以使用填充 ...

  8. 2.Python环境搭建

    Python是一个跨平台.可移植的编程语言,因此可在windows.linux/unix和Mac os x系统中安装使用.安装完成后,你会得到Python解释器环境,一个命令行交互环境,一个简单的集成 ...

  9. Elasticsearch:top_hits aggregation

    top_hits指标聚合器跟踪要聚合的最相关文档. 该聚合器旨在用作子聚合器,以便可以按存储分区汇总最匹配的文档. top_hits聚合器可以有效地用于通过存储桶聚合器按某些字段对结果集进行分组. 一 ...

  10. 使用Recoding Rules优化性能

    通过PromQL可以实时对Prometheus中采集到的样本数据进行查询,聚合以及其它各种运算操作.而在某些PromQL较为复杂且计算量较大时,直接使用PromQL可能会导致Prometheus响应超 ...