一种基于CAN总线的modbus通信设计的制作方法

文档序号:17757571发布日期:2019-05-24 21:25阅读:741来源:国知局
一种基于CAN总线的modbus通信设计的制作方法

本发明专利涉及电子设计技术领域,尤其涉及一种基于can总线的modbus通信设计。



背景技术:

阅读过modbus协议的人都知道modbus有ascii和rtu模式,其中rtu模式用的较多,一个数据包在网络上传输我们必须知道包的开始和结束,在rtu模式中数据包是以至少3.5个字符的静默时间开始和结束的,如果信息结束前存在超过1.5个字符以上的间隔时间则出错。为了检测这些时间间隔,在程序上将变得很被动。ascii虽然有专用的开始结束标志符,但是ascii需要把一个字节数据传换为两个字符发送所以其效率低。所以还是得采用rtu模式,但得根据can总线的特点解决数据包开始结束标志的定义。

can总线的数据传输是以帧为单位的,一个帧包含标识符、数据段crc等,标识符表示该帧的发送优先级,数据段包含实际的数据,数据长度从1到8字节,crc对该帧进行校验,因为帧中包含了数据校验功能,所以在can上跑modbus就不需要再对数据进行crc校验。在这里我们看到can总线是有优先级这个概念,但是没有出现像modbus这样有地址的概念,can总线上标识符段表示的是该帧的优先级,它面向的是数据,而modbus面向的是设备,每个数据包中都有地址,如果我们把地址放在can帧的数据段中那么所有设备都必须接收每一帧,然后对数据进行解析,如果网络负载比较大的是时候,这对设备不利。can控制器一般都能对特定的标识符段进行过滤,那么我们为什么不能把标识符段作为设备的地址,然后设备对特定的标识符进行过滤,这样就减少了设备的负担。但是如果标识符段作为目的地址,那么can总线上就不能有两个主机,应为can总线规定不能有两个相同标识符的帧同时发送。既然标识符符不能作为目的地址,那么就实现不了设备对数据的过滤。

发明专利内容

本发明专利涉及一种基于can总线的modbus通信设计,本发明以can总线上跑modbus协议为目的对数据网络层协议进行设计,实用性强。

附图说明

图1:工作流程图。

具体实施方式

为了使本发明专利的目的、技术方案及优点更加清楚明白,以下结合附图及实施例,对本发明专利进行进一步详细说明。应当理解,此处所描述的具体实施例仅仅用以解释本发明专利,并不用于限定本发明专利。

本发明专利涉及一种基于can总线的modbus通信设计,本发明以can总线上跑modbus协议为目的对数据网络层协议进行设计,实用性强。

进一步的,can驱动层主要做的工作是初始化设备,收发数据,如下是集can功能函数的结构体:

typedefstruct

{

uint8_t(*init)(uint8_tport,uint16_taddr);

void(*open)(uint8_tport);

void(*close)(uint8_tport);

uint8_t(*wirte)(uint8_tport,message*m);

void(*setbps)(uint8_tport,uint32_tbaud);

}can_device;

uint8_t(*init)(uint8_tport,uint16_taddr);初始化设备,port:端口号,指示初始化哪个can,addr:设备在通信中的地址,地址的长度要根据标准帧或者扩展帧定义。返回1:成功0:失败;

void(*open)(uint8_tport);打开设备;

void(*close)(uint8_tport);关闭设备;

uint8_t(*wirte)(uint8_tport,message*m);向设备写数据;

void(*setbps)(uint8_tport,uint32_tbaud);设置通信速率;

消息结构体如下:

typedefstruct

{

uint32_tcob_id;/**<message'sid*/

uint8_trtr;/**<remotetransmissionrequest.(0ifnotrtrmessage,1ifrtrmessage)*/

uint8_tlen;/**<message'slength(0to8)*/

uint8_tdata[8];/**<message'sdatas*/

}message。

进一步的,can接收中断服务程序序调用voidcan_msg_dispatch(can_uint8port,message*m),该函数对每一帧数据进行解析,工作流程如图1所示。

进一步的,在试验中用的操作系统为ucosii2.86,把接收完成的数据包发送给接收服务任务是通过消息邮箱把数据包发送给接收服务任务的。数据包的结构体如下:

typedefstruct

{

uint8_tport;

uint16_taddr;

uint8_tid;

uint16_tsize;

uint16_ttotal_size;

uint8_tmessage[can_max_len];

uint8_tttl;

void*next;

}can_pkg;

port:设备端口;

addr:数据来源地址;

id:包id;

size:包的当前大小;

total_size:包的总大小;

message:消息缓冲区;

ttl:该包的生命周期;

next:指向下一个包;

total_size:是通过接收到最后一帧数据计算出来的,当size=total_size时表示接收完成;

message是一个数组,这里为了设计简单采用了数组,这个用户可以灵活设计成动态分配;

ttl:当接收一个包时,如果传输过程中丢失一个帧那么这个包就永远不能接收完成,因此设置了ttl没个周期扫描一次,ttl减一,当ttl等于0时,不管接收是否完成,都将把包移除接收链表;

next:指向下一个包的指针,用作单向链表;

包在工作过程中分为三种状态:

使用状态:包正在接收数据;

游离装态:数据接收完成,等待处理;

空闲状态:包处于空闲状态。

进一步的,发送过程建议采用对列中断发送,发送中断产生后通过查看队列中是否还有要发送的数据来循环发送,上层应用只需向队列写数据。数据包id采用递增循环方式发送,没发送一个新的数据包时,将在上次分配的id上加1然后产看该id是否实用,如果没有使用,将采用该id,否者id继续加1,直到找到空闲的id,如果所有id都在使用那么id将返回0表示没有可用id分配;

staticvoid*id_queue[can_max_id];

id分配队列是一个void*的数据,它指向的数据类型是用户定义的,它的作用是当接收服务任务接收到回应的数据时,通过该数据把接收的信息发送给使用该id的任务。

以上所述仅为本发明专利的较佳实施例而已,并不用以限制本发明专利,凡在本发明专利的精神和原则之内所作的任何修改、等同替换和改进等,均应包含在本发明专利的保护范围之内。

当前第1页1 2 
网友询问留言 已有0条留言
  • 还没有人留言评论。精彩留言会获得点赞!
1