文档章节

CanOpen学习笔记4-- 建立SDO通信

b
 bo_zhang
发布于 2017/07/25 21:12
字数 1945
阅读 131
收藏 0

作为DSO Client想要对SDO Server进行写操作(调用_writeNetworkDict):

1、根据nodeID找出OD中对应的SDO Client Parameter的序号CliNbr(即index-0x1280)。

2、再在SDO transfers[]中判断作为SDO_CLIENT的CliNbr是否已经存在(GetSDOClientFromNodeId),即是否存在对同一个Server的通信,没有则继续。

3、在SDO transfers[]中选择一个没有被使用的传输线(getSDOfreeLine得到line序号)并保存whoami(SDO_CLIENT or SDO_SERVER),再初始化此传输线(initSDOline),将状态(SDO_DOWNLOAD_IN_PROGRESS或SDO_BLOCK_DOWNLOAD_IN_PROGRESS)和CliNbr以及索引等保存其中。传输量较大的分配内存到传输线(dynamicData)中,再复制全部数据到此传输线中。

4、构建SDO帧信息(8字节部分),并将Callback函数指针赋值给此传输线的回调函数指针,用于传输结束时调用。

5、发送SDO帧(根据SDO_CLIENT和CliNbr确定COB_ID部分),启动SDO传输。

 

注:函数writeNetworkDictCallBackAI是用于没有找到对应nodeID的SDO Client Parameter的传输,利用SDO_CLIENT中ServerID为0的SDO Client Parameter来赋值替代。

 

对于SDO写操作的结果可以通过getWriteResultNetworkDict来查看,在执行时先判断是否存在对应的Client以及其SDOline是否在使用,若是直接判断传输线的状态(transfers[line].state)是否为SDO_FINISHED,若不是,返回当前的状态;若是,复位传输线(resetSDOline)并返回SDO_FINISHED。

当需要结束SDO传输时(SDO传输完成或者超时),调用closeSDOtransfer,根据nodeID找到对应的在使用的传输线,并复位传输线。

 

利用SDO传输文件

Server端准备工作:传输一个文件至少需要传输三个部分,即文件名、文件大小以及文件内容,由于CanOpen协议本身是没有传输文件的规定的,所以需要在CanOpen协议基础上实现文件的传输。

这里在OD对象字典上定义三个变量,分别保存传输文件的三个部分(如上所述)。文件名利用visible_string类型存储,为避免动态分配内存,这里定义32字节的数组,也就是说文件名的最大长度为31字节(最后一个为结束符),所以文件名固定传输32个字节。文件大小用uint32类型存储。文件内容用domain类型存储,其大小和存储区域在传输完文件大小后动态分配。

这里至少FileSize和FileBuffer需要回调函数,在其值发生改变时调用。远程Client传输文件前需要先传输文件的大小,在FileSize的回调函数中,分配需要尺寸的内存,并初始化FileBuffer变量的相关参数(如类型、大小、指针)。注:其实FileBuffer定义的数组并没有利用,使用动态分配的存储空间。

这里FileName的回调函数并没有利用。

当FileBuffer 的回调函数调用时说明文件传输已经完成,可以对文件进行存储。注意由于这个函数是在_setODentry中调用的,也就是在canDispatch()中调用,而canDispatch()调用时已经关中断(定时器中断)了,同时在这个回调函数中对文件系统经行打开读写操作可能会导致故障(我这里发现写的时候系统自动复位),所以FileBuffer的回调函数应该尽量快速完成,可以设置一个标志位,这里置位,在某个线程(Task)中,轮询此标志并进行处理。处理完成后需要释放(free)分配的内存空间,并初始化FileBuffer索引相关的变量。

Client端准备工作:对于Server端的存储文件的三个变量索引必须知道(最好固定下来),在获得文件大小,文件名,文件内容后,调用WriteSDOFile(自己实现)启动文件发送。

这里首先发送的是文件大小,同时确定文件大小传输完成后的回调函数,在其回调函数启动发送文件名,在发送文件名的回调函数中启动发送文件内容,在发送文件内容的回调函数中释放分配的内存。

这里在开始就已经将文件名和文件大小以及文件内容的指针用全局变量保存下来。

 

发送文件后记:在SDO发送数据时会先将要发送的数据保存在SDO传输线中(小尺寸保存在transfers[line].data中,若尺寸过大则先动态分配内存(transfers[line].dynamicData),将所有要传输的数据复制到其中),原数据的内存可以释放掉。而在接收方,SDO在initiate download阶段只是在传输线中保存以后传送文件的大小,并没有分配内存,在之后接收数据时先保存在transfers[line].data[SDO_MAX_LENGTH_TRANSFER]中,当接收到的数据量大于SDO_MAX_LENGTH_TRANSFER(32)时再一次动态分配SDO_DYNAMIC_BUFFER_ALLOCATION_SIZE(128*1024)量的内存,并将之前收到的数据复制到其中,之后的接收数据直接保存到新分配的内存中。当接收的数据量再次大于SDO_DYNAMIC_BUFFER_ALLOCATION_SIZE时,会重新分配再加SDO_DYNAMIC_BUFFER_ALLOCATION_SIZE的内存量,也就是说每次超过分配的数据量时会再加SDO_DYNAMIC_BUFFER_ALLOCATION_SIZE大小的内存量。当数据接收完成之后,再将数据复制到对象字典中。

 

后记二:当SDO CLIENT发送或者接收超时,会在SDOTimeoutAlarm()中发送SDO ABORT给与该SDO通信的节点。同时置通信状态transfers[line].state为SDO_ABORTED_INTERNAL,并且置transfers[line].abortCode为SDOABT_TIMED_OUT,之后再调用此SDO传输线的CallBack函数transfers[line].Callback(d, nodeId),在这个函数中用户可以进行相应的处理。若传输成功,则置通信状态为transfers[line].state = SDO_FINISHED,并调用CallBack函数。若SDO CLIENT接收到SDO ABORT帧,会置通信状态为transfers[line].state = SDO_ABORTED_RCV,并且transfers[line].abortCode置为接收的错误代码,并调用transfers[line].Callback函数。

注意:在处理SDO帧(proceedSDO)时,由于自身原因导致的错误(如toggle位错误,通信阶段错误,line存取错误等),若自身为SDO_SERVER,则只resetSDOline并发送SDO ABORT帧;若自身为SDO_CLIENT,则先停掉该line的定时器,并置状态和错误代码,再发送SDO ABORT帧。都没有调用CallBack函数。

综上可知,当SDO Client发起读或者写远程OD时,可以初始化传输线(line)时设置CallBack函数,并发起传输;SDO Server接收到此初始SDO传输时选择一个空闲的SDO line并初始化,之后开始传输。传输过程中若SDO Server出现错误,则调用failedSDO复位传输线(line)并发送SDO ABORT帧,Client接收到此帧则停止定时器、置状态和错误代码并调用CallBack函数。若传输过程中SDO Client出现错误,则调用failedSDO停止定时器、置状态并发送SDO ABORT帧,没有复位传输线,也没有调用CallBack函数(需要应用检查传输状态并结束传输线,认为可以加上callback调用),Server接收到此帧则复位传输线。若Client规定时间内没有接收到Server响应,则置状态发送SDO ABORT帧,并调用CallBack函数,若此函数没有复位(或关闭)传输线,则还会复位此传输线。

 

后记三:对于OD对象字典的参数变量的回调函数,在完成处理后要返回OD_SUCCESSFUL,若返回其他非零值,会当做错误代码发送至与其通信的远端节点。注:没有写返回值的,编译器可能会随即返回某个值导致发送错误(Keil出现过)。

© 著作权归作者所有

共有 人打赏支持
b
粉丝 0
博文 7
码字总数 6636
作品 0
苏州
私信 提问
CANopen协议介绍

1.CANopen协议简介 从OSI 网络模型的角度来看,CAN总线只定义了OSI网络模型的第一层(物理层) 和第二层(数据链路层),而在实际设计中,这两层完全由硬件实现,设计人员无需再为此开发相关...

炉yu
2017/06/14
0
0
SPI (Serial Peripheral Interface)串行外设接口 协议详解+实例

SPI (Serial Peripheral Interface)串行外设接口 协议详解+实例 一、协议简介 SPI协议简介(转) (2008-04-26 16:24) 分类:单片机及硬件相关技术 来自:http://blog.chinaunix.net/space...

FreeBlues
2012/07/16
0
1
JDBC中如何获取java.sql.Array的值

因为最近在做GIS项目,中间涉及存取Oracle Spatial的SDOGeometry信息,由于当初的设计原因,现在增加一个功能,要从库中取出地理信息的数据——这个功能可真是折腾人啊。。 我也是刚接触GIS...

tnjin
2016/02/28
1K
0
SPI协议概括

一 SPI协议概括 SPI,是英语Serial Peripheral interface的缩写,顾名思义就是串行外围设备接口。是Motorola首先在其MC68HCXX系列处理器上定义的。SPI接口主要应用在 EEPROM,FLASH,实时时钟...

曾永刚
2012/08/08
0
0
ESP8266笔记汇总

一、前言 2015年开始,随着ESP8266的横空出现,WiFi SoC大幅降价,市场模组价格一下被拉到了10元档。WiFi由于可直接入网的,在智能家居等行业中成为了应用最广泛的物联网技术。本尊贵为物联网...

iotisan
2017/02/03
0
0

没有更多内容

加载失败,请刷新页面

加载更多

w, vmstat, top, sar, nload命令查看系统状态信息

w/uptime 查看系统负载 cat /proc/cpuinfo 查看cpu核数 vmstat 监控系统状态,用法 vmstat 1,关键的几列: r, b, swpd, si, so, bi, bo, us, wa top 查看进程使用资源情况 top -c 显示详细的...

野雪球
45分钟前
0
0
小白创建一个spring boot项目

进入 https://start.spring.io/

lilugirl
今天
2
0
Alibaba Java诊断利器Arthas实践--使用redefine排查应用奇怪的日志来源

背景 随着应用越来越复杂,依赖越来越多,日志系统越来越混乱,有时会出现一些奇怪的日志,比如: [] [] [] No credential found 那么怎样排查这些奇怪的日志从哪里打印出来的呢?因为搞不清...

hengyunabc
今天
2
0
home hosts

home hosts lwk@qwfys:~$ cat /etc/hosts127.0.0.1 localhost127.0.1.1 qwfys192.168.56.101vm600.qwfys.com39.108.212.91alpha1.ppy.com39.108.117.122alpha2.p......

qwfys
今天
3
0
大数据教程(6.1)hadoop生态圈介绍及就业前景

1. HADOOP背景介绍 1.1、什么是HADOOP 1.HADOOP是apache旗下的一套开源软件平台 2.HADOOP提供的功能:利用服务器集群,根据用户的自定义业务逻辑,对海量数据进行分布式处理 3.HADOOP的核心组...

em_aaron
今天
5
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部