EM9260嵌入式Linux工控板的CAN通讯方案解析

网友投稿 268 2022-11-13

EM9260嵌入式Linux工控板的CAN通讯方案解析

硬件组成

EM9260的CAN通讯接口可提供高达1Mbps的数据传输速率,当采用5Kbps的的数据传输速率时其通讯距离最高可达到10KM。硬件的错误检定特性也增强了CAN的抗电磁干扰能力,这给数据的远程可靠传输提供了有利保证。

CAN驱动接口函数

1、CAN报文的帧格式简介 在CAN2.0B中存在两种不同的帧格式,其主要的区别在于标识符的长度,具有11位标识符的帧称为标准帧,而包括有29位标识符的帧称为扩展帧。下面分别介绍数据帧的格式。

1、CAN2.0B标准帧 CAN标准帧信息为11个字节,包括两部分:信息和数据部分。前3个字节为信息部分,如图所示:

注:1、字节1为帧信息。D7位表示帧格式,在标准帧中,FF=0;D6位表示帧的类型,RTR=0表示为数据帧,RTR=1表示为 远程帧,在一般的数据通讯中,只使用数据帧;DLC表示数据帧实际的数据长度 2、字节2、字节3为报文识别码,11位有效 3、字节4~字节11为数据帧的实际数据,远程帧时无效

2、CAN2.0B扩展帧 CAN标准帧信息为13个字节,包括两部分:信息和数据部分。前5个字节为信息部分,如图所示:

注:1、字节1为帧信息。D7位表示帧格式,在扩展帧中,FF=1;D6位表示帧的类型,RTR=0表示为数据帧,RTR=1表示为 远程帧;DLC表示数据帧实际的数据长度 2、字节2~字节5为报文识别码,29位有效 3、字节6~字节13为数据帧的实际数据,远程帧时无效

struct can_frame { canid_t can_id; /* 用于定义CAN报文ID以及 EFF/RTR/ERR等标志 */ __u8 can_dlc; /* 用于定义can报文数据包长度0-8 */ __u8 data[8]; /* 用于定义can报文数据 */ };

其中的can报文ID为一个32 bit大小的结构,其中各个bit位定义如下: typedef __u32 canid_t; bit 0-28: CAN 报文的id(标准帧11bit/扩展帧为29bit). bit 29 : CAN报文错误帧标志(0 = data frame, 1 = error frame) bit 30 : CAN报文远程帧标志( 1 = rtr frame ) bit 31 : CAN报文帧格式标志 (0 = 标准帧, 1 = 扩展帧 )

struct accept_filter { unsigned int accept_code; /* 用于定义CAN报文验收代码位 32bit*/ unsigned int accept_mask; /* 用于定义CAN报文验收屏蔽位 32bit*/ unsigned char filter_mode; /* 用于定义CAN报文滤波模式 */ };

具体在进行应用程序开发时,首先调用CAN接口的open( )函数打开CAN接口: sprintf( portname, '/dev/em9x60_can%d', CanNo ); m_fd = open(portname, O_RDWR |O_NONBLOCK );

得到有效的文件描述符m_fd后,然后可调用can_api.h文件中定义的API函数对CAN接口进行相应的通讯参数设置: CAN_StartChip( m_fd ); CAN_SetBaudRate( m_fd, baudrate ); CAN_SetGlobalAcceptanceFilter( m_fd, AcceptanceFilter );

再调用read( ) / write( ) 实现CAN数据的收发操作。

4、CAN通讯接口的数据收发应用示例 在英利公司提供的CAN方案中,CAN通讯的数据收发均采用的中断方式,驱动程序中已自动完成了数据的收发,以及内部定义的CAN接收缓冲区和发送缓冲区的管理。对于用户开发应用程序来说,只需要调用英创公司提供的CAN通讯API函数中的收发函数即可。本小节主要介绍一个CAN通讯的综合应用示例程序。

// 定义CAN通讯类 class EM9X60_CAN { private: // 通讯线程标识符ID pthread_t m_thread; // CAN接收线程 static int ReceiveThreadFunc( void* lparam ); public: EM9X60_CAN(); virtual ~EM9X60_CAN(); // 已打开的CAN文件描述符 int m_fd; unsigned int m_canid; can_frame rxmsg; // 退出数据接收线程标志 int m_ExitThreadFlag; // 按照指定的参数打开CAN接口,并创建CAN接口接收线程 int OpenCAN( int CanNo, CAN_BAUDRATE baudrate, accept_filter*AcceptanceFilter ); // 关闭接口并释放相关资源 int CloseCAN( ); // 初始化设置CAN数据包id信息 int InitCanIDInfo( struct CanIDInfo* pcanid ); // CAN接口写数据 int WriteCAN( char* Buf, int len ); // CAN接收数据处理函数 virtual int PackagePro( char* Buf, int len ); };

OpenCAN 函数用于根据输入参数打开CAN设备,并创建CAN数据接收线程。

res = pthread_create( &m_thread, &attr, (void*)&ReceiveThreadFunc, (void*)this );

ReceiveThreadFunc函数是CAN数据接收和处理的主要核心代码,在该函数中调用select( ),等待串口数据的到来。对于接收到的数据处理也是在该函数中实现,在本例程中处理为简单的数据回发,用户可结合实际的应用修改此处代码,修改PackagePro( )函数即可。流程如下:

需要注意的是,select( )函数中的时间参数在Linux下,每次都需要重新赋值,否则会自动归0。

版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:浅谈mybatisPlus的Ipage分页和map参数的问题
下一篇:关于华为云的六大猜想
相关文章

 发表评论

暂时没有评论,来抢沙发吧~