77范文网 - 专业文章范例文档资料分享平台

OSAL解读笔记(6)

来源:网络收集 时间:2018-12-04 下载这篇文档 手机版
说明:文章内容仅供预览,部分内容可能不全,需要完整文档或者需要复制内容,请下载word后使用。下载word有问题请添加微信号:或QQ: 处理(尽可能给您提供完整文档),感谢您的支持与谅解。点击这里给我发消息

这个就是当有上位机向下位机写东西时,会调用上面这个函数。在这个函数中,会有下列: 先将接收到的长度值打出来:

NPI_PrintValue( \然后执行这个: VOID osal_memcpy( pAttr->pValue, pValue, len ); simpleProfileChar6Len = len;

notifyApp = SIMPLEPROFILE_CHAR6;

注意到这里这个pValue 及pAttr->pValue这两个参数,都要求大于传输的字节长度。这里担心的是这两个是否足够长,先看pValue,要搞清这个,先看谁在调用它,发现它是一个内部调用的函数,其长度定义无法修改之。我估计不会留这么长的空间,要不就是动态分配的还好办一点。

然后看这个pAttr->pValue,看这个pAttr会留多长呢?好象有一个说明是最大为512个octets。这个是什么含义呢?没有搞明白,先试吧。 在最后,它会调用:

simpleProfile_AppCBs->pfnSimpleProfileChange( notifyApp ); ///告诉某人,profile变化了

初始化时,注册了这个函数:

VOID SimpleProfile_RegisterAppCBs( &simpleBLEPeripheral_SimpleProfileCBs ); 也就是将bStatus_t SimpleProfile_RegisterAppCBs( simpleProfileCBs_t *appCallbacks ) {

simpleProfile_AppCBs = appCallbacks; }

static simpleProfileCBs_t simpleBLEPeripheral_SimpleProfileCBs = {

simpleProfileChangeCB // Charactersitic value change callback };

绕来绕去,原来最后调用的是

simpleProfileChangeCB(uint8 paramID)就是最前面的一个,就是在这里调用的。 原来是这样的:

1 当上位机有数据发下来时,就会调用:

static bStatus_t simpleProfile_WriteAttrCB( uint16 connHandle, gattAttribute_t *pAttr, uint8 *pValue, uint8 len, uint16 offset ) 2.在这个函数的最后,它会调用:

simpleProfile_AppCBs->pfnSimpleProfileChange( notifyApp );

而这个simpleProfile_AppCBs,它simpleProfile_AppCBs就是simpleProfileChangeCB 其实就是调用simpleProfileChangeCB。

这个simpleProfile_AppCBs在开始时,它只是指向一个NULL。在初始化时,它被赋给: simpleBLEPeripheral_SimpleProfileCBs,见上文中的兰色部分

而这个simpleBLEPeripheral_SimpleProfileCBs,它本身就是simpleProfileChangeCB 请见上文中的紫色部分

于是下位机先这么着。然后看上位机,如何发100个字节下来。

26

上位机要发100个字节,首先看这个UP键中有关发送部分。有一个语句: req.len = 10; ///原先为1 改为10 说明这个req很重要。这个如果限死了哪也没办法发100个数了。

我们在att.h中,看到这个定义最多为23-3=20个。感觉好象不行了。我们重新定义一下看 在att.h中,将这个 typedef struct {

uint16 handle; //!< Handle of the attribute to be written (must be first field) uint8 len; //!< Length of value

uint8 value[ATT_MTU_SIZE-3]; //!< Value of the attribute to be written

uint8 sig; //!< Authentication Signature status (not included (0), valid (1), invalid (2))

uint8 cmd; //!< Command Flag } attWriteReq_t;

红色部分改为定义成100看一下。如果不行,再将这个ATT_MTU_SIZE 定成103看 再不行就将这个L2CAP_MTU_SIZE 定义成103试一试看,L2CAP_MTU_SIZE原来定义为23的。

这样做的结果是上位机和下位机都死机了。可能不能超过23个字节吧。

我们改为20个字节看一下。还可以没死机。下位机没有改。看来下位机死机的问题能否改到不死呢?估计不可能了。因此我们暂时修改一下协议。 下位机能否主动发呢?

原来是从机收到读命令后,向上位机回复一个HELLO。现在想改成,从机收到数据后,就立即回复,而主机收到任何数据都将它打印出来,看这个可以吗?

修改的方法是:

首先,主机在收到后要立即打印出来收到东西了,这个要在回调函数中进行。 从机要能主动发数据过来。在收到20个字符后,主动发一个出去。

先看一下从机吧,原来从机是在收到读命令后去发送的。现在要收到数据后主自动回一个,这个有些区别的。看原来是怎么发的。

原来是收到读命令后,会调用这个simpleProfile_ReadAttrCB(。。。)在这个过程中,它会调用下列函数:

*pLen = simpleProfileReadConfig(uuid, newValue); VOID osal_memcpy( pValue, newValue, *pLen );

在这里,这个uuid就是SIMPLEPROFILE_CHAR6_UUID。于是我们可以模拟这个发一个下去看。事实上在这个simpleProfileReadConfig,只是处理了下列: len = osal_strlen(\

osal_memcpy(newValue,\

显然这样做行不通,因为上位机没有读,这个回调函数不会被执行。 只能用Note方式来向主机发数据。但这个Note如何调的呢? 由于没有例子可参考,所以先搜一下notification这个 发现有一个电池服务中调用了这个 有下列定义:

27

static void battNotifyCB( linkDBItem_t *pLinkItem ) {

if ( pLinkItem->stateFlags & LINK_CONNECTED ) {

uint16 value = GATTServApp_ReadCharCfg( pLinkItem->connectionHandle, battLevelClientCharCfg ); if ( value & GATT_CLIENT_CFG_NOTIFY ) {

attHandleValueNoti_t noti;

noti.handle = battAttrTbl[BATT_LEVEL_VALUE_IDX].handle; noti.len = 1;

noti.value[0] = battLevel;

GATT_Notification( pLinkItem->connectionHandle, ¬i, FALSE ); } } }

向一个连接的句柄,发送,发送中还要指明电池句柄,长度,和一个值,问题是这个电池的子句柄是怎么回事呢?

于是先在网上找到一个例子,已放到收藏夹中了。 先看一下这个例子再做吧。

看到这个庞大的配置表 注意到它从0x2800开始

static gattAttribute_t simpleProfileAttrTbl[SERVAPP_NUM_ATTR_SUPPORTED] = 。。。

它由3部分组成: char1 的配置表声明 char1 配置表的值

char配置表的用户声明

从char6来看,比其它的多了一个0x2902 多出来的 客户特征配置UUID

而按照网上博客的设想,也是多出来一个0x2902 多出来的 客户特征配置UUID,这个我们已经有了,故就不用再添加了。 有这么一句话:

需要主机的client端对它进行打开通知操作后,从机才能notification通知到主机client. 这个函数也调用了:GATTServApp_InitCharCfg(connHandle,simpleProfileChar6Config); 它是在void simpleProfile_HandleConnStatusCB( uint16 connHandle, uint8 changeType ) 这个回调中初始化的。

这个回调函数是当这个连接状态改变时,这个函数被调用,注意到其中一个参数是连接句柄。 这个连接句柄是连接时得到的吧。找一下看,不是,没有找到。暂不管它。

看代码时,偶然看到按下S1键会产生一个Notification,赶紧转去看一下。结果很失望,估计这个程序是AMO从某个TI的上面拷过来的,将这部分删除了。哪我们看一下TI中有没有这个呢?没看到,看是否防丢器上面有这个呢?按一个键,产生一个Note呢?没有找到。

28

再看:simpleprofile_addservice(uint32 services)这个函数在哪里调用了。 这个在初始化时确实调用了。

后面在这个simpleprofile_setparameter()中也已经在char6中,加入了Notification部分的代码。

我们再看一下原来是怎么发的?原先是在上位机读时,下位机会调用这个 static uint8 simpleProfile_ReadAttrCB( uint16 connHandle, gattAttribute_t *pAttr,

uint8 *pValue, uint8 *pLen, uint16 offset, uint8 maxLen ) 在这个过程中,当碰到的是char6时,就会有:

uint8 newValue[120]; ///这里定义了一个20意味着最多可以有20个字符过去。

extern uint8 simpleProfileReadConfig(uint16 uuid, uint8 *newValue); 这个实际上是准备数据 *pLen = simpleProfileReadConfig(uuid, newValue); VOID osal_memcpy( pValue, newValue, *pLen ); 于是就湖里湖涂地传上去了。 看到后来,发现好象只要

bStatus_t SimpleProfile_SetParameter( uint8 param, uint8 len, void *value )就可以将数据主动发上去了。Param的值为SIMPLEPROFILE_CHAR6 len为要发过去的长度,而*value为要发过去的值。

于是我们可以在收到上位机发过来的helloworld里而,加上这个

bStatus_t SimpleProfile_SetParameter( uint8 param, uint8 len, void *value )即可以了。

好的,我们就修改一下,只改了这么一点地方,看程序看了半天多。

SimpleProfile_SetParameter( SIMPLEPROFILE_CHAR6, 15, \回复Noti

下面看上位机如何处理这个消息吧。下位机发了这么一个上来,上位机在哪里处理呢?它怎么知道呢?

调试中发现,打印语句NPI_PrintValue()调用时,如果不加include”npi.h”则编译时会有警告,然后运行时居然会出错,奇怪啊! 希望的事情没有发生。

发现一个错误,CHAR6的CCC的长度只能是一个字节,而我们却搞了很多字节过去。 我们将它改为一个字节看一下。已改。

下面看一下在主机端,这个让从机Noti允许部分在何处进行的,应该是在连接建立时进行的吗?是的。

现在发现读char3,4的句柄都会失败 其它的都是成功的。char1,2,5,6都成功.不知为什么?

发现读5,6的句柄时,也会调用:simpleProfileReadConfig()

一时搞不出来暂时到此为止,以后有机会再做吧。

现在我们改为全部都是主机进行控制。主机可以往从机中写一片数据,这部分只进行一次。然后从机就从主机中读出来所有的原来写进去的数据。最后再读出从机的几个测量值,它的值是温度,湿度,电压,测量值

29

现在正式开始编写主机程序:

先编上位机的程序,按下发送键后,就发送20个字符出去。在接下来的等发送成功了,就继续发送20个,直到发送完成。

先要组帧。先发第一帧。我们在按键中先发送第一帧。然后,在收到这个帧的响应中再发其它的帧。如果帧发完了,我们就将这个帧计数清零。而在响应中,如果看到这个帧号为0,它将不会再继续往下发的。因为这个表示已经发送完成了。看一下发送结束后的响应在哪里呢?

现在已经写好发送3帧的例子了,接下来再编写从机的部分。从机首先要将主机发过来的数据进行拚接。然后检查是否正确,再次就是写入到FLASH中。

如何检查是否正确呢?先看帧中的内容,即帧号,如果帧号>128,即0x80。则证明是最后一帧了。在每次收到帧时当然先要检查是不是FF,如果是,则检查第2个字节是不是0,如果也是,则传输结束。本机将断开连接。

其实,收到每一帧,都将要拚接的。先要看帧的次序是不是正确,第一次帧号计数器总是为0,收到的是第0帧。后面收到的都要和它比较。还有这个帧号计数器是一个全局变量,要注意在收到错误帧时,将帧计数器清0。现在有个问题就是下位机完全是被动的,连一个应答信息也发不了。现在也没办法,先不管吧。等以后再说。 先将收到的几帧将它拚接起来。

再将它写到FLASH中去。再从中读出来,都可以了。注意到读出来的字节中,最后一个字节为BCC的值。

接下来,就是要采集有关的数据了,有关的数据有下列:

电池电压 测量电压 温度 湿度

然后我们要将些个数据拚起来。同样,我们可以用到下载的数组来作为应答。因为下载与采集不会同时发生,下载一生可能只发生一次(刚开始配置时)。而上载则会多次发生。 先看测电池电压 这个在连接时是不是就读进来呢?建立连接时的回调函数,我们看是不是可以读进来。但是读温湿度可能不妥。这个还是在任务中去解决吧。我们在连接后,发一个事件给主任务。由主任务去进行这些操作吧。

电池电压如何读,看原来的例子直接借用,测出来电池电压为168*0。02=3.36V 可能是正常的。

接下来,测一下这个测量电压的值, 已经看完了。

接下来,本来想读温度和湿度,或暂时交小江去做。

我们还是先将协议部分实现先做一下。将数据组装,由上位机将它读走再说。 NOTI还要搞通才行。不然无法应答,只能被动接收。

30

百度搜索“77cn”或“免费范文网”即可找到本站免费阅读全部范文。收藏本站方便下次阅读,免费范文网,提供经典小说综合文库OSAL解读笔记(6)在线全文阅读。

OSAL解读笔记(6).doc 将本文的Word文档下载到电脑,方便复制、编辑、收藏和打印 下载失败或者文档不完整,请联系客服人员解决!
本文链接:https://www.77cn.com.cn/wenku/zonghe/337256.html(转载请注明文章来源)
Copyright © 2008-2022 免费范文网 版权所有
声明 :本网站尊重并保护知识产权,根据《信息网络传播权保护条例》,如果我们转载的作品侵犯了您的权利,请在一个月内通知我们,我们会及时删除。
客服QQ: 邮箱:tiandhx2@hotmail.com
苏ICP备16052595号-18
× 注册会员免费下载(下载后可以自由复制和排版)
注册会员下载
全站内容免费自由复制
注册会员下载
全站内容免费自由复制
注:下载文档有可能“只有目录或者内容不全”等情况,请下载之前注意辨别,如果您已付费且无法下载或内容有问题,请联系我们协助你处理。
微信: QQ: