基于STM32F103移植canfestival协议栈(从站)CANopen |
您所在的位置:网站首页 › stm32f1移植stm32f › 基于STM32F103移植canfestival协议栈(从站)CANopen |
CAN open是一个基于CAN串行总线的网络传输系统的应用层协议,遵循ISO/OSI协议。CAN现场总线只是实现了OSI七层架构中的物理层和数据链路层,而canopen协议是基于他之上的一个应用层协议,它规定了(包含了)OSI七层架构的网络层以上的通信规则(个人理解)
二、通信对象理解 (1)网络管理对象(NMT) 包括Boot-up消息,Heartbeat协议(心跳节点)及NMT消息,基于主从通信模式, NMT 用于管理和监控网络中的各个节点,主要实现三种功能:节点状态控制、错误控制和节点启动。 (2)服务数据对象(SDO) l 包括接收 SDO(R-SDO) 和发送 SDO(T-SDO)。 l 通过使用索引和子索引, SDO 使客户机能够访问设备对象字典中的项。 l SDO 通过 CAL 中多元域的 CMS 对象来实现,允许传送任何长度的数据,当数据超过 4 个字节时分拆成几个报文。 l 协议是确认服务类型,为每个消息生成一个应答。 SDO 请求和应答报文总是包含 8 个字节。 (3)过程数据对象(PDO) ·包括接收 PDO(RPDO) 和发送 PDO(TPDO)。 ·用来传输实时数据,数据从一个创建者传到一个或多个接收者。数据传送限制在 1 到 8 个字节。 ·每个 CANopen 设备包含 8 个缺省的 PDO 通道, 4 个发送 PDO 通道和 4 个接收 PDO 通道。 ·PDO 包含同步和异步两种传输方式,由该 PDO 对应的通信参数决定。 ·PDO 消息的内容是预定义的,由该 PDO 对应的映射参数决定。 (4)同步对象(SYNC) 同步对象是由 CANopen 主站周期性地广播到 CAN 总线的报文,用来实现基本的网络时钟信号,每个设备可以根据自己的配置,决定是否使用该事件来跟其它网络设备进行同步通信。 (5)紧急报文(EMCY) 设备内部通信故障或者应用故障时发送的报文 三、对象字典 1)对象字典概述 CANopen对象字典(OD: Object Dictionary)是CANopen协议最为核心的概念。所谓的对象字典就是一个有序的对象组,描述了对应CANopen节点的所有参数,包括通讯数据的存放位置也列入其索引,这个表变成可以传递形式就叫做EDS文件(电子数据文档Electronic Data Sheet)。 理解eg:对象字典就相当于菜单(OD),比如说你去奶茶店点奶茶的时候。你看到店里的菜单上有很多品种,如果茶,奶茶,咖啡等(OD中的对象),他们前面有一个编号(就相当于索引),然后这些类型下面又细分出奶茶的名字,如波霸奶茶,柠檬茶,而他们前面也同样有着编号(就相当于子索引)。而后你看到这么多,不知道喝什么,此时你突然看到有套餐(相当于PDO、SDO),这样你就可以点一个套餐了,而套餐包含的样式有限(64bit),然后你告诉服务员,我要套餐A(已经映射好OD中的对象的PDO),此时服务员听到后(PDO、SDO发送成功)(而后面的工作人员给你制作套餐的过程就有点像我们PDO,SDO组装发送的过程)他就给你上 了一个套餐A的菜品。 四、移植CANfestival协议站 (1)移植CANfestival-3协议栈源码(网上资源很多,可以自己去下载,我也上传了) 新建inc、src、driver三个文件夹用来存放canfetsival的核心文件以及驱动文件; 文件包含:include中的19个.h文件以及example/AVR/Slave下的ObjDict.h文件//实现从机功能的时候要用到 以及将include中的AVR更名为stm32,并保留其中的applicfg.h、canfestival.h、config.h、timerscfg.h四个头文件。移植到inc这个文件夹里面(头文件) 将src里面的.c文件全部移植到新建的src文件里面;(symbols.c文件也要去除 ) (2)建立canopen_drive文件夹,用来存放驱动源文件(如canopen_drv.c、TestSlave.c/.h文件;底层驱动文件); 为什么要建canopen_drive?里面又该存放什么源文件? 答:①应该是为了添加相应的接口函数,供canfestival.h调用,如果没有的话,移植过来的协议栈源码就会报错。如下图: canSend() ,作用是发送can数据,最终canfestival库发送数据,都会调用canSend()函数; getElapsedTime(),作用是软件定时器的修正(通过一个硬件定时器,来模拟多个软件定时器). setTimer(),作用是改变硬件定时器的溢出周期 ②应该放一个canopen_drv.c(名字自定义,我的为了方便起见就这样命名了) canopen_drv.c含canSend()、canReciver()、canChangeBaudRate();供canfestival.h调用;含setTimer()、getElapsedTime()供timer.h调用(协议栈里的); 以上就完成了协议栈的移植; (3)建立bsp文件夹,用来存放与timer、can相关的源文件和头文件,基础工程;初始化TIM定时器,CAN通信的基础配置,以及一些IO口的初始化;可以移植正点原子的定时器,和CAN收发实验的那些基础配置; (4)建立对象字典文件TestSlave.c、TestSlave.h通过软件来建立,并保存在canopen_drive里面,方便后续的调用 总结:移植思想:①CAN、定时器硬件相关的操作代码②对象字典资源生成 根据编译错误找到config.h把下面这些注释掉或者删掉 还有把dfc里面的inline删掉,这样就还剩前面三个错误了;缺少的那三个函数; 缺啥补啥。借鉴了网上的大佬们的代码(这个放在canopen_drv里面) #include "canfestival.h" #include "timer.h" unsigned int TimeCNT=0;//时间计数 unsigned int NextTime=0;//下一次触发时间计数 unsigned int TIMER_MAX_COUNT=70000;//最大时间计数 static TIMEVAL last_time_set = TIMEVAL_MAX;//上一次的时间计数 unsigned char canSend(CAN_PORT notused, Message *m) { return 0; } unsigned char canChangeBaudRate(CAN_PORT port, char* baud) { return 0; } //Set the next alarm // void setTimer(TIMEVAL value) { NextTime=(TimeCNT+value)%TIMER_MAX_COUNT; } // Get the elapsed time since the last occured alarm // TIMEVAL getElapsedTime(void) { int ret=0; ret = TimeCNT> last_time_set ? TimeCNT - last_time_set : TimeCNT + TIMER_MAX_COUNT - last_time_set; last_time_set = TimeCNT; return ret; } //1s的定时器驱动 void timerForCan(void) { TimeCNT++; if (TimeCNT>=TIMER_MAX_COUNT) { TimeCNT=0; } if (TimeCNT==NextTime) { TimeDispatch(); } } //这个是canSend函数。实现PDO、SDO发送 unsigned char Can_Send_Msg(unsigned char* msg,unsigned char len) { unsigned char mbox; unsigned int i = 0; CanTxMsg TxMessage; TxMessage.StdId = 0x12; // 标准标识符为 0x12 TxMessage.ExtId = 0x12; // 设置扩展标示符(29 位) TxMessage.IDE = CAN_Id_Standard; // 标准帧 TxMessage.RTR = CAN_RTR_Data; // 数据帧 TxMessage.DLC = len; // 要发送的数据长度 for(i=0;i |
今日新闻 |
推荐新闻 |
CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3 |