diff --git a/CHANGELOG b/CHANGELOG new file mode 100644 index 0000000..c3f1816 --- /dev/null +++ b/CHANGELOG @@ -0,0 +1,52 @@ +/********************************************************************* + * + * J1939 Main Source Code + * + ********************************************************************* + * + * 本程序是由XieTongXueFlyMe对现有的J1939协议文档分析,和对前辈的贡献总结, + * 写出的一套开源的J1939驱动。 + * 本协议特点: + * 1.易移植(不针对特定的CAN硬件,只要满足CAN2.0B即可) + * 2.轻量级(可适应低端的MCU) + * 3.支持多任务调用接口(可用于嵌入式系统) + * 4.双模式(轮询或者中断,逻辑更加简单明了) + * 5.不掉帧(数据采用收发列队缓存) + * + * 源代码下载: + * https://github.com/XeiTongXueFlyMe/J1939 + * 源代码临时手册Web站点: + * https://xeitongxueflyme.github.io/j1939doc.github.io/ + * + * Version Date Description + * ------------------------------------------------------------------- + * v1.0.0 2017/06/04 首个版本 Version 1 测试版发布 + * v1.0.1 2017/08/04 完善功能 + * v1.1.0 2017/11/22 Version 1 稳定发布版 + * v2.0.1 2017/11/24 Version 2 测试版发布 + * v2.0.2 2018/01/03 解决V2.0.1 遗留问题 + * v2.1.0 2018/01/20 Version 2 稳定发布版 + * Author Date changes + *~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + *XeiTongXueFlyMe 17/06/04 首个版本 + *XeiTongXueFlyMe 17/08/04 增加对TP的支持 + *XeiTongXueFlyMe 17/11/24 增加对多路CAN硬件的收发,和报文处理 + *XeiTongXueFlyMe 17/11/29 增加请求和响应API + *XeiTongXueFlyMe 17/12/07 重做TP接受API函数 + *XeiTongXueFlyMe 17/12/08 增加软件滤波器 + *XeiTongXueFlyMe 18/01/03 重做接受发送API,简化协议栈初始化调用逻辑 + *SummerFalls 20/08/04 简化了宏开关; + 统一自定义类型大小写及_t后缀; + 将多组宏定义分组并改换成枚举类型; + 调整枚举类型变量的命名中相同字段所处的位置, + 例如将 'J1939_CONTROL_BYTE_' 提前, + 方便编辑器快速联想同类型变量; + 将不同CAN节点的相关全局变量使用数组进行管理, + 去除了多个switch代码段所造成的代码重复性高的问题, + 减少了Flash占用,增强了可扩展更多CAN节点的可能性, + 同时增加代码灵活性,尽量避免增减节点时对协议栈主源文件的大量改动; + 注释统一使用 MISRA-C 的标准 C 注释:/* Comment */; + 缩进统一使用空格缩进,避免不同编辑器缩进量差异; + 将本段版本历史记录信息从各个源文件中提取出来,单独存放于 CHANGELOG 文件中。 + **********************************************************************/ + diff --git a/readme.md b/readme.md index cf187da..a67dcce 100644 --- a/readme.md +++ b/readme.md @@ -1,39 +1,39 @@ -# 简述 - 1. 源代码下载: - > https://github.com/XeiTongXueFlyMe/J1939 - 2. 源代码说明书Web站点:(临时,已准备建站,以后分享更多的汽车通信协议) - > https://xeitongxueflyme.github.io/j1939doc.github.io/ - 3. 技术支持群: - > QQ群:264864184 ,为了节约时间成本,群主可以免费为大家解决最新协议栈问题(老版本,群里也有其他工程师为大家解决,群主不做答) +# 简述 -# 历史版本变更 +1. 源代码下载: + > +2. 源代码说明书Web站点:(临时,已准备建站,以后分享更多的汽车通信协议) + > +3. 技术支持群: + > QQ群:264864184 ,为了节约时间成本,群主可以免费为大家解决最新协议栈问题(老版本,群里也有其他工程师为大家解决,群主不做答) + +## 历史版本变更 > 版本说明:V a,b,c - 1. a 代表版本号 - 2. b 代表稳定的版本号 - 3. c 代表基于稳定版本号上功能添加,新的功能不一定稳定 -> 如果是工程使用,建议使用 **V x.x.0** 例如 ***V 1.1.0*** ,***V 2.1.0*** +1. a 代表版本号 +2. b 代表稳定的版本号 +3. c 代表基于稳定版本号上功能添加,新的功能不一定稳定 + +> 如果是工程使用,建议使用 **V x.x.0** 例如 ***V 1.1.0*** ,***V 2.1.0*** -## J1939Socket API Version 2 +### J1939Socket API Version 2 Version | date |Description ------------- | ------------- | ------------- [V2.1.0] |2018/1/20| Version 2.1 稳定发布版。经过实用性测试,Version 2.1相对Version 1.1做了很大的改进,Version 2.1版本更加的偏向于使用,移植更加的简单,架构和注解更加的规范。API(接口)更加人性化,实用化(感谢许多同行的使用反馈)。 [V2.0.1] |2017/12/8| 地址竞争,动态地址分配等J1939网络功能不能使用,本版本为V2.1.0发布前的测试版本。 - -## J1939Socket API Version 1 +### J1939Socket API Version 1 Version | date | Description ------------- | ------------- | ------------- -[V1.1.0] | 2017/11/22 | Version 1.1 稳定发布版。\n * 实现了J1939-21文档规定的功能(数据链路层)。\n * 轻量级(可适应低端的MCU)建议低端的MCU采用本版本移植开发。\n * 使用示例参考附带的readme.md和 \n * 移植示例参考 +[V1.1.0] | 2017/11/22 | Version 1.1 稳定发布版。\n * 实现了J1939-21文档规定的功能(数据链路层)。\n * 轻量级(可适应低端的MCU)建议低端的MCU采用本版本移植开发。\n * 使用示例参考附带的readme.md和 \n * 移植示例参考 [V1.0.1] | 2017/08/04 | 完善功能,增加对TP(长帧,多组)传输的支持,\n 1.增加非阻塞API调用接口 \n * 使用示例参考附带的readme.md和 \n * 移植示例参考 \n * 本文档不对Version 1 进行阐述。 V1.0.0 | 2017/06/04 | 首个开源版本\n 1.增加双模式(轮询或者中断,逻辑更加简单明了)\n 2.可适应低端的MCU \n 3.支持多任务调用接口(可用于嵌入式系统) V0.0.1 | 2017/05/04 | 初建工程\n * 易移植(不针对特定的CAN硬件,只要满足CAN2.0B即可) [V1.1.0]: https://github.com/XeiTongXueFlyMe/J1939/releases/tag/v1.1.0 "V1.1.0下载地址" -[V1.0.1]: https://github.com/XeiTongXueFlyMe/J1939/releases/tag/V1.01 "V1.0.1下载地址" +[V1.0.1]: https://github.com/XeiTongXueFlyMe/J1939/releases/tag/V1.01 "V1.0.1下载地址" [V2.0.1]: https://github.com/XeiTongXueFlyMe/J1939/releases/tag/V2.0.1 "V2.0.1下载地址" [V2.1.0]: https://github.com/XeiTongXueFlyMe/J1939/releases/tag/V2.1.0 "V2.1.0下载地址" - diff --git a/source/J1939.H b/source/J1939.H index d83164f..80e3ec8 100644 --- a/source/J1939.H +++ b/source/J1939.H @@ -1,341 +1,301 @@ -/********************************************************************* - * - * J1939 Main Source Code - * - ********************************************************************* - * - * 本程序是由XieTongXueFlyMe对现有的J1939协议文档分析,和对前辈的贡献总结, - * 写出的一套开源的J1939驱动。 - * 本协议特点: - * 1.易移植(不针对特定的CAN硬件,只要满足CAN2.0B即可) - * 2.轻量级(可适应低端的MCU) - * 3.支持多任务调用接口(可用于嵌入式系统) - * 4.双模式(轮询或者中断,逻辑更加简单明了) - * 5.不掉帧(数据采用收发列队缓存) - * - * 源代码下载: - * https://github.com/XeiTongXueFlyMe/J1939 - * 源代码临时手册Web站点: - * https://xeitongxueflyme.github.io/j1939doc.github.io/ - * - * Version Date Description - * ------------------------------------------------------------------- - * v1.0.0 2017/06/04 首个版本 Version 1 测试版发布 - * v1.0.1 2017/08/04 完善功能 - * v1.1.0 2017/11/22 Version 1 稳定发布版 - * v2.0.1 2017/11/24 Version 2 测试版发布 - * v2.0.2 2018/01/03 解决V2.0.1 遗留问题 - * v2.1.0 2018/01/20 Version 2 稳定发布版 - * Author Date changes - *~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - *XeiTongXueFlyMe 7/06/04 首个版本 - *XeiTongXueFlyMe 7/08/04 增加对TP的支持 - *XeiTongXueFlyMe 7/11/24 增加对多路CAN硬件的收发,和报文处理 - *XeiTongXueFlyMe 7/11/29 增加请求和响应API - *XeiTongXueFlyMe 7/12/07 重做TP接受API函数 - *XeiTongXueFlyMe 7/12/08 增加软件滤波器 - *XeiTongXueFlyMe 8/01/03 重做接受发送API,简化协议栈初始化调用逻辑 - **********************************************************************/ -#ifndef __J1939_H -#define __J1939_H -/******************************类型声明*********************************/ -#define FALSE 0 -#define TRUE 1 +#ifndef __J1939_H +#define __J1939_H + +#include + +/******************************类型声明******************************/ /** 统一类型定义 - * 不同的单片机的编译器, int,short,long 的位数可能不同 + * 不同的单片机的编译器,char,int,short,long 的位数可能不同 * * 在移植J1939协议栈时,首先应该配置这里 */ -typedef unsigned int j1939_uint32_t; /** < 32位无符号整形*/ -typedef int j1939_int32_t; /** < 32位整形*/ -typedef unsigned short j1939_uint16_t; /** < 16位无符号整形*/ -typedef unsigned char j1939_uint8_t; /** < 8位无符号整形*/ -typedef char j1939_int8_t; /** < 8位无符号整形*/ -#define J1939_NULL 0 - -//函数返回代码 -#define RC_SUCCESS 0 /**< 成功*/ -#define RC_QUEUEEMPTY 1 /**< 列队为空*/ -#define RC_QUEUEFULL 1 /**< 列队满*/ -#define RC_CANNOTRECEIVE 2 /**< 不能接收*/ -#define RC_CANNOTTRANSMIT 2 /**< 不能传输*/ -#define RC_PARAMERROR 3 /**< 参数错误*/ - -//内部常量 -#define J1939_FALSE 0 /**< 代表函数错误返回*/ -#define J1939_TRUE 1 /**< 代表函数正确返回*/ - -// J1939 默认的优先级(参考J1939文档) -#define J1939_CONTROL_PRIORITY 0x03 /**< J1939文档默认的优先级*/ -#define J1939_INFO_PRIORITY 0x06 /**< J1939文档默认的优先级*/ -#define J1939_PROPRIETARY_PRIORITY 0x06 /**< J1939文档默认的优先级*/ -#define J1939_REQUEST_PRIORITY 0x06 /**< J1939文档默认的优先级*/ -#define J1939_ACK_PRIORITY 0x06 /**< J1939文档默认的优先级*/ -#define J1939_TP_CM_PRIORITY 0x07 /**< J1939文档默认的优先级*/ -#define J1939_TP_DT_PRIORITY 0x07 /**< J1939文档默认的优先级*/ - -// J1939 定义的地址 -#define J1939_GLOBAL_ADDRESS 255 /**< 全局地址*/ -#define J1939_NULL_ADDRESS 254 /**< 空地址*/ - -//J1939协议栈的PNG请求响应,相关的定义 -#define J1939_PF_REQUEST2 201 /**< J1939协议栈的请求 PF */ -#define J1939_PF_TRANSFER 202 /**< J1939协议栈的转移 PF */ - -#define J1939_PF_REQUEST 234 /**< 请求 或 用于握手机制*/ -#define J1939_PF_ACKNOWLEDGMENT 232 /**< 确认请求 或 用于握手机制*/ - -#define J1939_ACK_CONTROL_BYTE 0 /**< 用于TP(长帧数据),代表确认*/ -#define J1939_NACK_CONTROL_BYTE 1 /**< 用于TP(长帧数据),PNG不被支持。否定消息*/ -#define J1939_ACCESS_DENIED_CONTROL_BYTE 2/**< 拒绝访问,但是信息是被支持,暂时不能响应(需要再次发送请求)*/ -#define J1939_CANNOT_RESPOND_CONTROL_BYTE 3/**< 不能做出反应,有空但是接受的缓存不够,或则发送资源被占领,暂时不能响应(需要再次发送请求)*/ - -//TP协议的一些宏定义 -#define J1939_PF_DT 235 /**< 协议传输---数据传输 PF*/ -#define J1939_PF_TP_CM 236 /**< 协议传输---链接管理 PF*/ - -//TP的超时时间,单位(ms) -#define J1939_TP_Tr 200 /**< 宏定义TP的超时时间*/ -#define J1939_TP_Th 500 /**< 宏定义TP的超时时间*/ -#define J1939_TP_T1 750 /**< 宏定义TP的超时时间*/ -#define J1939_TP_T2 1250 /**< 宏定义TP的超时时间*/ -#define J1939_TP_T3 1250 /**< 宏定义TP的超时时间*/ -#define J1939_TP_T4 1050 /**< 宏定义TP的超时时间*/ -#define J1939_TP_TIMEOUT_NORMAL 0 /**< 未超时正常*/ -#define J1939_TP_TIMEOUT_ABNORMAL 1 /**< 超时*/ -#define J1939_RTS_CONTROL_BYTE 16 /**< TP.CM_RTS*/ -#define J1939_CTS_CONTROL_BYTE 17 /**< TP.CM_CTS*/ -#define J1939_EOMACK_CONTROL_BYTE 19 /**< 消息应答结束*/ -#define J1939_BAM_CONTROL_BYTE 32 /**< 广播公告消息*/ -#define J1939_CONNABORT_CONTROL_BYTE 255 /**< 连接中断控制字节(放弃连接)*/ -#define J1939_RESERVED_BYTE 0xFF /**< 变量的保留位的值*/ - -//与J1939网络层有关的定义 -#define J1939_PGN2_REQ_ADDRESS_CLAIM 0x00 -#define J1939_PGN1_REQ_ADDRESS_CLAIM 0xEA -#define J1939_PGN0_REQ_ADDRESS_CLAIM 0x00 - -#define J1939_PGN2_COMMANDED_ADDRESS 0x00 -#define J1939_PGN1_COMMANDED_ADDRESS 0xFE /**< 命令地址消息*/ -#define J1939_PGN0_COMMANDED_ADDRESS 0xD8 /**< 参考J1939-81 地址命令配置*/ - -#define J1939_PF_ADDRESS_CLAIMED 238 -#define J1939_PF_CANNOT_CLAIM_ADDRESS 238 -#define J1939_PF_PROPRIETARY_A 239 /**< 专用A*/ -#define J1939_PF_PROPRIETARY_B 255 /**< 专用B*/ +typedef uint32_t j1939_uint32_t; /** < 32位无符号整形 */ +typedef int32_t j1939_int32_t; /** < 32位有符号整形 */ +typedef uint16_t j1939_uint16_t; /** < 16位无符号整形 */ +typedef uint8_t j1939_uint8_t; /** < 8位无符号整形 */ +typedef int8_t j1939_int8_t; /** < 8位有符号整形 */ /**< 是否对TP协议的支持(是否支持长帧(大于8字节的数据)的发送与接受)*/ -#define J1939_TP_RX_TX J1939_TRUE +#define J1939_TP_RX_TX J1939_TRUE /**< TP协议的支持的最大接受发送消息长度(最大可配置为1785)*/ #define J1939_TP_MAX_MESSAGE_LENGTH 240 +#define J1939_NULL 0 + +#define J1939_FALSE 0 /**< 代表函数错误返回 */ +#define J1939_TRUE 1 /**< 代表函数正确返回 */ + +/**< 函数返回代码 */ +typedef enum { + RC_SUCCESS = 0, /**< 成功*/ + RC_QUEUEEMPTY = 1, /**< 队列为空*/ + RC_QUEUEFULL = 1, /**< 队列满*/ + RC_CANNOTRECEIVE = 2, /**< 不能接收*/ + RC_CANNOTTRANSMIT = 2, /**< 不能传输*/ + RC_PARAMERROR = 3, /**< 参数错误*/ +} J1939_Status_t; + +/**< J1939 默认的优先级(参考J1939文档) */ +typedef enum { + J1939_PRIORITY_CONTROL = 0x03, /**< J1939文档默认的优先级*/ + J1939_PRIORITY_INFO = 0x06, /**< J1939文档默认的优先级*/ + J1939_PRIORITY_PROPRIETARY = 0x06, /**< J1939文档默认的优先级*/ + J1939_PRIORITY_REQUEST = 0x06, /**< J1939文档默认的优先级*/ + J1939_PRIORITY_ACK = 0x06, /**< J1939文档默认的优先级*/ + J1939_PRIORITY_TP_CM = 0x07, /**< J1939文档默认的优先级*/ + J1939_PRIORITY_TP_DT = 0x07, /**< J1939文档默认的优先级*/ +} J1939_Priority_t; + +/**< J1939协议栈的PNG请求响应,相关的定义 */ +typedef enum { + J1939_PF_REQUEST2 = 201, /**< J1939协议栈的请求 PF */ + J1939_PF_TRANSFER = 202, /**< J1939协议栈的转移 PF */ + J1939_PF_ACKNOWLEDGMENT = 232, /**< 确认请求 或 用于握手机制*/ + J1939_PF_REQUEST = 234, /**< 请求 或 用于握手机制*/ + J1939_PF_TP_DT = 235, /**< TP协议传输---数据传输 PF*/ + J1939_PF_TP_CM = 236, /**< TP协议传输---链接管理 PF*/ + J1939_PF_ADDRESS_CLAIMED = 238, + J1939_PF_CANNOT_CLAIM_ADDRESS = 238, + J1939_PF_PROPRIETARY_A = 239, /**< 专用A*/ + J1939_PF_PROPRIETARY_B = 255, /**< 专用B*/ +} J1939_PDUFormat_t; + +/**< PF(PDUFormat)小于 240 时,PS(PDUSpecific)为 DA(DestinationAddress) */ +typedef enum { + J1939_PS_DA_GLOBAL = 255, /**< 全局地址*/ + J1939_PS_DA_NULL = 254, /**< 空地址*/ +} J1939_PDUSpecific_DA_t; + +typedef enum { + J1939_CONTROL_BYTE_ACK = 0, /**< 用于TP(长帧数据),代表确认*/ + J1939_CONTROL_BYTE_NACK = 1, /**< 用于TP(长帧数据),PNG不被支持。否定消息*/ + J1939_CONTROL_BYTE_ACCESS_DENIED = 2, /**< 拒绝访问,但是信息是被支持,暂时不能响应(需要再次发送请求)*/ + J1939_CONTROL_BYTE_CANNOT_RESPOND = 3, /**< 不能做出反应,有空但是接受的缓存不够,或则发送资源被占领,暂时不能响应(需要再次发送请求)*/ + J1939_CONTROL_BYTE_RTS = 16, /**< TP.CM_RTS*/ + J1939_CONTROL_BYTE_CTS = 17, /**< TP.CM_CTS*/ + J1939_CONTROL_BYTE_EOMACK = 19, /**< 消息应答结束*/ + J1939_CONTROL_BYTE_BAM = 32, /**< 广播公告消息*/ + J1939_CONTROL_BYTE_CONNABORT = 255, /**< 连接中断控制字节(放弃连接)*/ + /* CONTROL BYTE RESERVED BELOW */ + J1939_CONTROL_BYTE_RESERVED = 0xFF, /**< 变量的保留位的值*/ +} J1939_CONTROL_BYTE_t; + +/**< TP的超时时间,单位(ms) */ +typedef enum { + J1939_TP_Tr = 200, + J1939_TP_Th = 500, + J1939_TP_T1 = 750, + J1939_TP_T2 = 1250, + J1939_TP_T3 = 1250, + J1939_TP_T4 = 1050, +} J1939_TP_TIMEOUT_t; + +#define J1939_TP_TIMEOUT_NORMAL 0 /**< 未超时正常*/ +#define J1939_TP_TIMEOUT_ABNORMAL 1 /**< 超时*/ + +/**< 与J1939网络层有关的定义 */ +#define J1939_PGN0_REQ_ADDRESS_CLAIM 0x00 +#define J1939_PGN1_REQ_ADDRESS_CLAIM 0xEA +#define J1939_PGN2_REQ_ADDRESS_CLAIM 0x00 + +#define J1939_PGN0_COMMANDED_ADDRESS 0xD8 /**< 参考J1939-81 地址命令配置*/ +#define J1939_PGN1_COMMANDED_ADDRESS 0xFE /**< 命令地址消息*/ +#define J1939_PGN2_COMMANDED_ADDRESS 0x00 + /**CAN节点的选择枚举 -* -* 默认支持最大4路CAN硬件\n -*/ -typedef enum -{ - Select_CAN_NODE_Null, /**< 不选择任何CAN硬件*/ - Select_CAN_NODE_1, /**< 选择CAN硬件 1*/ - Select_CAN_NODE_2, /**< 选择CAN硬件 2*/ - Select_CAN_NODE_3, /**< 选择CAN硬件 3*/ - Select_CAN_NODE_4, /**< 选择CAN硬件 4*/ -}CAN_NODE; + * + * 默认支持最大4路CAN硬件\n + */ +typedef enum { + Select_CAN_NODE_1, /**< 选择CAN硬件 1*/ + Select_CAN_NODE_2, /**< 选择CAN硬件 2*/ + Select_CAN_NODE_3, /**< 选择CAN硬件 3*/ + Select_CAN_NODE_4, /**< 选择CAN硬件 4*/ + Select_CAN_NODE_Null, /**< 不选择任何CAN硬件*/ +} CAN_NODE_t; #if J1939_TP_RX_TX /**TP的状态描述枚举 -* -*/ -typedef enum -{ - J1939_TP_NULL, /**< 长数据传输处于空闲,只有TP系统处于空闲,才能用处理下一个发送,和接受请求*/ - J1939_TP_RX, /**< 长数据传输处于接收*/ - J1939_TP_TX, /**< 长数据传输处于发送*/ - J1939_TP_OSBUSY,/**< 长数据传输处于繁忙,比如刚接受一整段长数据,但是CPU没来得处理,又一个长数据请求到来,为了数据不被覆盖,将状态设为本值*/ -}J1939_TP_State; + * + */ +typedef enum { + J1939_TP_NULL, /**< 长数据传输处于空闲,只有TP系统处于空闲,才能用处理下一个发送,和接受请求*/ + J1939_TP_RX, /**< 长数据传输处于接收*/ + J1939_TP_TX, /**< 长数据传输处于发送*/ + J1939_TP_OSBUSY, /**< 长数据传输处于繁忙,比如刚接受一整段长数据,但是CPU没来得处理,又一个长数据请求到来,为了数据不被覆盖,将状态设为本值*/ +} J1939_TP_STATE_t; + /**TP的标志位结构体 -* -* 本结构体记录了TP的状态,使用TP发送和接受的CAN硬件编号 -*/ -typedef struct -{ - J1939_TP_State state; /**< TP的连接状态*/ - CAN_NODE TP_RX_CAN_NODE; /**< TP接受请求产生的 CAN硬件编号*/ - CAN_NODE TP_TX_CAN_NODE; /**< TP接受发送产生的 CAN硬件编号*/ -}J1939_TP_Flags; + * + * 本结构体记录了TP的状态,使用TP发送和接受的CAN硬件编号 + */ +typedef struct { + J1939_TP_STATE_t state; /**< TP的连接状态*/ + CAN_NODE_t TP_RX_CAN_NODE; /**< TP接受请求产生的 CAN硬件编号*/ + CAN_NODE_t TP_TX_CAN_NODE; /**< TP接受发送产生的 CAN硬件编号*/ +} J1939_TP_FLAGS_t; + /**J1939消息对象的结构体 -* -* 本结构体实现了 J1939的消息对象 -*/ -typedef struct -{ - j1939_uint32_t PGN ; /**< J1939的消息对象的 PGN*/ - j1939_uint8_t data[J1939_TP_MAX_MESSAGE_LENGTH] ;/**< J1939的消息对象的 数据*/ - j1939_uint16_t byte_count;/**< J1939的消息对象的 数据大小*/ - j1939_uint8_t SA; /**< J1939的消息对象的 目标地址(发送目的地 或 接受来源地)*/ - -} J1939_MESSAGE_T ; + * + * 本结构体实现了 J1939的消息对象 + */ +typedef struct { + j1939_uint32_t PGN; /**< J1939的消息对象的 PGN*/ + j1939_uint8_t data[J1939_TP_MAX_MESSAGE_LENGTH]; /**< J1939的消息对象的 数据*/ + j1939_uint16_t byte_count; /**< J1939的消息对象的 数据大小*/ + j1939_uint8_t SA; /**< J1939的消息对象的 目标地址(发送目的地 或 接受来源地)*/ +} J1939_TP_MESSAGE_t; + /**J1939消息对象的结构体 -* -* 本结构体实现了 J1939的多帧消息对象 -*/ -typedef struct -{ - j1939_uint8_t *data; /**< 缓存区指针*/ - j1939_uint16_t data_num; /**< 缓存区大小*/ - j1939_uint8_t SA; /**< J1939的消息对象的 数据 源地址*/ - j1939_uint16_t byte_count; /**< J1939的消息对象的 数据大小*/ - j1939_uint32_t PGN ; /**< J1939的消息对象的 PGN*/ -}TP_RX_MESSAGE; -/**J1939_TP_Tx_Step枚举 -* -* 实现了记录长帧(多帧)传输的TX 的步骤 -*/ -typedef enum -{ - J1939_TP_TX_WAIT, - J1939_TP_TX_CM_START, - J1939_TP_TX_CM_WAIT, - J1939_TP_TX_DT, - J1939_TP_WAIT_ACK, - J1939_TP_TX_ERROR, - J1939_TX_DONE, -}J1939_TP_Tx_Step;//协议的发送步骤 -/**J1939_TRANSPORT_TX_INFO 结构体 -* -* 实现了长帧传输中产生的临时数据,和一些传输交换数据 -*/ -typedef struct -{ - J1939_MESSAGE_T tp_tx_msg; /**< J1939的消息对象*/ - j1939_uint16_t time; /**< 时间*/ - j1939_uint8_t packet_offset_p; /**< 数据包偏移指针*/ - j1939_uint8_t packets_total; /**< 总共有多少个数据包*/ - j1939_uint8_t packets_request_num; /**< 请求发送的数据包数(接受方准备接受的数据包数)*/ - J1939_TP_Tx_Step state ; /**< 协议的发送步骤*/ -} J1939_TRANSPORT_TX_INFO; -/**J1939_TP_Rx_Step枚举 -* -* 实现了记录长帧(多帧)传输的RX 的步骤 -*/ -typedef enum -{ - J1939_TP_RX_WAIT, - J1939_TP_RX_READ_DATA, - J1939_TP_RX_DATA_WAIT, - J1939_TP_RX_ERROR, - J1939_RX_DONE, -}J1939_TP_Rx_Step;//协议的接收步骤 - -/**J1939_TRANSPORT_RX_INFO 结构体 -* -* 实现了长帧传输中产生的临时数据,和一些传输交换数据 -*/ -typedef struct -{ - J1939_MESSAGE_T tp_rx_msg; /**< J1939的消息对象*/ - j1939_uint8_t osbusy; /**< 此位置1,代表系统繁忙,cpu需要处理其他的事物,直接拒绝一切的链接请求\n 如果正在接受中,此位置1,则会发出链接保持消息帧。*/ - j1939_uint16_t time; /**< 时间*/ - j1939_uint8_t packets_total; /**< 总共有多少个数据包*/ - j1939_uint8_t packets_ok_num;/**< 已经接受的数据包数*/ - J1939_TP_Rx_Step state ; /**< 协议的接受步骤*/ -} J1939_TRANSPORT_RX_INFO; - -#endif //J1939_TP_RX_TX + * + * 本结构体实现了 J1939的多帧消息对象 + */ +typedef struct { + j1939_uint8_t *data; /**< 缓存区指针*/ + j1939_uint16_t data_num; /**< 缓存区大小*/ + j1939_uint8_t SA; /**< J1939的消息对象的 数据 源地址*/ + j1939_uint16_t byte_count; /**< J1939的消息对象的 数据大小*/ + j1939_uint32_t PGN; /**< J1939的消息对象的 PGN*/ +} TP_RX_MESSAGE_t; + +/**J1939_TP_TX_STEP_t 枚举 + * + * 实现了记录长帧(多帧)传输的TX 的步骤 + */ +typedef enum { + J1939_TP_TX_WAIT, + J1939_TP_TX_CM_START, + J1939_TP_TX_CM_WAIT, + J1939_TP_TX_DT, + J1939_TP_WAIT_ACK, + J1939_TP_TX_ERROR, + J1939_TX_DONE, +} J1939_TP_TX_STEP_t; /* 协议的发送步骤 */ + +/**J1939_TRANSPORT_TX_INFO_t 结构体 + * + * 实现了长帧传输中产生的临时数据,和一些传输交换数据 + */ +typedef struct { + J1939_TP_MESSAGE_t tp_tx_msg; /**< J1939的消息对象*/ + j1939_uint16_t time; /**< 时间*/ + j1939_uint8_t packet_offset_p; /**< 数据包偏移指针*/ + j1939_uint8_t packets_total; /**< 总共有多少个数据包*/ + j1939_uint8_t packets_request_num; /**< 请求发送的数据包数(接受方准备接受的数据包数)*/ + J1939_TP_TX_STEP_t state; /**< 协议的发送步骤*/ +} J1939_TRANSPORT_TX_INFO_t; + +/**J1939_TP_RX_STEP_t 枚举 + * + * 实现了记录长帧(多帧)传输的RX 的步骤 + */ +typedef enum { + J1939_TP_RX_WAIT, + J1939_TP_RX_READ_DATA, + J1939_TP_RX_DATA_WAIT, + J1939_TP_RX_ERROR, + J1939_RX_DONE, +} J1939_TP_RX_STEP_t; /* 协议的接收步骤 */ + +/**J1939_TRANSPORT_RX_INFO_t 结构体 + * + * 实现了长帧传输中产生的临时数据,和一些传输交换数据 + */ +typedef struct { + J1939_TP_MESSAGE_t tp_rx_msg; /**< J1939的消息对象*/ + j1939_uint8_t osbusy; /**< 此位置1,代表系统繁忙,cpu需要处理其他的事物,直接拒绝一切的链接请求\n 如果正在接受中,此位置1,则会发出链接保持消息帧。*/ + j1939_uint16_t time; /**< 时间*/ + j1939_uint8_t packets_total; /**< 总共有多少个数据包*/ + j1939_uint8_t packets_ok_num; /**< 已经接受的数据包数*/ + J1939_TP_RX_STEP_t state; /**< 协议的接受步骤*/ +} J1939_TRANSPORT_RX_INFO_t; + +#endif /* J1939_TP_RX_TX */ /** -* @note 实现Request_PGN 的响应 -*/ -struct Request_List{ - j1939_uint8_t *data; - j1939_uint16_t lenght; - j1939_uint32_t PGN; - CAN_NODE Can_Node; - void (*update)(); /**< 在函数里需要对data更新,如果不用更新data赋值为J1939_NULL*/ - struct Request_List *next; /**< 链表末尾,需要一直保持J1939_NULL*/ + * @note 实现Request_PGN 的响应 + */ +struct RequestList { + j1939_uint8_t *data; + j1939_uint16_t length; + j1939_uint32_t PGN; + CAN_NODE_t Can_Node; + void (*update)(); /**< 在函数里需要对data更新,如果不用更新data赋值为J1939_NULL*/ + struct RequestList *next; /**< 链表末尾,需要一直保持J1939_NULL*/ }; -// J1939 Data Structures -// J1939_MESSAGE_STRUCT旨在J1939消息块映射到设备的地址映射。 只有字段PDU格式不映射到设备寄存器。 -// 结构应该简单地使用PDUFormat和忽视PDUFormat_Top。调整将立即接收和传输之前。 -// 注:编译器创建结构从低一点的位置高一些位置,所以可能出现不匹配的设备寄存器。 -#define J1939_MSG_LENGTH 9 //消息长度 -#define J1939_DATA_LENGTH 8 //数据长度 +/* J1939 Data Structures */ +/* J1939_MESSAGE_STRUCT旨在J1939消息块映射到设备的地址映射。 只有字段PDU格式不映射到 */ +/* 结构应该简单地使用PDUFormat和忽视PDUFormat_Top。调整将立即接收和传输之前 */ +/* 注:编译器创建结构从低一点的位置高一些位置,所以可能出现不匹配的设备寄存器 */ +#define J1939_MSG_LENGTH 9 /* 消息长度 */ +#define J1939_DATA_LENGTH 8 /* 数据长度 */ /** J1939_MESSAGE_UNION 结构体 -* 实现了J1939消息对象 -* -* -*/ -union J1939_MESSAGE_UNION -{ -/** j1939 的 ID 组成结构体 -* -*/ - struct j1939_PID - { - j1939_uint8_t DataPage : 1; /**< 数据页*/ - j1939_uint8_t Res : 1; /**< Res位*/ - j1939_uint8_t Priority : 3; /**< 优先级*/ - j1939_uint8_t Reserve : 3; /**< 空闲*/ - j1939_uint8_t PDUFormat; /**< PF*/ - j1939_uint8_t PDUSpecific; /**< PS*/ - j1939_uint8_t SourceAddress; /**< SA*/ - j1939_uint8_t DataLength : 4; /**< 数据长度*/ - j1939_uint8_t RTR : 4; /**< RTR位*/ - j1939_uint8_t Data[J1939_DATA_LENGTH]; /**< 数据*/ - j1939_uint32_t PGN :24; /**< 参数群编号*/ - j1939_uint32_t ReservePGN : 8; /**< 空闲*/ - }; - struct j1939_PID Mxe; /**< j1939 的 ID 组成结构体*/ - j1939_uint8_t Array[J1939_MSG_LENGTH + J1939_DATA_LENGTH]; /**< 联合体数组,方便快速处理结构体赋值*/ -}; + * + * 实现了J1939消息对象 + */ +typedef union J1939_MESSAGE_UNION { + /** J1939 的 ID 组成结构体 + * + */ + struct J1939_PID { + j1939_uint8_t DataPage : 1; /**< 数据页*/ + j1939_uint8_t Res : 1; /**< Res位*/ + j1939_uint8_t Priority : 3; /**< 优先级*/ + j1939_uint8_t : 3; /**< 空闲*/ + j1939_uint8_t PDUFormat; /**< PF*/ + j1939_uint8_t PDUSpecific; /**< PS*/ + j1939_uint8_t SourceAddress; /**< SA*/ + j1939_uint8_t DataLength : 4; /**< 数据长度*/ + j1939_uint8_t RTR : 4; /**< RTR位*/ + j1939_uint8_t Data[J1939_DATA_LENGTH]; /**< 数据*/ + j1939_uint32_t PGN : 24; /**< 参数群编号*/ + j1939_uint32_t : 8; /**< 空闲*/ + } Mxe; /**< J1939 的 ID 组成结构体*/ + j1939_uint8_t Array[J1939_MSG_LENGTH + J1939_DATA_LENGTH]; /**< 联合体数组,方便快速处理结构体赋值*/ +} J1939_MESSAGE_t; -#define GroupExtension PDUSpecific -#define DestinationAddress PDUSpecific /** 一个宏定义,具体变量名称作用命名 -* -*/ -typedef union J1939_MESSAGE_UNION J1939_MESSAGE; - -union J1939_FLAGS_UNION -{ - struct - { - j1939_uint8_t TransmitMessagesdCover : 1; //发送数据时,J1939协议接受缓存有数据覆盖 - j1939_uint8_t ReceivedMessagesdCoverOrDroppedNode : 3; - j1939_uint8_t ReceivedMessagesdCover : 1; //接受数据时,J1939协议接受缓存有数据覆盖 - j1939_uint8_t ReceivedMessagesDropped : 1; //接受数据时,J1939协议接受缓存有数据溢出 - }; - j1939_uint8_t FlagVal; -}; - -typedef union J1939_FLAGS_UNION J1939_FLAG; - -/********************************************API**************************************************************/ - -//初始化函数 -extern void J1939_Initialization( ); -//CAN驱动收发中断入口 -extern void J1939_ISR( ); -//心跳函数,定时被调用 -extern void J1939_Poll( ); -//读取单帧消息 -extern j1939_uint8_t J1939_Read_Message( J1939_MESSAGE *MsgPtr, CAN_NODE _Can_Node); -//发送单帧消息 -extern j1939_uint8_t J1939_Send_Message( J1939_MESSAGE *MsgPtr, CAN_NODE _Can_Node); -//多帧(多组)消息发送函数 (RTS/CTS传输协议) -extern j1939_int8_t J1939_TP_TX_Message(j1939_uint32_t PGN, j1939_uint8_t DA, j1939_uint8_t *data, j1939_uint16_t data_num, CAN_NODE _Can_Node); -//多帧(多组)消息接受函数 (RTS/CTS传输协议) -extern j1939_int8_t J1939_TP_RX_Message(TP_RX_MESSAGE *msg, CAN_NODE _Can_Node); -//请求获去一个PGN -extern void J1939_Request_PGN(j1939_uint32_t pgn ,j1939_uint8_t DA, CAN_NODE _Can_Node); -//创建一个PGN响应 -extern void J1939_Create_Response(j1939_uint8_t data[], j1939_uint16_t dataLenght, j1939_uint32_t PGN, void (*dataUPFun)(), CAN_NODE _Can_Node); - - -#endif //__J1939_H - - - + * + */ +#define GroupExtension PDUSpecific +#define DestinationAddress PDUSpecific + +typedef union J1939_FLAGS_UNION { + struct { + j1939_uint8_t TransmitMessagesdCover : 1; /* 发送数据时,J1939协议接受缓存有数据覆盖 */ + j1939_uint8_t ReceivedMessagesdCoverOrDroppedNode : 3; + j1939_uint8_t ReceivedMessagesdCover : 1; /* 接受数据时,J1939协议接受缓存有数据覆盖 */ + j1939_uint8_t ReceivedMessagesDropped : 1; /* 接受数据时,J1939协议接受缓存有数据溢出 */ + }; + j1939_uint8_t FlagVal; +} J1939_FLAG_t; + +/******************************API******************************/ + +/* 初始化函数 */ +extern void J1939_Initialization(void); +/* CAN驱动收发中断入口 */ +extern void J1939_ISR(void); +/* 心跳函数,定时被调用 */ +extern void J1939_Poll(void); +/* 读取单帧消息 */ +extern J1939_Status_t J1939_Read_Message(J1939_MESSAGE_t *MsgPtr, CAN_NODE_t _Can_Node); +/* 发送单帧消息 */ +extern J1939_Status_t J1939_Send_Message(J1939_MESSAGE_t *MsgPtr, CAN_NODE_t _Can_Node); +#if J1939_TP_RX_TX +/* 多帧(多组)消息发送函数 (RTS/CTS传输协议) */ +extern J1939_Status_t J1939_TP_TX_Message(j1939_uint32_t PGN, j1939_uint8_t DA, j1939_uint8_t *data, + j1939_uint16_t data_num, CAN_NODE_t _Can_Node); +/* 多帧(多组)消息接受函数 (RTS/CTS传输协议) */ +extern J1939_Status_t J1939_TP_RX_Message(TP_RX_MESSAGE_t *msg, CAN_NODE_t _Can_Node); +/* 请求获去一个PGN */ +extern void J1939_Request_PGN(j1939_uint32_t PGN, j1939_uint8_t DA, CAN_NODE_t _Can_Node); +/* 创建一个PGN响应 */ +extern void J1939_Create_Response(j1939_uint8_t data[], j1939_uint16_t dataLength, j1939_uint32_t PGN, + void (*dataUPFun)(), CAN_NODE_t _Can_Node); +#endif /* J1939_TP_RX_TX */ + +#endif /* __J1939_H */ diff --git a/source/J1939.c b/source/J1939.c index 2a7de29..74f8a6a 100644 --- a/source/J1939.c +++ b/source/J1939.c @@ -1,464 +1,233 @@ -/********************************************************************* - * - * J1939 Main Source Code - * - ********************************************************************* - * - * 本程序是由XieTongXueFlyMe对现有的J1939协议文档分析,和对前辈的贡献总结, - * 写出的一套开源的J1939驱动。 - * 本协议特点: - * 1.易移植(不针对特定的CAN硬件,只要满足CAN2.0B即可) - * 2.轻量级(可适应低端的MCU) - * 3.支持多任务调用接口(可用于嵌入式系统) - * 4.双模式(轮询或者中断,逻辑更加简单明了) - * 5.不掉帧(数据采用收发列队缓存) - * - * 源代码下载: - * https://github.com/XeiTongXueFlyMe/J1939 - * 源代码临时手册Web站点: - * https://xeitongxueflyme.github.io/j1939doc.github.io/ - * - * Version Date Description - * ------------------------------------------------------------------- - * v1.0.0 2017/06/04 首个版本 Version 1 测试版发布 - * v1.0.1 2017/08/04 完善功能 - * v1.1.0 2017/11/22 Version 1 稳定发布版 - * v2.0.1 2017/11/24 Version 2 测试版发布 - * v2.0.2 2018/01/03 解决V2.0.1 遗留问题 - * v2.1.0 2018/01/20 Version 2 稳定发布版 - * Author Date changes - *~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - *XeiTongXueFlyMe 7/06/04 首个版本 - *XeiTongXueFlyMe 7/08/04 增加对TP的支持 - *XeiTongXueFlyMe 7/11/24 增加对多路CAN硬件的收发,和报文处理 - *XeiTongXueFlyMe 7/11/29 增加请求和响应API - *XeiTongXueFlyMe 7/12/07 重做TP接受API函数 - *XeiTongXueFlyMe 7/12/08 增加软件滤波器 - *XeiTongXueFlyMe 8/01/03 重做接受发送API,简化协议栈初始化调用逻辑 - **********************************************************************/ -#ifndef __J1939_SOURCE -#define __J1939_SOURCE -#endif +#include -#include "J1939.H" -#include "J1939_config.H" +#include "J1939.h" +#include "J1939_Config.h" -#define J1939_TRUE 1 /**< 代表函数正确返回*/ -#define J1939_FALSE 0 /**< 代表函数错误返回*/ -#define ADDRESS_CLAIM_TX 1 /**< 进入地址竞争发送处理模式*/ -#define ADDRESS_CLAIM_RX 2 /**< 进入地址竞争接受处理模式*/ +#define ADDRESS_CLAIM_TX 1 /**< 进入地址竞争发送处理模式*/ +#define ADDRESS_CLAIM_RX 2 /**< 进入地址竞争接受处理模式*/ -//全局变量。 /** 设备的标称符 - * - * 我们需要在"J1939_config.H"中配置 - * @note 在初始化中赋值,赋值参考参考1939-81文档 + * + * 我们需要在"J1939_Config.h"中配置 + * @note 在初始化中赋值,赋值参考参考J1939-81文档 */ -j1939_uint8_t CA_Name[J1939_DATA_LENGTH]; -j1939_uint8_t CommandedAddress; - -j1939_uint8_t J1939_Address; -J1939_FLAG J1939_Flags; -J1939_MESSAGE OneMessage; -CAN_NODE Can_Node; -//节点地址 -j1939_uint8_t NodeAddress_1; -j1939_uint8_t NodeAddress_2; -j1939_uint8_t NodeAddress_3; -j1939_uint8_t NodeAddress_4; -//接受列队全局变量(CAN_NODE_1) -j1939_uint8_t RXHead_1; -j1939_uint8_t RXTail_1; -j1939_uint8_t RXQueueCount_1; -J1939_MESSAGE RXQueue_1[J1939_RX_QUEUE_SIZE]; -//发送列队全局变量 (CAN_NODE_1) -j1939_uint8_t TXHead_1; -j1939_uint8_t TXTail_1; -j1939_uint8_t TXQueueCount_1; -J1939_MESSAGE TXQueue_1[J1939_TX_QUEUE_SIZE]; -//接受列队全局变量(CAN_NODE_2) -j1939_uint8_t RXHead_2; -j1939_uint8_t RXTail_2; -j1939_uint8_t RXQueueCount_2; -J1939_MESSAGE RXQueue_2[J1939_RX_QUEUE_SIZE]; -//发送列队全局变量 (CAN_NODE_2) -j1939_uint8_t TXHead_2; -j1939_uint8_t TXTail_2; -j1939_uint8_t TXQueueCount_2; -J1939_MESSAGE TXQueue_2[J1939_TX_QUEUE_SIZE]; -//接受列队全局变量(CAN_NODE_3) -j1939_uint8_t RXHead_3; -j1939_uint8_t RXTail_3; -j1939_uint8_t RXQueueCount_3; -J1939_MESSAGE RXQueue_3[J1939_RX_QUEUE_SIZE]; -//发送列队全局变量 (CAN_NODE_3) -j1939_uint8_t TXHead_3; -j1939_uint8_t TXTail_3; -j1939_uint8_t TXQueueCount_3; -J1939_MESSAGE TXQueue_3[J1939_TX_QUEUE_SIZE]; -//接受列队全局变量(CAN_NODE_4) -j1939_uint8_t RXHead_4; -j1939_uint8_t RXTail_4; -j1939_uint8_t RXQueueCount_4; -J1939_MESSAGE RXQueue_4[J1939_RX_QUEUE_SIZE]; -//发送列队全局变量 (CAN_NODE_4) -j1939_uint8_t TXHead_4; -j1939_uint8_t TXTail_4; -j1939_uint8_t TXQueueCount_4; -J1939_MESSAGE TXQueue_4[J1939_TX_QUEUE_SIZE]; - -struct Request_List REQUEST_LIST; +j1939_uint8_t CA_Name[J1939_DATA_LENGTH]; +j1939_uint8_t CommandedAddress; + +j1939_uint8_t J1939_Address; +J1939_FLAG_t J1939_Flags; +J1939_MESSAGE_t OneMessage; +CAN_NODE_t Can_Node; + +/* 节点地址 */ +j1939_uint8_t NodeAddress[J1939_NODE_NUM]; + +/* 接受队列全局变量(CAN_NODE) */ +j1939_uint8_t RXHead [J1939_NODE_NUM]; +j1939_uint8_t RXTail [J1939_NODE_NUM]; +j1939_uint8_t RXQueueCount [J1939_NODE_NUM]; +J1939_MESSAGE_t RXQueue [J1939_NODE_NUM][J1939_RX_QUEUE_SIZE]; + +/* 发送队列全局变量 (CAN_NODE) */ +j1939_uint8_t TXHead [J1939_NODE_NUM]; +j1939_uint8_t TXTail [J1939_NODE_NUM]; +j1939_uint8_t TXQueueCount [J1939_NODE_NUM]; +J1939_MESSAGE_t TXQueue [J1939_NODE_NUM][J1939_TX_QUEUE_SIZE]; + +struct RequestList REQUEST_LIST; #if J1939_TP_RX_TX -//TP协议全局变量 -J1939_TP_Flags J1939_TP_Flags_t; -J1939_TRANSPORT_RX_INFO TP_RX_MSG; -J1939_TRANSPORT_TX_INFO TP_TX_MSG; -#endif //J1939_TP_RX_TX +/* TP协议全局变量 */ +J1939_TP_FLAGS_t J1939_TP_Flags_t; +J1939_TRANSPORT_RX_INFO_t TP_RX_MSG; +J1939_TRANSPORT_TX_INFO_t TP_TX_MSG; + +/* 声明TP轮询函数 */ +static void J1939_TP_Poll(void); +#endif /* J1939_TP_RX_TX */ -static void J1939_ReceiveMessages( void ); -static j1939_uint8_t J1939_TransmitMessages( void ); +static void J1939_ReceiveMessages(void); +static J1939_Status_t J1939_TransmitMessages(void); +static void J1939_Response(const j1939_uint32_t PGN); /** -* @note 硬件滤波器2 或 软件滤波器 滤波配置(设置PS段)\n -*/ -void SetAddressFilter( j1939_uint8_t Address ) -{ - /*软件滤波*/ + * @note 硬件滤波器2 或 软件滤波器 滤波配置(设置PS段)\n + */ +void SetAddressFilter(j1939_uint8_t Address) +{ + /* 软件滤波 */ #if J1939SoftwareFilterEn == J1939_TRUE - switch (Can_Node) - { - case Select_CAN_NODE_1: - { - NodeAddress_1 = Address; - break; - } - case Select_CAN_NODE_2: - { - NodeAddress_2 = Address; - break; - } - case Select_CAN_NODE_3: - { - NodeAddress_3 = Address; - break; - } - case Select_CAN_NODE_4: - { - NodeAddress_4 = Address; - break; - } - default : - { - break; - } - } -#endif//J1939SoftwareFilterEn - /*硬件滤波*/ - Port_SetAddressFilter(Address); -} + NodeAddress[Can_Node] = Address; +#endif /* J1939SoftwareFilterEn */ + + /* 硬件滤波 */ + Port_SetAddressFilter(Address); +} /** -* @param[in] J1939_MESSAGE * -* @note 发送*MsgPtr的信息,所有的数据字段(比如数据长度、优先级、和源地址)必须已经设置。\n -*/ -void SendOneMessage( J1939_MESSAGE *MsgPtr ) -{ - //设置消息的最后部分,确保DataLength规范。(参考CAN B2.0) - MsgPtr->Mxe.Res = 0;//参考J1939的数据链路层(SAE J1939-21) - MsgPtr->Mxe.RTR = 0; - if (MsgPtr->Mxe.DataLength > 8) - MsgPtr->Mxe.DataLength = 8; - //发送一帧消息,将 J1939_MESSAGE 中的所有消息加载道can模块自有的结构中 - Port_CAN_Transmit(MsgPtr); -} + * @param[in] J1939_MESSAGE * + * @note 发送*MsgPtr的信息,所有的数据字段(比如数据长度、优先级、和源地址)必须已经设置。\n + */ +void SendOneMessage(J1939_MESSAGE_t *MsgPtr) +{ + /* 设置消息的最后部分,确保DataLength规范。(参考CAN 2.0B) */ + MsgPtr->Mxe.Res = 0; /* 参考J1939的数据链路层(SAE J1939-21) */ + MsgPtr->Mxe.RTR = 0; + + if (MsgPtr->Mxe.DataLength > 8) { + MsgPtr->Mxe.DataLength = 8; + } + + /* 发送一帧消息,将 J1939_MESSAGE 中的所有消息加载道can模块自有的结构中 */ + Port_CAN_Transmit(MsgPtr); +} /** -* @param[in] MsgPtr 用户要出队的消息 -* @param[in] _Can_Node 要出队的CAN硬件编号 -* @return RC_SUCCESS 消息出队成功 -* @return RC_QUEUEEMPTY 没有消息返回 -* @note 从接受队列中读取一个信息到*MsgPtr。如果我们用的是中断,需要将中断失能,在获取接受队列数据时 -*/ -j1939_uint8_t J1939_DequeueMessage( J1939_MESSAGE *MsgPtr, CAN_NODE _Can_Node) -{ - j1939_uint8_t _rc = RC_SUCCESS; - - //***************************关接受中断******************************** - #if J1939_POLL_ECAN == J1939_FALSE + * @param[in] MsgPtr 用户要出队的消息 + * @param[in] _Can_Node 要出队的CAN硬件编号 + * @return RC_SUCCESS 消息出队成功 + * @return RC_QUEUEEMPTY 没有消息返回 + * @note 从接受队列中读取一个信息到*MsgPtr。如果我们用的是中断,需要将中断失能,在获取接受队列数据时 + */ +J1939_Status_t J1939_DequeueMessage(J1939_MESSAGE_t *MsgPtr, CAN_NODE_t _Can_Node) +{ + J1939_Status_t _rc = RC_SUCCESS; + + /*************************关接受中断*************************/ Port_RXinterruptDisable(); - #endif - switch (_Can_Node) - { - case Select_CAN_NODE_1: - { - if (RXQueueCount_1 == 0) - { - _rc = RC_QUEUEEMPTY; - } - else - { - *MsgPtr = RXQueue_1[RXHead_1]; - RXHead_1 ++; - if (RXHead_1 >= J1939_RX_QUEUE_SIZE) - RXHead_1 = 0; - RXQueueCount_1 --; - } - break; - } - case Select_CAN_NODE_2: - { - if (RXQueueCount_2 == 0) - { - _rc = RC_QUEUEEMPTY; - } - else - { - *MsgPtr = RXQueue_2[RXHead_2]; - RXHead_2 ++; - if (RXHead_2 >= J1939_RX_QUEUE_SIZE) - RXHead_2 = 0; - RXQueueCount_2 --; - } - break; - } - case Select_CAN_NODE_3: - { - if (RXQueueCount_3 == 0) - { - _rc = RC_QUEUEEMPTY; - } - else - { - *MsgPtr = RXQueue_3[RXHead_3]; - RXHead_3 ++; - if (RXHead_3 >= J1939_RX_QUEUE_SIZE) - RXHead_3 = 0; - RXQueueCount_3 --; - } - break; - } - case Select_CAN_NODE_4: - { - if (RXQueueCount_4 == 0) - { - _rc = RC_QUEUEEMPTY; - } - else - { - *MsgPtr = RXQueue_4[RXHead_4]; - RXHead_4 ++; - if (RXHead_4 >= J1939_RX_QUEUE_SIZE) - RXHead_4 = 0; - RXQueueCount_4 --; - } - break; - } - default : - { - _rc = RC_CANNOTRECEIVE; - break; - } - } - //***************************开接受中断******************************** -#if J1939_POLL_ECAN == J1939_FALSE - Port_RXinterruptEnable(); -#endif - return _rc; + if (_Can_Node < J1939_NODE_NUM) { + if (RXQueueCount[_Can_Node] == 0) { + _rc = RC_QUEUEEMPTY; + } else { + *MsgPtr = RXQueue[_Can_Node][RXHead[_Can_Node]]; + RXHead[_Can_Node]++; + + if (RXHead[_Can_Node] >= J1939_RX_QUEUE_SIZE) { + RXHead[_Can_Node] = 0; + } + + RXQueueCount[_Can_Node]--; + } + } else { + /* 若 _Can_Node 索引超过当前协议栈支持节点数,则返回 RC_CANNOTRECEIVE */ + _rc = RC_CANNOTRECEIVE; + } + + /*************************开接受中断*************************/ + Port_RXinterruptEnable(); + + return _rc; } + /** -* @param[in] MsgPtr 存储读取消息的缓存 -* @param[in] _Can_Node 读取消息的CAN硬件编号(从哪一路CAN读取数据) -* @return RC_SUCCESS 读取消息成功, -* @return RC_QUEUEEMPTY 读取消息不成功,没有消息。 -* @note 从接受队列中读取一个信息到*MsgPtr。 -*/ -j1939_uint8_t J1939_Read_Message( J1939_MESSAGE *MsgPtr, CAN_NODE _Can_Node) + * @param[in] MsgPtr 存储读取消息的缓存 + * @param[in] _Can_Node 读取消息的CAN硬件编号(从哪一路CAN读取数据) + * @return RC_SUCCESS 读取消息成功, + * @return RC_QUEUEEMPTY 读取消息不成功,没有消息。 + * @note 从接受队列中读取一个信息到*MsgPtr。 + */ +J1939_Status_t J1939_Read_Message(J1939_MESSAGE_t *MsgPtr, CAN_NODE_t _Can_Node) { - return J1939_DequeueMessage(MsgPtr,_Can_Node); + return J1939_DequeueMessage(MsgPtr, _Can_Node); } + /** -* @param[in] MsgPtr 用户要入队的消息 -* @param[in] _Can_Node 要入队的CAN硬件编号(要选择的使用的CAN硬件编号) -* @return RC_SUCCESS 消息入队成功 -* @return RC_QUEUEFULL 发送列队满,消息入队失败 -* @return RC_CANNOTTRANSMIT 系统目前不能发送消息 -* @note 这段程序,将*MsgPtr放入发送消息列队中\n - 如果信息不能入队或者发送,将有一个相应的返回提示,\n - 如果发送中断被设置(可用),当消息列队后,发送中断被使能 -*/ -j1939_uint8_t J1939_EnqueueMessage( J1939_MESSAGE *MsgPtr, CAN_NODE _Can_Node) -{ - j1939_uint8_t _rc = RC_SUCCESS; - -#if J1939_POLL_ECAN == J1939_FALSE + * @param[in] MsgPtr 用户要入队的消息 + * @param[in] _Can_Node 要入队的CAN硬件编号(要选择的使用的CAN硬件编号) + * @return RC_SUCCESS 消息入队成功 + * @return RC_QUEUEFULL 发送队列满,消息入队失败 + * @return RC_CANNOTTRANSMIT 系统目前不能发送消息 + * @note 这段程序,将*MsgPtr放入发送消息队列中\n + 如果信息不能入队或者发送,将有一个相应的返回提示,\n + 如果发送中断被设置(可用),当消息队列后,发送中断被使能 + */ +J1939_Status_t J1939_EnqueueMessage(J1939_MESSAGE_t *MsgPtr, CAN_NODE_t _Can_Node) +{ + J1939_Status_t _rc = RC_SUCCESS; + Port_TXinterruptDisable(); -#endif - - if (0) + + if (0) { _rc = RC_CANNOTTRANSMIT; - else - { - switch (_Can_Node) - { - case Select_CAN_NODE_1: - { - if ((J1939_OVERWRITE_TX_QUEUE == J1939_TRUE) || - (TXQueueCount_1 < J1939_TX_QUEUE_SIZE)) - { - if (TXQueueCount_1 < J1939_TX_QUEUE_SIZE) - { - TXQueueCount_1 ++; - TXTail_1 ++; - if (TXTail_1 >= J1939_TX_QUEUE_SIZE) - TXTail_1 = 0; - }else{ - J1939_Flags.TransmitMessagesdCover = 1;//发送数据被覆盖,上一帧数据被覆盖 - } - TXQueue_1[TXTail_1] = *MsgPtr; - } - else - _rc = RC_QUEUEFULL; - break; - } - case Select_CAN_NODE_2: - { - if ((J1939_OVERWRITE_TX_QUEUE == J1939_TRUE) || - (TXQueueCount_2 < J1939_TX_QUEUE_SIZE)) - { - if (TXQueueCount_2 < J1939_TX_QUEUE_SIZE) - { - TXQueueCount_2 ++; - TXTail_2 ++; - if (TXTail_2 >= J1939_TX_QUEUE_SIZE) - TXTail_2 = 0; - }else{ - J1939_Flags.TransmitMessagesdCover = 1;//发送数据被覆盖,上一帧数据被覆盖 - } - TXQueue_2[TXTail_2] = *MsgPtr; - } - else - _rc = RC_QUEUEFULL; - break; - } - case Select_CAN_NODE_3: - { - if ((J1939_OVERWRITE_TX_QUEUE == J1939_TRUE) || - (TXQueueCount_3 < J1939_TX_QUEUE_SIZE)) - { - if (TXQueueCount_3 < J1939_TX_QUEUE_SIZE) - { - TXQueueCount_3 ++; - TXTail_3 ++; - if (TXTail_3 >= J1939_TX_QUEUE_SIZE) - TXTail_3 = 0; - }else{ - J1939_Flags.TransmitMessagesdCover = 1;//发送数据被覆盖,上一帧数据被覆盖 - } - TXQueue_3[TXTail_3] = *MsgPtr; - } - else - _rc = RC_QUEUEFULL; - break; - } - case Select_CAN_NODE_4: - { - if ((J1939_OVERWRITE_TX_QUEUE == J1939_TRUE) || - (TXQueueCount_4 < J1939_TX_QUEUE_SIZE)) - { - if (TXQueueCount_4 < J1939_TX_QUEUE_SIZE) - { - TXQueueCount_4 ++; - TXTail_4 ++; - if (TXTail_4 >= J1939_TX_QUEUE_SIZE) - TXTail_4 = 0; - }else{ - J1939_Flags.TransmitMessagesdCover = 1;//发送数据被覆盖,上一帧数据被覆盖 - } - TXQueue_4[TXTail_4] = *MsgPtr; - } - else - _rc = RC_QUEUEFULL; - break; - } - default : - { - break; - } - } - } - -#if J1939_POLL_ECAN == J1939_FALSE + } else { + if ((J1939_OVERWRITE_TX_QUEUE == J1939_TRUE) || (TXQueueCount[_Can_Node] < J1939_TX_QUEUE_SIZE)) { + if (TXQueueCount[_Can_Node] < J1939_TX_QUEUE_SIZE) { + TXQueueCount[_Can_Node]++; + TXTail[_Can_Node]++; + + if (TXTail[_Can_Node] >= J1939_TX_QUEUE_SIZE) { + TXTail[_Can_Node] = 0; + } + } else { + J1939_Flags.TransmitMessagesdCover = 1; /* 发送数据被覆盖,上一帧数据被覆盖 */ + } + + TXQueue[_Can_Node][TXTail[_Can_Node]] = *MsgPtr; + } else { + _rc = RC_QUEUEFULL; + } + } + Port_TXinterruptEnable(); - //触发发送中断 + + /* 触发发送中断 */ Port_TXinterruptOk(); -#endif + return _rc; -} +} + /** -* @param[in] MsgPtr 存储发送消息的缓存 -* @param[in] _Can_Node 发送消息的CAN硬件编号(从哪一路CAN发送数据) -* @return RC_SUCCESS 发送消息成功 -* @return RC_QUEUEFULL 发送消息不成功,发送列队满,消息入队失败 -* @return RC_CANNOTTRANSMIT 发送消息不成功,系统目前不能发送消息 -* @note 如果信息不能入队或者发送,将有一个相应的返回提示,\n -*/ -j1939_uint8_t J1939_Send_Message( J1939_MESSAGE *MsgPtr, CAN_NODE _Can_Node) + * @param[in] MsgPtr 存储发送消息的缓存 + * @param[in] _Can_Node 发送消息的CAN硬件编号(从哪一路CAN发送数据) + * @return RC_SUCCESS 发送消息成功 + * @return RC_QUEUEFULL 发送消息不成功,发送队列满,消息入队失败 + * @return RC_CANNOTTRANSMIT 发送消息不成功,系统目前不能发送消息 + * @note 如果信息不能入队或者发送,将有一个相应的返回提示,\n + */ +J1939_Status_t J1939_Send_Message(J1939_MESSAGE_t *MsgPtr, CAN_NODE_t _Can_Node) { - return J1939_EnqueueMessage(MsgPtr,_Can_Node); + return J1939_EnqueueMessage(MsgPtr, _Can_Node); } + /** -* -* @note 这段代码在系统初始化中被调用,(放在CAN设备初始化之后)\n - 初始化J1939全局变量\n -*/ -void J1939_Initialization() + * + * @note 这段代码在系统初始化中被调用,(放在CAN设备初始化之后)\n + 初始化J1939全局变量\n + */ +void J1939_Initialization(void) { - /*初始化全局变量*/ - J1939_Flags.FlagVal = 0; //没有声明地址,其他的标识位将被设置为0(复位) - - /*初始化接受和发送列队*/ - TXHead_1 = 0; - TXHead_2 = 0; - TXHead_3 = 0; - TXHead_4 = 0; - TXTail_1 = 0xFF; - TXTail_2 = 0xFF; - TXTail_3 = 0xFF; - TXTail_4 = 0xFF; - RXHead_1 = 0; - RXHead_2 = 0; - RXHead_3 = 0; - RXHead_4 = 0; - RXTail_1 = 0xFF; - RXTail_2 = 0xFF; - RXTail_3 = 0xFF; - RXTail_4 = 0xFF; - TXQueueCount_1 = 0; - TXQueueCount_2 = 0; - TXQueueCount_3 = 0; - TXQueueCount_4 = 0; - RXQueueCount_1 = 0; - RXQueueCount_2 = 0; - RXQueueCount_3 = 0; - RXQueueCount_4 = 0; - /*初始化节点地址*/ - NodeAddress_1 = J1939_STARTING_ADDRESS_1; - NodeAddress_2 = J1939_STARTING_ADDRESS_2; - NodeAddress_3 = J1939_STARTING_ADDRESS_3; - NodeAddress_4 = J1939_STARTING_ADDRESS_4; - /*初始化CAN节点的选择*/ + /* 初始化全局变量 */ + J1939_Flags.FlagVal = 0; /* 没有声明地址,其他的标识位将被设置为0(复位) */ + + /* 初始化接受和发送队列 */ + j1939_uint8_t i; + for (i = 0; i < J1939_NODE_NUM; i++) + { + TXHead[i] = 0; + TXTail[i] = 0xFF; + RXHead[i] = 0; + RXTail[i] = 0xFF; + TXQueueCount[i] = 0; + RXQueueCount[i] = 0; + + /* 初始化节点地址 */ + NodeAddress[i] = J1939_STARTING_ADDRESS[i]; + } + + /* 初始化CAN节点的选择 */ Can_Node = Select_CAN_NODE_1; - /*初始化请求链表*/ + + /* 初始化请求链表 */ REQUEST_LIST.PGN = 0; REQUEST_LIST.data = J1939_NULL; - REQUEST_LIST.update = J1939_NULL; - REQUEST_LIST.lenght = 0; - REQUEST_LIST.Can_Node = Select_CAN_NODE_Null; - REQUEST_LIST.next = J1939_NULL; - /*将TP协议置为空闲*/ + REQUEST_LIST.update = J1939_NULL; + REQUEST_LIST.length = 0; + REQUEST_LIST.Can_Node = Select_CAN_NODE_Null; + REQUEST_LIST.next = J1939_NULL; + + /* 将TP协议置为空闲 */ #if J1939_TP_RX_TX J1939_TP_Flags_t.state = J1939_TP_NULL; J1939_TP_Flags_t.TP_RX_CAN_NODE = Select_CAN_NODE_Null; @@ -466,1293 +235,1070 @@ void J1939_Initialization() TP_TX_MSG.packets_request_num = 0; TP_TX_MSG.packets_total = 0; - TP_TX_MSG.packet_offset_p = 0; - TP_TX_MSG.time = 0; - TP_TX_MSG.state = J1939_TP_TX_WAIT; + TP_TX_MSG.packet_offset_p = 0; + TP_TX_MSG.time = 0; + TP_TX_MSG.state = J1939_TP_TX_WAIT; TP_RX_MSG.packets_ok_num = 0; - TP_RX_MSG.packets_total = 0; - TP_RX_MSG.time = 0; - TP_RX_MSG.state = J1939_TP_RX_WAIT; + TP_RX_MSG.packets_total = 0; + TP_RX_MSG.time = 0; + TP_RX_MSG.state = J1939_TP_RX_WAIT; #endif -} +} /** -* @note 这个函数被调用,当设备产生CAN中断(可能是接受中断,也可能是发送中断)\n - 首先我们要清除中断标识位\n - 然后调用接受或者发送函数。 -*/ -#if J1939_POLL_ECAN == J1939_FALSE -void J1939_ISR( void ) -{ - //判断相关标识位,是接受还是发送 - //清除标识位 + * @note 这个函数被调用,当设备产生CAN中断(可能是接受中断,也可能是发送中断)\n + 首先我们要清除中断标识位\n + 然后调用接受或者发送函数。 + */ +#if J1939_POLL_ECAN == J1939_FALSE +void J1939_ISR(void) +{ + /* 判断相关标识位,是接受还是发送 */ + /* 清除标识位 */ Port_CAN_identifier_clc(); - //调用相关的处理函数 - J1939_ReceiveMessages(); - J1939_TransmitMessages(); - #if J1939_TP_RX_TX - J1939_TP_Poll(); - #endif //J1939_TP_RX_TX - //可能存在因为错误产生中断,直接清除相关的标识位 -} -#endif - + /* 调用相关的处理函数 */ + J1939_ReceiveMessages(); + J1939_TransmitMessages(); +#if J1939_TP_RX_TX + J1939_TP_Poll(); +#endif /* J1939_TP_RX_TX */ + /* 可能存在因为错误产生中断,直接清除相关的标识位 */ +} +#endif + /** -* @param[in] ElapsedTime 一个大概的毫秒数,通常设置 5 或 3 -* @note 如果我们采用轮询的方式获取信息,这个函数每几个毫秒将被调用一次。\n - 不断的接受消息和发送消息从消息队列中\n - 此外,如果我们正在等待一个地址竞争反应。\n - 如果超时,我们只接收特定的消息(目标地址 = J1939_Address)\n - - 如果设备使用中断,此函数被调用,在调用J1939_Initialization()函数后,因为\n - J1939_Initialization()可能初始化WaitingForAddressClaimContention标识位为1.\n - - 如果接受到命令地址消息,这个函数也必须被调用,以防万一总线要求我们改变地址\n - - 如果使用中断模式,本程序将不会处理接受和发送消息,只处理地址竞争超时。\n -*/ -//声明TP轮询函数 -void J1939_TP_Poll(); -void J1939_Poll( ) + * @param[in] ElapsedTime 一个大概的毫秒数,通常设置 5 或 3 + * @note 如果我们采用轮询的方式获取信息,这个函数每几个毫秒将被调用一次。\n + 不断的接受消息和发送消息从消息队列中\n + 此外,如果我们正在等待一个地址竞争反应。\n + 如果超时,我们只接收特定的消息(目标地址 = J1939_Address)\n + + 如果设备使用中断,此函数被调用,在调用J1939_Initialization()函数后,因为\n + J1939_Initialization()可能初始化WaitingForAddressClaimContention标识位为1.\n + + 如果接受到命令地址消息,这个函数也必须被调用,以防万一总线要求我们改变地址\n + + 如果使用中断模式,本程序将不会处理接受和发送消息,只处理地址竞争超时。\n + */ +void J1939_Poll(void) { - //我们必须调用J1939_ReceiveMessages接受函数,在时间被重置为0之前。 + /* 我们必须调用J1939_ReceiveMessages接受函数,在时间被重置为0之前。 */ #if J1939_POLL_ECAN == J1939_TRUE - Can_Node = Select_CAN_NODE_1; - J1939_Address = NodeAddress_1; - J1939_ReceiveMessages(); - J1939_TransmitMessages(); - Can_Node = Select_CAN_NODE_2; - J1939_Address = NodeAddress_2; - J1939_ReceiveMessages(); - J1939_TransmitMessages(); - Can_Node = Select_CAN_NODE_3; - J1939_Address = NodeAddress_3; - J1939_ReceiveMessages(); - J1939_TransmitMessages(); - Can_Node = Select_CAN_NODE_4; - J1939_Address = NodeAddress_4; - J1939_ReceiveMessages(); - J1939_TransmitMessages(); + Can_Node = Select_CAN_NODE_1; + J1939_Address = NodeAddress[0]; + J1939_ReceiveMessages(); + J1939_TransmitMessages(); + Can_Node = Select_CAN_NODE_2; + J1939_Address = NodeAddress[1]; + J1939_ReceiveMessages(); + J1939_TransmitMessages(); + Can_Node = Select_CAN_NODE_3; + J1939_Address = NodeAddress[2]; + J1939_ReceiveMessages(); + J1939_TransmitMessages(); + Can_Node = Select_CAN_NODE_4; + J1939_Address = NodeAddress[3]; + J1939_ReceiveMessages(); + J1939_TransmitMessages(); #if J1939_TP_RX_TX - J1939_TP_Poll(); -#endif //J1939_TP_RX_TX -#endif //J1939_POLL_ECAN == J1939_TRUE -} -void J1939_Response(const j1939_uint32_t PGN); + J1939_TP_Poll(); +#endif /* J1939_TP_RX_TX */ +#endif /* J1939_POLL_ECAN == J1939_TRUE */ +} #if J1939SoftwareFilterEn == J1939_TRUE /** -* @return RC_SUCCESS 消息是可以接受 -* @return RC_CANNOTTRANSMIT 消息是不可以接受 -* @note 软件滤波器\n -* @note 基于SAE J1939协议,我们需要CAN控制器提供至少3个滤波器给J1939协议代码。三个滤波器分别配置如下: - 1. 设置滤波器0,只接受广播信息(PF = 240 -255)。 - 2. 设置设置滤波器1,2只接受全局地址(J1939_GLOBAL_ADDRESS) - 3. 随着程序的运行,将改变滤波器2,来适应程序逻辑。 -*/ -j1939_uint8_t J1939_Messages_Filter(J1939_MESSAGE *MsgPtr) + * @return RC_SUCCESS 消息是可以接受 + * @return RC_CANNOTTRANSMIT 消息是不可以接受 + * @note 软件滤波器\n + * @note 基于SAE J1939协议,我们需要CAN控制器提供至少3个滤波器给J1939协议代码。三个滤波器分别配置如下: + 1. 设置滤波器0,只接受广播信息(PF = 240 -255)。 + 2. 设置设置滤波器1,2只接受全局地址(J1939_GLOBAL_ADDRESS) + 3. 随着程序的运行,将改变滤波器2,来适应程序逻辑。 + */ +J1939_Status_t J1939_Messages_Filter(J1939_MESSAGE_t *MsgPtr) { - /*滤波器0*/ - if((MsgPtr->Mxe.PDUFormat) >= 240) - { + /* 滤波器0 */ + if ((MsgPtr->Mxe.PDUFormat) >= 240) { return RC_SUCCESS; } - /*滤波器1*/ - if(((MsgPtr->Mxe.PDUFormat) < 240) && (MsgPtr->Mxe.PDUSpecific == J1939_GLOBAL_ADDRESS)) - { + + /* 滤波器1 */ + if (((MsgPtr->Mxe.PDUFormat) < 240) && (MsgPtr->Mxe.PDUSpecific == J1939_PS_DA_GLOBAL)) { return RC_SUCCESS; } - /*滤波器2*/ - switch (Can_Node) - { - case Select_CAN_NODE_1: - { - if(((MsgPtr->Mxe.PDUFormat) < 240) && (MsgPtr->Mxe.PDUSpecific == NodeAddress_1)) - { - return RC_SUCCESS; - } - break; - } - case Select_CAN_NODE_2: - { - if(((MsgPtr->Mxe.PDUFormat) < 240) && (MsgPtr->Mxe.PDUSpecific == NodeAddress_2)) - { - return RC_SUCCESS; - } - break; - } - case Select_CAN_NODE_3: - { - if(((MsgPtr->Mxe.PDUFormat) < 240) && (MsgPtr->Mxe.PDUSpecific == NodeAddress_3)) - { - return RC_SUCCESS; - } - break; - } - case Select_CAN_NODE_4: - { - if(((MsgPtr->Mxe.PDUFormat) < 240) && (MsgPtr->Mxe.PDUSpecific == NodeAddress_4)) - { - return RC_SUCCESS; - } - break; - } - default : - { - break; - } - } + + /* 滤波器2 */ + if (((MsgPtr->Mxe.PDUFormat) < 240) && (MsgPtr->Mxe.PDUSpecific == NodeAddress[Can_Node])) { + return RC_SUCCESS; + } + return RC_CANNOTTRANSMIT; } -#endif //J1939SoftwareFilterEn +#endif /* J1939SoftwareFilterEn */ /** -* @note 这段程序被调用,当CAN收发器接受数据(中断 或者 轮询)。\n - 如果一个信息被接受, 它将被调用\n - 如果信息是一个网络管理信息或长帧传输(TP),接受的信息将被加工处理,在这个函数中。\n - 否则, 信息将放置在用户的接收队列。\n - 注意:在这段程序运行期间中断是失能的。\n -*/ -void J1939_ReceiveMessages( void ) + * @note 这段程序被调用,当CAN收发器接受数据(中断 或者 轮询)。\n + 如果一个信息被接受, 它将被调用\n + 如果信息是一个网络管理信息或长帧传输(TP),接受的信息将被加工处理,在这个函数中。\n + 否则, 信息将放置在用户的接收队列。\n + 注意:在这段程序运行期间中断是失能的。\n + */ +void J1939_ReceiveMessages(void) { #if J1939_TP_RX_TX - j1939_uint32_t _pgn = 0; -#endif //J1939_TP_RX_TX - /*从接收缓存中读取信息到OneMessage中,OneMessage是一个全局变量*/ - /*Port_CAN_Receive函数读取到数据返回1,没有数据则返回0*/ - if(Port_CAN_Receive(&OneMessage)) - { + j1939_uint32_t _pgn = 0; +#endif /* J1939_TP_RX_TX */ + + /* 从接收缓存中读取信息到OneMessage中,OneMessage是一个全局变量 */ + /* Port_CAN_Receive函数读取到数据返回1,没有数据则返回0 */ + if (Port_CAN_Receive(&OneMessage)) { #if J1939SoftwareFilterEn == J1939_TRUE - if(J1939_Messages_Filter(&OneMessage) != RC_SUCCESS) - { - return ; - } -#endif //J1939SoftwareFilterEn - switch( OneMessage.Mxe.PDUFormat) - { + + if (J1939_Messages_Filter(&OneMessage) != RC_SUCCESS) { + return; + } + +#endif /* J1939SoftwareFilterEn */ + + switch (OneMessage.Mxe.PDUFormat) { #if J1939_TP_RX_TX - case J1939_PF_TP_CM: //参考J1939-21 TP多帧传输协议 - _pgn = (j1939_uint32_t)((OneMessage.Mxe.Data[7]<<16)&0xFF0000) - +(j1939_uint32_t)((OneMessage.Mxe.Data[6]<<8)&0xFF00) - +(j1939_uint32_t)((OneMessage.Mxe.Data[5])&0xFF); - if((J1939_TP_Flags_t.state == J1939_TP_NULL) && (TP_RX_MSG.state == J1939_TP_RX_WAIT)) - { - if(OneMessage.Mxe.Data[0] == 16) - { - J1939_TP_Flags_t.state = J1939_TP_RX; - J1939_TP_Flags_t.TP_RX_CAN_NODE = Can_Node; - - TP_RX_MSG.tp_rx_msg.SA = OneMessage.Mxe.SourceAddress; - TP_RX_MSG.tp_rx_msg.PGN = (j1939_uint32_t)((OneMessage.Mxe.Data[7]<<16)&0xFF0000) - +(j1939_uint32_t)((OneMessage.Mxe.Data[6]<<8)&0xFF00) - +(j1939_uint32_t)((OneMessage.Mxe.Data[5])&0xFF); - /*如果系统繁忙*/ - if(TP_RX_MSG.osbusy) - { - TP_RX_MSG.state = J1939_TP_RX_ERROR; - break; - } - /*判断是否有足够的内存接收数据,如果没有直接,断开连接*/ - if(((j1939_uint32_t)((OneMessage.Mxe.Data[2]<<8)&0xFF00) - +(j1939_uint32_t)((OneMessage.Mxe.Data[1])&0xFF)) > J1939_TP_MAX_MESSAGE_LENGTH) - { - TP_RX_MSG.state = J1939_TP_RX_ERROR; - break; - } - TP_RX_MSG.tp_rx_msg.byte_count = ((j1939_uint32_t)((OneMessage.Mxe.Data[2]<<8)&0xFF00) - +(j1939_uint32_t)((OneMessage.Mxe.Data[1])&0xFF)); - TP_RX_MSG.packets_total = OneMessage.Mxe.Data[3]; - TP_RX_MSG.time = J1939_TP_T2; - TP_RX_MSG.state = J1939_TP_RX_READ_DATA; - break; + + case J1939_PF_TP_CM: /* 参考J1939-21 TP多帧传输协议 */ + _pgn = (j1939_uint32_t) ((OneMessage.Mxe.Data[7] << 16) & 0xFF0000) + + (j1939_uint32_t) ((OneMessage.Mxe.Data[6] << 8) & 0xFF00) + + (j1939_uint32_t) ((OneMessage.Mxe.Data[5]) & 0xFF); + + if ((J1939_TP_Flags_t.state == J1939_TP_NULL) && (TP_RX_MSG.state == J1939_TP_RX_WAIT)) { + if (OneMessage.Mxe.Data[0] == 16) { + J1939_TP_Flags_t.state = J1939_TP_RX; + J1939_TP_Flags_t.TP_RX_CAN_NODE = Can_Node; + + TP_RX_MSG.tp_rx_msg.SA = OneMessage.Mxe.SourceAddress; + TP_RX_MSG.tp_rx_msg.PGN = (j1939_uint32_t) ((OneMessage.Mxe.Data[7] << 16) & 0xFF0000) + + (j1939_uint32_t) ((OneMessage.Mxe.Data[6] << 8) & 0xFF00) + + (j1939_uint32_t) ((OneMessage.Mxe.Data[5]) & 0xFF); + + /* 如果系统繁忙 */ + if (TP_RX_MSG.osbusy) { + TP_RX_MSG.state = J1939_TP_RX_ERROR; + break; + } + + /* 判断是否有足够的内存接收数据,如果没有直接,断开连接 */ + if (((j1939_uint32_t) ((OneMessage.Mxe.Data[2] << 8) & 0xFF00) + + (j1939_uint32_t) ((OneMessage.Mxe.Data[1]) & 0xFF)) > J1939_TP_MAX_MESSAGE_LENGTH) { + TP_RX_MSG.state = J1939_TP_RX_ERROR; + break; + } + + TP_RX_MSG.tp_rx_msg.byte_count = ((j1939_uint32_t) ((OneMessage.Mxe.Data[2] << 8) & 0xFF00) + + (j1939_uint32_t) ((OneMessage.Mxe.Data[1]) & 0xFF)); + TP_RX_MSG.packets_total = OneMessage.Mxe.Data[3]; + TP_RX_MSG.time = J1939_TP_T2; + TP_RX_MSG.state = J1939_TP_RX_READ_DATA; + break; } + goto PutInReceiveQueue; break; - } - if(J1939_TP_Flags_t.state == J1939_TP_TX) - { - /*校验PGN*/ - if (_pgn == TP_TX_MSG.tp_tx_msg.PGN) - { - switch(OneMessage.Mxe.Data[0]) - { - case J1939_RTS_CONTROL_BYTE: - /* 程序运行到这里,说明已经与网络中设备1建立虚拟链接(作为发送端),但是收到设备2的链接请求,并且同一个PGN消息请求*/ - /* 根据J1939-21数据链路层的规定,我们要保持原有的链接,不做任何事,设备2会应为超时自动放弃链接*/ - break; - case J1939_CTS_CONTROL_BYTE: - if((J1939_TP_TX_CM_WAIT == TP_TX_MSG.state) || (J1939_TP_WAIT_ACK == TP_TX_MSG.state)) - { - /* 发送等待保持 */ - if(0x00u == OneMessage.Mxe.Data[1]) - { - /* 刷新等待计数器 */ - TP_TX_MSG.time = J1939_TP_T4; - } - else - { - if((OneMessage.Mxe.Data[2]+OneMessage.Mxe.Data[1]) > (TP_TX_MSG.packets_total+1)) - { - /*请求超出数据包范围*/ - TP_TX_MSG.state = J1939_TP_TX_ERROR; - } - else - { /* response parameter OK */ - TP_TX_MSG.packets_request_num = OneMessage.Mxe.Data[1]; - TP_TX_MSG.packet_offset_p = (j1939_uint8_t)(OneMessage.Mxe.Data[2] - 1); - TP_TX_MSG.state = J1939_TP_TX_DT; - } - - } - } - break; - case J1939_EOMACK_CONTROL_BYTE: - if(J1939_TP_WAIT_ACK == TP_TX_MSG.state) - { - TP_TX_MSG.state = J1939_TX_DONE; - } - //这里可以增加一个对数据的校验 - break; - case J1939_CONNABORT_CONTROL_BYTE: - //收到一个放弃连接,什么都不做,协议会在一段延时时间后主动放弃链接 - break; - default: - break; - } - } - } - goto PutInReceiveQueue; - break; -#endif//J1939_TP_RX_TX + } + + if (J1939_TP_Flags_t.state == J1939_TP_TX) { + /* 校验PGN */ + if (_pgn == TP_TX_MSG.tp_tx_msg.PGN) { + switch (OneMessage.Mxe.Data[0]) { + case J1939_CONTROL_BYTE_RTS: + /* 程序运行到这里,说明已经与网络中设备1建立虚拟链接(作为发送端),但是收到设备2的链接请求,并且同一个PGN消息请求*/ + /* 根据J1939-21数据链路层的规定,我们要保持原有的链接,不做任何事,设备2会应为超时自动放弃链接*/ + break; + + case J1939_CONTROL_BYTE_CTS: + if ((J1939_TP_TX_CM_WAIT == TP_TX_MSG.state) || (J1939_TP_WAIT_ACK == TP_TX_MSG.state)) { + /* 发送等待保持 */ + if (0x00u == OneMessage.Mxe.Data[1]) { + /* 刷新等待计数器 */ + TP_TX_MSG.time = J1939_TP_T4; + } else { + if ((OneMessage.Mxe.Data[2] + OneMessage.Mxe.Data[1]) + > (TP_TX_MSG.packets_total + 1)) { + /* 请求超出数据包范围 */ + TP_TX_MSG.state = J1939_TP_TX_ERROR; + } else { + /* response parameter OK */ + TP_TX_MSG.packets_request_num = OneMessage.Mxe.Data[1]; + TP_TX_MSG.packet_offset_p = (j1939_uint8_t) (OneMessage.Mxe.Data[2] - 1); + TP_TX_MSG.state = J1939_TP_TX_DT; + } + + } + } + + break; + + case J1939_CONTROL_BYTE_EOMACK: + if (J1939_TP_WAIT_ACK == TP_TX_MSG.state) { + TP_TX_MSG.state = J1939_TX_DONE; + } + + /* 这里可以增加一个对数据的校验 */ + break; + + case J1939_CONTROL_BYTE_CONNABORT: + /* 收到一个放弃连接,什么都不做,协议会在一段延时时间后主动放弃链接 */ + break; + + default: + break; + } + } + } + + goto PutInReceiveQueue; + break; +#endif /* J1939_TP_RX_TX */ #if J1939_TP_RX_TX - case J1939_PF_DT: - if((TP_RX_MSG.state == J1939_TP_RX_DATA_WAIT)&&(TP_RX_MSG.tp_rx_msg.SA == OneMessage.Mxe.SourceAddress)) - { - TP_RX_MSG.tp_rx_msg.data[(OneMessage.Mxe.Data[0]-1)*7u]=OneMessage.Mxe.Data[1]; - TP_RX_MSG.tp_rx_msg.data[(OneMessage.Mxe.Data[0]-1)*7u+1]=OneMessage.Mxe.Data[2]; - TP_RX_MSG.tp_rx_msg.data[(OneMessage.Mxe.Data[0]-1)*7u+2]=OneMessage.Mxe.Data[3]; - TP_RX_MSG.tp_rx_msg.data[(OneMessage.Mxe.Data[0]-1)*7u+3]=OneMessage.Mxe.Data[4]; - TP_RX_MSG.tp_rx_msg.data[(OneMessage.Mxe.Data[0]-1)*7u+4]=OneMessage.Mxe.Data[5]; - TP_RX_MSG.tp_rx_msg.data[(OneMessage.Mxe.Data[0]-1)*7u+5]=OneMessage.Mxe.Data[6]; - TP_RX_MSG.tp_rx_msg.data[(OneMessage.Mxe.Data[0]-1)*7u+6]=OneMessage.Mxe.Data[7]; - /*特殊处理重新接受已接受过的数据包*/ - if((OneMessage.Mxe.Data[0]) > TP_RX_MSG.packets_ok_num) - { - TP_RX_MSG.packets_ok_num++; - } - TP_RX_MSG.time = J1939_TP_T1; - /*判断是否收到偶数个数据包或者读取到最后一个数据包*/ - if((TP_RX_MSG.packets_ok_num%2 == 0) ||(TP_RX_MSG.packets_ok_num == TP_RX_MSG.packets_total)) - { - TP_RX_MSG.state = J1939_TP_RX_READ_DATA; - break ; - } - break ; + + case J1939_PF_TP_DT: + if ((TP_RX_MSG.state == J1939_TP_RX_DATA_WAIT) + && (TP_RX_MSG.tp_rx_msg.SA == OneMessage.Mxe.SourceAddress)) { + TP_RX_MSG.tp_rx_msg.data[(OneMessage.Mxe.Data[0] - 1) * 7u] = OneMessage.Mxe.Data[1]; + TP_RX_MSG.tp_rx_msg.data[(OneMessage.Mxe.Data[0] - 1) * 7u + 1] = OneMessage.Mxe.Data[2]; + TP_RX_MSG.tp_rx_msg.data[(OneMessage.Mxe.Data[0] - 1) * 7u + 2] = OneMessage.Mxe.Data[3]; + TP_RX_MSG.tp_rx_msg.data[(OneMessage.Mxe.Data[0] - 1) * 7u + 3] = OneMessage.Mxe.Data[4]; + TP_RX_MSG.tp_rx_msg.data[(OneMessage.Mxe.Data[0] - 1) * 7u + 4] = OneMessage.Mxe.Data[5]; + TP_RX_MSG.tp_rx_msg.data[(OneMessage.Mxe.Data[0] - 1) * 7u + 5] = OneMessage.Mxe.Data[6]; + TP_RX_MSG.tp_rx_msg.data[(OneMessage.Mxe.Data[0] - 1) * 7u + 6] = OneMessage.Mxe.Data[7]; + + /* 特殊处理重新接受已接受过的数据包 */ + if ((OneMessage.Mxe.Data[0]) > TP_RX_MSG.packets_ok_num) { + TP_RX_MSG.packets_ok_num++; + } + + TP_RX_MSG.time = J1939_TP_T1; + + /* 判断是否收到偶数个数据包或者读取到最后一个数据包 */ + if ((TP_RX_MSG.packets_ok_num % 2 == 0) || (TP_RX_MSG.packets_ok_num == TP_RX_MSG.packets_total)) { + TP_RX_MSG.state = J1939_TP_RX_READ_DATA; + break; + } + + break; } - //程序不可能运行到这,但是我们不能放弃接受的数据包 + + /* 程序不可能运行到这,但是我们不能放弃接受的数据包 */ goto PutInReceiveQueue; -#endif//J1939_TP_RX_TX - case J1939_PF_REQUEST: - /*用OneMessage.Mxe.PGN 来存下被请求的PGN*/ - if(OneMessage.Mxe.Data[1] < 240) - { - OneMessage.Mxe.PGN = (j1939_uint32_t)((OneMessage.Mxe.Data[2]<<16)&0x030000) - +(j1939_uint32_t)((OneMessage.Mxe.Data[1]<<8)&0xFF00) - +0x00; - }else{ - OneMessage.Mxe.PGN = (j1939_uint32_t)((OneMessage.Mxe.Data[2]<<16)&0x030000) - +(j1939_uint32_t)((OneMessage.Mxe.Data[1]<<8)&0xFF00) - +(j1939_uint32_t)((OneMessage.Mxe.Data[0])&0xFF); - } - J1939_Response(OneMessage.Mxe.PGN); - break; - default: -PutInReceiveQueue: - { -/* -if(OneMessage.Mxe.PDUFormat < 240){ - OneMessage.Mxe.PGN = (j1939_uint32_t)((OneMessage.Array[0]<<16)&0x030000) - +(j1939_uint32_t)((OneMessage.Array[1]<<8)&0xFF00) - +0x00; -}else{ - OneMessage.Mxe.PGN = (j1939_uint32_t)((OneMessage.Array[0]<<16)&0x030000) - +(j1939_uint32_t)((OneMessage.Array[1]<<8)&0xFF00) - +(j1939_uint32_t)((OneMessage.Array[2])&0xFF); -} -*/ - if(OneMessage.Mxe.PDUFormat < 240){ - OneMessage.Mxe.PGN = (OneMessage.Mxe.Res << 17) - +(OneMessage.Mxe.DataPage << 16) - +(OneMessage.Mxe.PDUFormat << 8); - }else{ - OneMessage.Mxe.PGN = (OneMessage.Mxe.Res << 17) - +(OneMessage.Mxe.DataPage << 16) - +(OneMessage.Mxe.PDUFormat << 8) - + OneMessage.Mxe.PDUSpecific; - } - - switch (Can_Node) - { - case Select_CAN_NODE_1: - { - if ( (J1939_OVERWRITE_RX_QUEUE == J1939_TRUE) || - (RXQueueCount_1 < J1939_RX_QUEUE_SIZE)) - { - if (RXQueueCount_1 < J1939_RX_QUEUE_SIZE) - { - RXQueueCount_1 ++; - RXTail_1 ++; - if (RXTail_1 >= J1939_RX_QUEUE_SIZE) - RXTail_1 = 0; - }else{ - J1939_Flags.ReceivedMessagesdCover = 1; //产生数据覆盖 - J1939_Flags.ReceivedMessagesdCoverOrDroppedNode = Select_CAN_NODE_1; - } - RXQueue_1[RXTail_1] = OneMessage; - } - else - J1939_Flags.ReceivedMessagesDropped = 1; //产生数据溢出 - break; - } - case Select_CAN_NODE_2: - { - if ( (J1939_OVERWRITE_RX_QUEUE == J1939_TRUE) || - (RXQueueCount_2 < J1939_RX_QUEUE_SIZE)) - { - if (RXQueueCount_2 < J1939_RX_QUEUE_SIZE) - { - RXQueueCount_2 ++; - RXTail_2 ++; - if (RXTail_2 >= J1939_RX_QUEUE_SIZE) - RXTail_2 = 0; - }else{ - J1939_Flags.ReceivedMessagesdCover = 1; //产生数据覆盖 - J1939_Flags.ReceivedMessagesdCoverOrDroppedNode = Select_CAN_NODE_2; - } - RXQueue_2[RXTail_2] = OneMessage; - } - else - J1939_Flags.ReceivedMessagesDropped = 1; - break; - } - case Select_CAN_NODE_3: - { - if ( (J1939_OVERWRITE_RX_QUEUE == J1939_TRUE) || - (RXQueueCount_3 < J1939_RX_QUEUE_SIZE)) - { - if (RXQueueCount_3 < J1939_RX_QUEUE_SIZE) - { - RXQueueCount_3 ++; - RXTail_3 ++; - if (RXTail_3 >= J1939_RX_QUEUE_SIZE) - RXTail_3 = 0; - }else{ - J1939_Flags.ReceivedMessagesdCover = 1; //产生数据覆盖 - J1939_Flags.ReceivedMessagesdCoverOrDroppedNode = Select_CAN_NODE_3; - } - RXQueue_3[RXTail_3] = OneMessage; - } - else - J1939_Flags.ReceivedMessagesDropped = 1; - break; - } - case Select_CAN_NODE_4: - { - if ( (J1939_OVERWRITE_RX_QUEUE == J1939_TRUE) || - (RXQueueCount_4 < J1939_RX_QUEUE_SIZE)) - { - if (RXQueueCount_4 < J1939_RX_QUEUE_SIZE) - { - RXQueueCount_4 ++; - RXTail_4 ++; - if (RXTail_4 >= J1939_RX_QUEUE_SIZE) - RXTail_4 = 0; - }else{ - J1939_Flags.ReceivedMessagesdCover = 1; //产生数据覆盖 - J1939_Flags.ReceivedMessagesdCoverOrDroppedNode = Select_CAN_NODE_4; - } - RXQueue_4[RXTail_4] = OneMessage; - } - else - J1939_Flags.ReceivedMessagesDropped = 1; - break; - } - default : - { - break; - } - } - } - - } - } +#endif /* J1939_TP_RX_TX */ + + case J1939_PF_REQUEST: + + /* 用OneMessage.Mxe.PGN 来存下被请求的PGN */ + if (OneMessage.Mxe.Data[1] < 240) { + OneMessage.Mxe.PGN = (j1939_uint32_t) ((OneMessage.Mxe.Data[2] << 16) & 0x030000) + + (j1939_uint32_t) ((OneMessage.Mxe.Data[1] << 8) & 0xFF00) + + 0x00; + } else { + OneMessage.Mxe.PGN = (j1939_uint32_t) ((OneMessage.Mxe.Data[2] << 16) & 0x030000) + + (j1939_uint32_t) ((OneMessage.Mxe.Data[1] << 8) & 0xFF00) + + (j1939_uint32_t) ((OneMessage.Mxe.Data[0]) & 0xFF); + } -} + J1939_Response(OneMessage.Mxe.PGN); + break; + + default: +#if J1939_TP_RX_TX +PutInReceiveQueue: { + /* + if (OneMessage.Mxe.PDUFormat < 240) { + OneMessage.Mxe.PGN = (j1939_uint32_t)((OneMessage.Array[0] << 16) & 0x030000) + + (j1939_uint32_t)((OneMessage.Array[1] << 8) & 0xFF00) + + 0x00; + } else { + OneMessage.Mxe.PGN = (j1939_uint32_t)((OneMessage.Array[0] << 16) & 0x030000) + + (j1939_uint32_t)((OneMessage.Array[1] << 8) & 0xFF00) + + (j1939_uint32_t)((OneMessage.Array[2]) & 0xFF); + } */ + if (OneMessage.Mxe.PDUFormat < 240) { + OneMessage.Mxe.PGN = (OneMessage.Mxe.Res << 17) + + (OneMessage.Mxe.DataPage << 16) + + (OneMessage.Mxe.PDUFormat << 8); + } else { + OneMessage.Mxe.PGN = (OneMessage.Mxe.Res << 17) + + (OneMessage.Mxe.DataPage << 16) + + (OneMessage.Mxe.PDUFormat << 8) + + OneMessage.Mxe.PDUSpecific; + } + + if ((J1939_OVERWRITE_RX_QUEUE == J1939_TRUE) || (RXQueueCount[Can_Node] < J1939_RX_QUEUE_SIZE)) { + if (RXQueueCount[Can_Node] < J1939_RX_QUEUE_SIZE) { + RXQueueCount[Can_Node]++; + RXTail[Can_Node]++; + + if (RXTail[Can_Node] >= J1939_RX_QUEUE_SIZE) { + RXTail[Can_Node] = 0; + } + } else { + J1939_Flags.ReceivedMessagesdCover = 1; /* 产生数据覆盖 */ + J1939_Flags.ReceivedMessagesdCoverOrDroppedNode = Can_Node; + } + + RXQueue[Can_Node][RXTail[Can_Node]] = OneMessage; + } else { + J1939_Flags.ReceivedMessagesDropped = 1; /* 产生数据溢出 */ + } + } +#endif /* J1939_TP_RX_TX */ + break; + } + } +} /** -* @return RC_SUCCESS 信息发送成功 -* @return RC_CANNOTTRANSMIT 系统没有发送消息,没有要发送的消息,或错误的CAN设备 -* @note 调用这个函数后,如果发送消息列队中有消息就位,则会发送消息 ,如果不能发送消息,相关的错误代码将返回。\n - 程序运行期间,中断是被失能的。 -*/ -static j1939_uint8_t J1939_TransmitMessages() -{ - switch (Can_Node) - { - case Select_CAN_NODE_1: - { - if (TXQueueCount_1 == 0) - { - //如果没有要发送的消息从发送消息列队中,恢复中断(清空发送标识位) - #if J1939_POLL_ECAN == J1939_FALSE - Port_TXinterruptEnable(); - #endif - return RC_CANNOTTRANSMIT; - } - else - { - while(TXQueueCount_1 > 0) - { - /*确保上次数据发送成功*/ - /**************可增加一个判断函数**************************/ - - TXQueue_1[TXHead_1].Mxe.SourceAddress = NodeAddress_1; - - SendOneMessage( (J1939_MESSAGE *) &(TXQueue_1[TXHead_1]) ); - TXHead_1 ++; - if (TXHead_1 >= J1939_TX_QUEUE_SIZE) - TXHead_1 = 0; - TXQueueCount_1 --; - } - - /*配置了一些标识位,使能中断*/ - #if J1939_POLL_ECAN == J1939_FALSE - Port_TXinterruptEnable(); - #endif - } - break; - } - case Select_CAN_NODE_2: - { - if (TXQueueCount_2 == 0) - { - //如果没有要发送的消息从发送消息列队中,恢复中断(清空发送标识位) - #if J1939_POLL_ECAN == J1939_FALSE - Port_TXinterruptEnable(); - #endif - return RC_CANNOTTRANSMIT; - } - else - { - - while(TXQueueCount_2 > 0) - { - /*确保上次数据发送成功*/ - /**************可增加一个判断函数**************************/ - - TXQueue_2[TXHead_2].Mxe.SourceAddress = NodeAddress_2; - - SendOneMessage( (J1939_MESSAGE *) &(TXQueue_2[TXHead_2]) ); - TXHead_2 ++; - if (TXHead_2 >= J1939_TX_QUEUE_SIZE) - TXHead_2 = 0; - TXQueueCount_2 --; - } - - /*配置了一些标识位,使能中断*/ - #if J1939_POLL_ECAN == J1939_FALSE - Port_TXinterruptEnable(); - #endif - } - break; - } - case Select_CAN_NODE_3: - { - if (TXQueueCount_3 == 0) - { - //如果没有要发送的消息从发送消息列队中,恢复中断(清空发送标识位) - #if J1939_POLL_ECAN == J1939_FALSE - Port_TXinterruptEnable(); - #endif - return RC_CANNOTTRANSMIT; - } - else - { - while(TXQueueCount_3 > 0) - { - /*确保上次数据发送成功*/ - /**************可增加一个判断函数**************************/ - - TXQueue_3[TXHead_3].Mxe.SourceAddress = NodeAddress_3; - - SendOneMessage( (J1939_MESSAGE *) &(TXQueue_3[TXHead_3]) ); - TXHead_3 ++; - if (TXHead_3 >= J1939_TX_QUEUE_SIZE) - TXHead_3 = 0; - TXQueueCount_3 --; - } - - /*配置了一些标识位,使能中断*/ - #if J1939_POLL_ECAN == J1939_FALSE - Port_TXinterruptEnable(); - #endif - } - break; - } - case Select_CAN_NODE_4: - { - if (TXQueueCount_4 == 0) - { - //如果没有要发送的消息从发送消息列队中,恢复中断(清空发送标识位) - #if J1939_POLL_ECAN == J1939_FALSE - Port_TXinterruptEnable(); - #endif - return RC_CANNOTTRANSMIT; - } - else - { - - while(TXQueueCount_4 > 0) - { - /*确保上次数据发送成功*/ - /**************可增加一个判断函数**************************/ - - TXQueue_4[TXHead_4].Mxe.SourceAddress = NodeAddress_4; - - SendOneMessage( (J1939_MESSAGE *) &(TXQueue_4[TXHead_4]) ); - TXHead_4 ++; - if (TXHead_4 >= J1939_TX_QUEUE_SIZE) - TXHead_4 = 0; - TXQueueCount_4 --; - } - - /*配置了一些标识位,使能中断*/ - #if J1939_POLL_ECAN == J1939_FALSE - Port_TXinterruptEnable(); - #endif - } - break; - } - default : - { - return RC_CANNOTTRANSMIT; - break; - } - } - - return RC_SUCCESS; + * @return RC_SUCCESS 信息发送成功 + * @return RC_CANNOTTRANSMIT 系统没有发送消息,没有要发送的消息,或错误的CAN设备 + * @note 调用这个函数后,如果发送消息队列中有消息就位,则会发送消息 ,如果不能发送消息,相关的错误代码将返回。\n + 程序运行期间,中断是被失能的。 + */ +static J1939_Status_t J1939_TransmitMessages(void) +{ + if (TXQueueCount[Can_Node] == 0) { + /* 如果没有要发送的消息从发送消息队列中,恢复中断(清空发送标识位) */ + Port_TXinterruptEnable(); + + return RC_CANNOTTRANSMIT; + } else { + while (TXQueueCount[Can_Node] > 0) { + /* 确保上次数据发送成功 */ + /**************可增加一个判断函数**************************/ + + TXQueue[Can_Node][TXHead[Can_Node]].Mxe.SourceAddress = NodeAddress[Can_Node]; + + SendOneMessage((J1939_MESSAGE_t *) & (TXQueue[Can_Node][TXHead[Can_Node]])); + TXHead[Can_Node]++; + + if (TXHead[Can_Node] >= J1939_TX_QUEUE_SIZE) { + TXHead[Can_Node] = 0; + } + + TXQueueCount[Can_Node]--; + } + + /* 配置了一些标识位,使能中断 */ + Port_TXinterruptEnable(); + } + + return RC_SUCCESS; } + #if J1939_TP_RX_TX /** -* @note 发送TP.DT,参考J1939-21 -*/ + * @note 发送TP.DT,参考J1939-21 + */ void J1939_TP_DT_Packet_send(void) { - J1939_MESSAGE _msg; - j1939_uint16_t _packet_offset_p; - j1939_int32_t _i=0; - _msg.Mxe.Priority = J1939_TP_DT_PRIORITY; - _msg.Mxe.DataPage =0; - _msg.Mxe.PDUFormat = J1939_PF_DT; - _msg.Mxe.DestinationAddress = TP_TX_MSG.tp_tx_msg.SA; - _msg.Mxe.DataLength = 8; - - - /*获取请求发送的数据包数量*/ - if(TP_TX_MSG.packets_request_num > 0) - { - TP_TX_MSG.packets_request_num--; - /*获取数据偏移指针*/ - _packet_offset_p = (j1939_uint16_t)(TP_TX_MSG.packet_offset_p*7u); - /*加载数据包编号*/ - _msg.Mxe.Data[0] = (j1939_uint8_t)(1u + TP_TX_MSG.packet_offset_p); + J1939_MESSAGE_t _msg; + j1939_uint16_t _packet_offset_p; + j1939_int32_t _i = 0; + _msg.Mxe.Priority = J1939_PRIORITY_TP_DT; + _msg.Mxe.DataPage = 0; + _msg.Mxe.PDUFormat = J1939_PF_TP_DT; + _msg.Mxe.DestinationAddress = TP_TX_MSG.tp_tx_msg.SA; + _msg.Mxe.DataLength = 8; - for(_i = 0; _i<7; _i++) - { - _msg.Mxe.Data[_i+1] = TP_TX_MSG.tp_tx_msg.data[_packet_offset_p + _i]; + /* 获取请求发送的数据包数量 */ + if (TP_TX_MSG.packets_request_num > 0) { + TP_TX_MSG.packets_request_num--; + /* 获取数据偏移指针 */ + _packet_offset_p = (j1939_uint16_t) (TP_TX_MSG.packet_offset_p * 7u); + /* 加载数据包编号 */ + _msg.Mxe.Data[0] = (j1939_uint8_t) (1u + TP_TX_MSG.packet_offset_p); + + for (_i = 0; _i < 7; _i++) { + _msg.Mxe.Data[_i + 1] = TP_TX_MSG.tp_tx_msg.data[_packet_offset_p + _i]; } - /*是否是最后一包数据消息*/ - if(TP_TX_MSG.packet_offset_p == (TP_TX_MSG.packets_total - 1u)) - { - /*参数群是否能被填满,是否需要填充,*/ - if ( _packet_offset_p > TP_TX_MSG.tp_tx_msg.byte_count - 7 ) - { - /*计算需要填充的数据数*/ - _i = TP_TX_MSG.tp_tx_msg.byte_count- _packet_offset_p - 7 ; - - for ( ; _i < 0 ; _i++ ) - { - /*我们默认J1939的参数群大小为8*/ - _msg.Mxe.Data[_i+8] = J1939_RESERVED_BYTE ; + + /* 是否是最后一包数据消息 */ + if (TP_TX_MSG.packet_offset_p == (TP_TX_MSG.packets_total - 1u)) { + /* 参数群是否能被填满,是否需要填充 */ + if (_packet_offset_p > TP_TX_MSG.tp_tx_msg.byte_count - 7) { + /* 计算需要填充的数据数 */ + _i = TP_TX_MSG.tp_tx_msg.byte_count - _packet_offset_p - 7; + + for (; _i < 0; _i++) { + /* 我们默认J1939的参数群大小为8 */ + _msg.Mxe.Data[_i + 8] = J1939_CONTROL_BYTE_RESERVED; } } - TP_TX_MSG.packets_request_num = 0; TP_TX_MSG.packet_offset_p = 0; TP_TX_MSG.time = J1939_TP_T3; - /* 跳转步骤,等待结束确认或则重新发送数据请求*/ + /* 跳转步骤,等待结束确认或则重新发送数据请求 */ TP_TX_MSG.state = J1939_TP_WAIT_ACK; - } - else - { - /*为下一个数据发送做准备*/ - TP_TX_MSG.packet_offset_p++; - TP_TX_MSG.state = J1939_TP_TX_DT; + } else { + /* 为下一个数据发送做准备 */ + TP_TX_MSG.packet_offset_p++; + TP_TX_MSG.state = J1939_TP_TX_DT; } - /*可能队列已满,发不出去,但是这里不能靠返回值进行无限的死等*/ + /* 可能队列已满,发不出去,但是这里不能靠返回值进行无限的死等 */ J1939_EnqueueMessage(&_msg, Can_Node); - } - else - { + } else { - TP_TX_MSG.packets_request_num = 0; - TP_TX_MSG.packet_offset_p = 0; - TP_TX_MSG.time = J1939_TP_T3; - TP_TX_MSG.state = J1939_TP_WAIT_ACK; + TP_TX_MSG.packets_request_num = 0; + TP_TX_MSG.packet_offset_p = 0; + TP_TX_MSG.time = J1939_TP_T3; + TP_TX_MSG.state = J1939_TP_WAIT_ACK; } } + /** -* @note 发送TP。CM-RTS,16,23,4,255,PGN消息,参考J1939-21, -*/ + * @note 发送TP。CM-RTS,16,23,4,255,PGN消息,参考J1939-21, + */ void J1939_CM_Start(void) { - j1939_uint32_t pgn_num; - J1939_MESSAGE _msg; + j1939_uint32_t pgn_num; + J1939_MESSAGE_t _msg; pgn_num = TP_TX_MSG.tp_tx_msg.PGN; - _msg.Mxe.Priority = J1939_TP_CM_PRIORITY; - _msg.Mxe.DataPage =0; + _msg.Mxe.Priority = J1939_PRIORITY_TP_CM; + _msg.Mxe.DataPage = 0; _msg.Mxe.PDUFormat = J1939_PF_TP_CM; _msg.Mxe.DestinationAddress = TP_TX_MSG.tp_tx_msg.SA; _msg.Mxe.DataLength = 8; - _msg.Mxe.Data[0] = J1939_RTS_CONTROL_BYTE; - _msg.Mxe.Data[1] = (j1939_uint8_t) TP_TX_MSG.tp_tx_msg.byte_count ; - _msg.Mxe.Data[2] = (j1939_uint8_t) ((TP_TX_MSG.tp_tx_msg.byte_count)>>8); + _msg.Mxe.Data[0] = J1939_CONTROL_BYTE_RTS; + _msg.Mxe.Data[1] = (j1939_uint8_t) TP_TX_MSG.tp_tx_msg.byte_count; + _msg.Mxe.Data[2] = (j1939_uint8_t) ((TP_TX_MSG.tp_tx_msg.byte_count) >> 8); _msg.Mxe.Data[3] = TP_TX_MSG.packets_total; - _msg.Mxe.Data[4] = J1939_RESERVED_BYTE; - _msg.Mxe.Data[7] = (j1939_uint8_t)((pgn_num>>16) & 0xff); - _msg.Mxe.Data[6] = (j1939_uint8_t)(pgn_num>>8 & 0xff); - _msg.Mxe.Data[5] = (j1939_uint8_t)(pgn_num & 0xff); + _msg.Mxe.Data[4] = J1939_CONTROL_BYTE_RESERVED; + _msg.Mxe.Data[7] = (j1939_uint8_t) ((pgn_num >> 16) & 0xff); + _msg.Mxe.Data[6] = (j1939_uint8_t) (pgn_num >> 8 & 0xff); + _msg.Mxe.Data[5] = (j1939_uint8_t) (pgn_num & 0xff); - /*可能队列已满,发不出去,但是这里不能靠返回值进行无限的死等*/ + /* 可能队列已满,发不出去,但是这里不能靠返回值进行无限的死等 */ J1939_EnqueueMessage(&_msg, Can_Node); - /*刷新等待时间,触发下一个步骤()*/ + /* 刷新等待时间,触发下一个步骤 */ TP_TX_MSG.time = J1939_TP_T3; TP_TX_MSG.state = J1939_TP_TX_CM_WAIT; - } + /** -* @note 中断TP链接 -*/ + * @note 中断TP链接 + */ void J1939_TP_TX_Abort(void) { - J1939_MESSAGE _msg; - j1939_uint32_t pgn_num; - - pgn_num = TP_TX_MSG.tp_tx_msg.PGN; - - _msg.Mxe.Priority = J1939_TP_CM_PRIORITY; - _msg.Mxe.DataPage =0; - _msg.Mxe.PDUFormat = J1939_PF_TP_CM; - _msg.Mxe.DestinationAddress = TP_TX_MSG.tp_tx_msg.SA; - _msg.Mxe.DataLength = 8; - _msg.Mxe.Data[0] = J1939_CONNABORT_CONTROL_BYTE; - _msg.Mxe.Data[1] = J1939_RESERVED_BYTE; - _msg.Mxe.Data[2] = J1939_RESERVED_BYTE; - _msg.Mxe.Data[3] = J1939_RESERVED_BYTE; - _msg.Mxe.Data[4] = J1939_RESERVED_BYTE; - _msg.Mxe.Data[7] = (j1939_uint8_t)((pgn_num>>16) & 0xff); - _msg.Mxe.Data[6] = (j1939_uint8_t)(pgn_num>>8 & 0xff); - _msg.Mxe.Data[5] = (j1939_uint8_t)(pgn_num & 0xff); - - /*可能队列已满,发不出去,但是这里不能靠返回值进行无限的死等*/ + J1939_MESSAGE_t _msg; + j1939_uint32_t pgn_num; + + pgn_num = TP_TX_MSG.tp_tx_msg.PGN; + + _msg.Mxe.Priority = J1939_PRIORITY_TP_CM; + _msg.Mxe.DataPage = 0; + _msg.Mxe.PDUFormat = J1939_PF_TP_CM; + _msg.Mxe.DestinationAddress = TP_TX_MSG.tp_tx_msg.SA; + _msg.Mxe.DataLength = 8; + _msg.Mxe.Data[0] = J1939_CONTROL_BYTE_CONNABORT; + _msg.Mxe.Data[1] = J1939_CONTROL_BYTE_RESERVED; + _msg.Mxe.Data[2] = J1939_CONTROL_BYTE_RESERVED; + _msg.Mxe.Data[3] = J1939_CONTROL_BYTE_RESERVED; + _msg.Mxe.Data[4] = J1939_CONTROL_BYTE_RESERVED; + _msg.Mxe.Data[7] = (j1939_uint8_t) ((pgn_num >> 16) & 0xff); + _msg.Mxe.Data[6] = (j1939_uint8_t) (pgn_num >> 8 & 0xff); + _msg.Mxe.Data[5] = (j1939_uint8_t) (pgn_num & 0xff); + + /* 可能队列已满,发不出去,但是这里不能靠返回值进行无限的死等 */ J1939_EnqueueMessage(&_msg, Can_Node); - /*结束发送*/ + /* 结束发送 */ TP_TX_MSG.state = J1939_TX_DONE; - } + /** -* @note 中断TP链接 -*/ + * @note 中断TP链接 + */ void J1939_TP_RX_Abort(void) { - J1939_MESSAGE _msg; - j1939_uint32_t pgn_num; - - pgn_num = TP_RX_MSG.tp_rx_msg.PGN; - - _msg.Mxe.Priority = J1939_TP_CM_PRIORITY; - _msg.Mxe.DataPage =0; - _msg.Mxe.PDUFormat = J1939_PF_TP_CM; - _msg.Mxe.DestinationAddress = TP_RX_MSG.tp_rx_msg.SA; - _msg.Mxe.DataLength = 8; - _msg.Mxe.Data[0] = J1939_CONNABORT_CONTROL_BYTE; - _msg.Mxe.Data[1] = J1939_RESERVED_BYTE; - _msg.Mxe.Data[2] = J1939_RESERVED_BYTE; - _msg.Mxe.Data[3] = J1939_RESERVED_BYTE; - _msg.Mxe.Data[4] = J1939_RESERVED_BYTE; - _msg.Mxe.Data[7] = (j1939_uint8_t)((pgn_num>>16) & 0xff); - _msg.Mxe.Data[6] = (j1939_uint8_t)(pgn_num>>8 & 0xff); - _msg.Mxe.Data[5] = (j1939_uint8_t)(pgn_num & 0xff); - - /*可能队列已满,发不出去,但是这里不能靠返回值进行无限的死等*/ + J1939_MESSAGE_t _msg; + j1939_uint32_t pgn_num; + + pgn_num = TP_RX_MSG.tp_rx_msg.PGN; + + _msg.Mxe.Priority = J1939_PRIORITY_TP_CM; + _msg.Mxe.DataPage = 0; + _msg.Mxe.PDUFormat = J1939_PF_TP_CM; + _msg.Mxe.DestinationAddress = TP_RX_MSG.tp_rx_msg.SA; + _msg.Mxe.DataLength = 8; + _msg.Mxe.Data[0] = J1939_CONTROL_BYTE_CONNABORT; + _msg.Mxe.Data[1] = J1939_CONTROL_BYTE_RESERVED; + _msg.Mxe.Data[2] = J1939_CONTROL_BYTE_RESERVED; + _msg.Mxe.Data[3] = J1939_CONTROL_BYTE_RESERVED; + _msg.Mxe.Data[4] = J1939_CONTROL_BYTE_RESERVED; + _msg.Mxe.Data[7] = (j1939_uint8_t) ((pgn_num >> 16) & 0xff); + _msg.Mxe.Data[6] = (j1939_uint8_t) (pgn_num >> 8 & 0xff); + _msg.Mxe.Data[5] = (j1939_uint8_t) (pgn_num & 0xff); + + /* 可能队列已满,发不出去,但是这里不能靠返回值进行无限的死等 */ J1939_EnqueueMessage(&_msg, Can_Node); - /*结束发送*/ + /* 结束发送 */ TP_RX_MSG.state = J1939_RX_DONE; - } + /** -* @note TP的计时器 -*/ + * @note TP的计时器 + */ j1939_uint8_t J1939_TP_TX_RefreshCMTimer(j1939_uint16_t dt_ms) { - if((J1939_TP_TX_CM_WAIT == TP_TX_MSG.state)||(J1939_TP_WAIT_ACK == TP_TX_MSG.state)) - { - if(TP_TX_MSG.time > dt_ms) - { - TP_TX_MSG.time = TP_TX_MSG.time - dt_ms; - return J1939_TP_TIMEOUT_NORMAL; - } - else - { - /*超时 */ - TP_TX_MSG.time = 0u; - return J1939_TP_TIMEOUT_ABNORMAL; - } - - } - else - { - return J1939_TP_TIMEOUT_NORMAL; - } + if ((J1939_TP_TX_CM_WAIT == TP_TX_MSG.state) || (J1939_TP_WAIT_ACK == TP_TX_MSG.state)) { + if (TP_TX_MSG.time > dt_ms) { + TP_TX_MSG.time = TP_TX_MSG.time - dt_ms; + return J1939_TP_TIMEOUT_NORMAL; + } else { + /* 超时 */ + TP_TX_MSG.time = 0u; + return J1939_TP_TIMEOUT_ABNORMAL; + } + + } else { + return J1939_TP_TIMEOUT_NORMAL; + } } + /** -* @note TP的计时器 -*/ + * @note TP的计时器 + */ j1939_uint8_t J1939_TP_RX_RefreshCMTimer(j1939_uint16_t dt_ms) { - if((J1939_TP_RX_DATA_WAIT == TP_RX_MSG.state)) - { - if(TP_RX_MSG.time > dt_ms) - { - TP_RX_MSG.time = TP_RX_MSG.time - dt_ms; - return J1939_TP_TIMEOUT_NORMAL; - } - else - { - /*超时 */ - TP_RX_MSG.time = 0u; - return J1939_TP_TIMEOUT_ABNORMAL; - } - - } - else - { - return J1939_TP_TIMEOUT_NORMAL; - } + if ((J1939_TP_RX_DATA_WAIT == TP_RX_MSG.state)) { + if (TP_RX_MSG.time > dt_ms) { + TP_RX_MSG.time = TP_RX_MSG.time - dt_ms; + return J1939_TP_TIMEOUT_NORMAL; + } else { + /* 超时 */ + TP_RX_MSG.time = 0u; + return J1939_TP_TIMEOUT_ABNORMAL; + } + + } else { + return J1939_TP_TIMEOUT_NORMAL; + } } /** -* @note 发送读取数据 TP.CM_CTS 和 EndofMsgAck消息。 -*/ -void J1939_read_DT_Packet() + * @note 发送读取数据 TP.CM_CTS 和 EndofMsgAck消息。 + */ +void J1939_read_DT_Packet(void) { - J1939_MESSAGE _msg; - j1939_uint32_t pgn_num; - pgn_num = TP_RX_MSG.tp_rx_msg.PGN; - - _msg.Mxe.Priority = J1939_TP_CM_PRIORITY; - _msg.Mxe.DataPage =0; - _msg.Mxe.PDUFormat = J1939_PF_TP_CM; - _msg.Mxe.DestinationAddress = TP_RX_MSG.tp_rx_msg.SA; - _msg.Mxe.DataLength = 8; - - /*如果系统繁忙,保持链接但是不传送消息*/ - if(TP_RX_MSG.osbusy) - { - _msg.Mxe.Data[0] = J1939_CTS_CONTROL_BYTE; - _msg.Mxe.Data[1] = 0; - _msg.Mxe.Data[2] = J1939_RESERVED_BYTE; - _msg.Mxe.Data[3] = J1939_RESERVED_BYTE; - _msg.Mxe.Data[4] = J1939_RESERVED_BYTE; - _msg.Mxe.Data[7] = (j1939_uint8_t)((pgn_num>>16) & 0xff); - _msg.Mxe.Data[6] = (j1939_uint8_t)(pgn_num>>8 & 0xff); - _msg.Mxe.Data[5] = (j1939_uint8_t)(pgn_num & 0xff); - /*可能队列已满,发不出去,但是这里不能靠返回值进行无限的死等*/ + J1939_MESSAGE_t _msg; + j1939_uint32_t pgn_num; + pgn_num = TP_RX_MSG.tp_rx_msg.PGN; + + _msg.Mxe.Priority = J1939_PRIORITY_TP_CM; + _msg.Mxe.DataPage = 0; + _msg.Mxe.PDUFormat = J1939_PF_TP_CM; + _msg.Mxe.DestinationAddress = TP_RX_MSG.tp_rx_msg.SA; + _msg.Mxe.DataLength = 8; + + /* 如果系统繁忙,保持链接但是不传送消息 */ + if (TP_RX_MSG.osbusy) { + _msg.Mxe.Data[0] = J1939_CONTROL_BYTE_CTS; + _msg.Mxe.Data[1] = 0; + _msg.Mxe.Data[2] = J1939_CONTROL_BYTE_RESERVED; + _msg.Mxe.Data[3] = J1939_CONTROL_BYTE_RESERVED; + _msg.Mxe.Data[4] = J1939_CONTROL_BYTE_RESERVED; + _msg.Mxe.Data[7] = (j1939_uint8_t) ((pgn_num >> 16) & 0xff); + _msg.Mxe.Data[6] = (j1939_uint8_t) (pgn_num >> 8 & 0xff); + _msg.Mxe.Data[5] = (j1939_uint8_t) (pgn_num & 0xff); + /* 可能队列已满,发不出去,但是这里不能靠返回值进行无限的死等 */ J1939_EnqueueMessage(&_msg, Can_Node); - return ; - } - if(TP_RX_MSG.packets_total > TP_RX_MSG.packets_ok_num) - { - /*最后一次响应,如果不足2包数据*/ - if((TP_RX_MSG.packets_total - TP_RX_MSG.packets_ok_num)==1) - { - _msg.Mxe.Data[0] = J1939_CTS_CONTROL_BYTE; - _msg.Mxe.Data[1] = 1; - _msg.Mxe.Data[2] = TP_RX_MSG.packets_total; - _msg.Mxe.Data[3] = J1939_RESERVED_BYTE; - _msg.Mxe.Data[4] = J1939_RESERVED_BYTE; - _msg.Mxe.Data[7] = (j1939_uint8_t)((pgn_num>>16) & 0xff); - _msg.Mxe.Data[6] = (j1939_uint8_t)(pgn_num>>8 & 0xff); - _msg.Mxe.Data[5] = (j1939_uint8_t)(pgn_num & 0xff); - /*可能队列已满,发不出去,但是这里不能靠返回值进行无限的死等*/ + return; + } + + if (TP_RX_MSG.packets_total > TP_RX_MSG.packets_ok_num) { + /* 最后一次响应,如果不足2包数据 */ + if ((TP_RX_MSG.packets_total - TP_RX_MSG.packets_ok_num) == 1) { + _msg.Mxe.Data[0] = J1939_CONTROL_BYTE_CTS; + _msg.Mxe.Data[1] = 1; + _msg.Mxe.Data[2] = TP_RX_MSG.packets_total; + _msg.Mxe.Data[3] = J1939_CONTROL_BYTE_RESERVED; + _msg.Mxe.Data[4] = J1939_CONTROL_BYTE_RESERVED; + _msg.Mxe.Data[7] = (j1939_uint8_t) ((pgn_num >> 16) & 0xff); + _msg.Mxe.Data[6] = (j1939_uint8_t) (pgn_num >> 8 & 0xff); + _msg.Mxe.Data[5] = (j1939_uint8_t) (pgn_num & 0xff); + /* 可能队列已满,发不出去,但是这里不能靠返回值进行无限的死等 */ J1939_EnqueueMessage(&_msg, Can_Node); - TP_RX_MSG.state = J1939_TP_RX_DATA_WAIT; - return ; - } - _msg.Mxe.Data[0] = J1939_CTS_CONTROL_BYTE; - _msg.Mxe.Data[1] = 2; - _msg.Mxe.Data[2] = (TP_RX_MSG.packets_ok_num + 1); - _msg.Mxe.Data[3] = J1939_RESERVED_BYTE; - _msg.Mxe.Data[4] = J1939_RESERVED_BYTE; - _msg.Mxe.Data[7] = (j1939_uint8_t)((pgn_num>>16) & 0xff); - _msg.Mxe.Data[6] = (j1939_uint8_t)(pgn_num>>8 & 0xff); - _msg.Mxe.Data[5] = (j1939_uint8_t)(pgn_num & 0xff); - - /*可能队列已满,发不出去,但是这里不能靠返回值进行无限的死等*/ + TP_RX_MSG.state = J1939_TP_RX_DATA_WAIT; + return; + } + + _msg.Mxe.Data[0] = J1939_CONTROL_BYTE_CTS; + _msg.Mxe.Data[1] = 2; + _msg.Mxe.Data[2] = (TP_RX_MSG.packets_ok_num + 1); + _msg.Mxe.Data[3] = J1939_CONTROL_BYTE_RESERVED; + _msg.Mxe.Data[4] = J1939_CONTROL_BYTE_RESERVED; + _msg.Mxe.Data[7] = (j1939_uint8_t) ((pgn_num >> 16) & 0xff); + _msg.Mxe.Data[6] = (j1939_uint8_t) (pgn_num >> 8 & 0xff); + _msg.Mxe.Data[5] = (j1939_uint8_t) (pgn_num & 0xff); + + /* 可能队列已满,发不出去,但是这里不能靠返回值进行无限的死等 */ J1939_EnqueueMessage(&_msg, Can_Node); - TP_RX_MSG.state = J1939_TP_RX_DATA_WAIT; - return ; - }else - { - /*发送传输正常结束消息,EndofMsgAck*/ - _msg.Mxe.Data[0] = J1939_EOMACK_CONTROL_BYTE; - _msg.Mxe.Data[1] = (TP_RX_MSG.tp_rx_msg.byte_count & 0x00ff); - _msg.Mxe.Data[2] = ((TP_RX_MSG.tp_rx_msg.byte_count >> 8) & 0x00ff); - _msg.Mxe.Data[3] = TP_RX_MSG.packets_total; - _msg.Mxe.Data[4] = J1939_RESERVED_BYTE; - _msg.Mxe.Data[7] = (j1939_uint8_t)((pgn_num>>16) & 0xff); - _msg.Mxe.Data[6] = (j1939_uint8_t)(pgn_num>>8 & 0xff); - _msg.Mxe.Data[5] = (j1939_uint8_t)(pgn_num & 0xff); - /*可能队列已满,发不出去,但是这里不能靠返回值进行无限的死等*/ + TP_RX_MSG.state = J1939_TP_RX_DATA_WAIT; + return; + } else { + /* 发送传输正常结束消息,EndofMsgAck */ + _msg.Mxe.Data[0] = J1939_CONTROL_BYTE_EOMACK; + _msg.Mxe.Data[1] = (TP_RX_MSG.tp_rx_msg.byte_count & 0x00ff); + _msg.Mxe.Data[2] = ((TP_RX_MSG.tp_rx_msg.byte_count >> 8) & 0x00ff); + _msg.Mxe.Data[3] = TP_RX_MSG.packets_total; + _msg.Mxe.Data[4] = J1939_CONTROL_BYTE_RESERVED; + _msg.Mxe.Data[7] = (j1939_uint8_t) ((pgn_num >> 16) & 0xff); + _msg.Mxe.Data[6] = (j1939_uint8_t) (pgn_num >> 8 & 0xff); + _msg.Mxe.Data[5] = (j1939_uint8_t) (pgn_num & 0xff); + /* 可能队列已满,发不出去,但是这里不能靠返回值进行无限的死等 */ J1939_EnqueueMessage(&_msg, Can_Node); - TP_RX_MSG.state = J1939_RX_DONE; - return ; - } + TP_RX_MSG.state = J1939_RX_DONE; + return; + } } + /** -* @note TP协议的心跳,为了满足在总线的计时准确,10ms轮询一次 J1939_TP_TX_RefreshCMTimer(10)\n - 如果想要更高的分辨率,1ms轮询一次,但是要改下面计时函数 J1939_TP_TX_RefreshCMTimer(1) -*/ -void J1939_TP_Poll() + * @note TP协议的心跳,为了满足在总线的计时准确,10ms轮询一次 J1939_TP_TX_RefreshCMTimer(10)\n + 如果想要更高的分辨率,1ms轮询一次,但是要改下面计时函数 J1939_TP_TX_RefreshCMTimer(1) + */ +void J1939_TP_Poll(void) { - if(J1939_TP_Flags_t.state == J1939_TP_NULL || J1939_TP_Flags_t.state == J1939_TP_OSBUSY) - { - return ; - } - if(J1939_TP_Flags_t.state == J1939_TP_RX) - { - Can_Node = J1939_TP_Flags_t.TP_RX_CAN_NODE; - switch(TP_RX_MSG.state) - { - case J1939_TP_RX_WAIT: - ; - break; - case J1939_TP_RX_READ_DATA: - /*发送读取数据 TP.CM_CTS 和 EndofMsgAck消息*/ - J1939_read_DT_Packet(); - break; - case J1939_TP_RX_DATA_WAIT: - /*等待TP.DT帧传输的消息*/ - if(J1939_TP_TIMEOUT_ABNORMAL == J1939_TP_RX_RefreshCMTimer(10)) - { - /* 等待超时,发生连接异常,跳转到异常步骤 */ - TP_RX_MSG.state = J1939_TP_RX_ERROR; - } - break; - case J1939_TP_RX_ERROR: - J1939_TP_RX_Abort(); - J1939_TP_Flags_t.TP_RX_CAN_NODE = Select_CAN_NODE_Null; - break; - case J1939_RX_DONE: - TP_RX_MSG.packets_ok_num = 0; - TP_RX_MSG.packets_total = 0; - TP_RX_MSG.time = J1939_TP_T3; - TP_RX_MSG.state = J1939_TP_RX_WAIT; - J1939_TP_Flags_t.state = J1939_TP_NULL; - break; - default: - break; - } - return ; - } - if(J1939_TP_Flags_t.state == J1939_TP_TX) - { - Can_Node = J1939_TP_Flags_t.TP_TX_CAN_NODE; - switch (TP_TX_MSG.state) - { - case J1939_TP_TX_WAIT: - /*没有要发送的数据*/ - break; - case J1939_TP_TX_CM_START: - /*发送TP.CM_RTS帧传输的消息(参考j1939-21)*/ - J1939_CM_Start(); - break; - case J1939_TP_TX_CM_WAIT: - /*等待TP.CM_CTS帧传输的消息*/ - if(J1939_TP_TIMEOUT_ABNORMAL == J1939_TP_TX_RefreshCMTimer(10)) - { - /* 等待超时,发生连接异常,跳转到异常步骤 */ - TP_TX_MSG.state = J1939_TP_TX_ERROR; - } - break; - case J1939_TP_TX_DT: - J1939_TP_DT_Packet_send(); - break; - case J1939_TP_WAIT_ACK: - /*等待TP.EndofMsgACK帧传输的消息*/ - if(J1939_TP_TIMEOUT_ABNORMAL == J1939_TP_TX_RefreshCMTimer(10)) - { - /* 等待超时,发生连接异常,跳转到异常步骤 */ - TP_TX_MSG.state = J1939_TP_TX_ERROR; - } - break; - case J1939_TP_TX_ERROR: - J1939_TP_TX_Abort(); - - break; - case J1939_TX_DONE: - TP_TX_MSG.packets_request_num = 0; - TP_TX_MSG.packet_offset_p = 0; - TP_TX_MSG.time = J1939_TP_T3; - TP_TX_MSG.state = J1939_TP_TX_WAIT; - J1939_TP_Flags_t.state = J1939_TP_NULL; - break; - default: - //程序不会运行到这里来,可以增加一个调试输出 - break; - } - return ; - } + if (J1939_TP_Flags_t.state == J1939_TP_NULL || J1939_TP_Flags_t.state == J1939_TP_OSBUSY) { + return; + } + + if (J1939_TP_Flags_t.state == J1939_TP_RX) { + Can_Node = J1939_TP_Flags_t.TP_RX_CAN_NODE; + + switch (TP_RX_MSG.state) { + case J1939_TP_RX_WAIT: + ; + break; + + case J1939_TP_RX_READ_DATA: + /* 发送读取数据 TP.CM_CTS 和 EndofMsgAck消息 */ + J1939_read_DT_Packet(); + break; + + case J1939_TP_RX_DATA_WAIT: + + /* 等待TP.DT帧传输的消息 */ + if (J1939_TP_TIMEOUT_ABNORMAL == J1939_TP_RX_RefreshCMTimer(10)) { + /* 等待超时,发生连接异常,跳转到异常步骤 */ + TP_RX_MSG.state = J1939_TP_RX_ERROR; + } + + break; + + case J1939_TP_RX_ERROR: + J1939_TP_RX_Abort(); + J1939_TP_Flags_t.TP_RX_CAN_NODE = Select_CAN_NODE_Null; + break; + + case J1939_RX_DONE: + TP_RX_MSG.packets_ok_num = 0; + TP_RX_MSG.packets_total = 0; + TP_RX_MSG.time = J1939_TP_T3; + TP_RX_MSG.state = J1939_TP_RX_WAIT; + J1939_TP_Flags_t.state = J1939_TP_NULL; + break; + + default: + break; + } + + return; + } + + if (J1939_TP_Flags_t.state == J1939_TP_TX) { + Can_Node = J1939_TP_Flags_t.TP_TX_CAN_NODE; + + switch (TP_TX_MSG.state) { + case J1939_TP_TX_WAIT: + /* 没有要发送的数据 */ + break; + + case J1939_TP_TX_CM_START: + /* 发送TP.CM_RTS帧传输的消息(参考J1939-21) */ + J1939_CM_Start(); + break; + + case J1939_TP_TX_CM_WAIT: + + /* 等待TP.CM_CTS帧传输的消息 */ + if (J1939_TP_TIMEOUT_ABNORMAL == J1939_TP_TX_RefreshCMTimer(10)) { + /* 等待超时,发生连接异常,跳转到异常步骤 */ + TP_TX_MSG.state = J1939_TP_TX_ERROR; + } + + break; + + case J1939_TP_TX_DT: + J1939_TP_DT_Packet_send(); + break; + + case J1939_TP_WAIT_ACK: + + /* 等待TP.EndofMsgACK帧传输的消息 */ + if (J1939_TP_TIMEOUT_ABNORMAL == J1939_TP_TX_RefreshCMTimer(10)) { + /* 等待超时,发生连接异常,跳转到异常步骤 */ + TP_TX_MSG.state = J1939_TP_TX_ERROR; + } + + break; + + case J1939_TP_TX_ERROR: + J1939_TP_TX_Abort(); + + break; + + case J1939_TX_DONE: + TP_TX_MSG.packets_request_num = 0; + TP_TX_MSG.packet_offset_p = 0; + TP_TX_MSG.time = J1939_TP_T3; + TP_TX_MSG.state = J1939_TP_TX_WAIT; + J1939_TP_Flags_t.state = J1939_TP_NULL; + break; + + default: + /* 程序不会运行到这里来,可以增加一个调试输出 */ + break; + } + + return; + } } /**这是一个非阻塞io接口 -* -* @param[in] PGN TP会话的参数群编号 -* @param[in] SA TP会话的目标地址 -* @param[in] *data TP会话的数据缓存地址 -* @param[in] data_num TP会话的数据大小 -* @param[in] _Can_Node 要入队的CAN硬件编号(要选择的使用的CAN硬件编号) -* @return RC_SUCCESS 成功打开TP链接,开始进入发送流程 -* @return RC_CANNOTTRANSMIT 不能发送,因为TP协议已经建立虚拟链接,并且未断开 -* @note TP协议的发送函数 -*/ -j1939_int8_t J1939_TP_TX_Message(j1939_uint32_t PGN,j1939_uint8_t DA,j1939_uint8_t *data,j1939_uint16_t data_num, CAN_NODE _Can_Node) + * + * @param[in] PGN TP会话的参数群编号 + * @param[in] SA TP会话的目标地址 + * @param[in] *data TP会话的数据缓存地址 + * @param[in] data_num TP会话的数据大小 + * @param[in] _Can_Node 要入队的CAN硬件编号(要选择的使用的CAN硬件编号) + * @return RC_SUCCESS 成功打开TP链接,开始进入发送流程 + * @return RC_CANNOTTRANSMIT 不能发送,因为TP协议已经建立虚拟链接,并且未断开 + * @note TP协议的发送函数 + */ +J1939_Status_t J1939_TP_TX_Message(j1939_uint32_t PGN, j1939_uint8_t DA, j1939_uint8_t *data, j1939_uint16_t data_num, + CAN_NODE_t _Can_Node) { - j1939_uint16_t _byte_count =0; - /*取得发送权限*/ - if(J1939_TP_Flags_t.state == J1939_TP_NULL) - { - J1939_TP_Flags_t.state = J1939_TP_TX; - J1939_TP_Flags_t.TP_TX_CAN_NODE = _Can_Node; - }else - { - return RC_CANNOTTRANSMIT;//不能发送,因为TP协议已经建立虚拟链接,并且未断开 - } - - TP_TX_MSG.tp_tx_msg.PGN = PGN; - TP_TX_MSG.tp_tx_msg.SA = DA; - TP_TX_MSG.tp_tx_msg.byte_count = data_num; - for(_byte_count = 0;_byte_count < data_num;_byte_count++) - { - TP_TX_MSG.tp_tx_msg.data[_byte_count] = data[_byte_count]; - } - TP_TX_MSG.packet_offset_p = 0; - TP_TX_MSG.packets_request_num = 0; - TP_TX_MSG.packets_total = data_num/7; - if((data_num%7) != 0) - { - TP_TX_MSG.packets_total ++; - } - TP_TX_MSG.time = J1939_TP_T3; - //触发开始CM_START - TP_TX_MSG.state = J1939_TP_TX_CM_START; - - - return RC_SUCCESS; + j1939_uint16_t _byte_count = 0; + + /* 取得发送权限 */ + if (J1939_TP_Flags_t.state == J1939_TP_NULL) { + J1939_TP_Flags_t.state = J1939_TP_TX; + J1939_TP_Flags_t.TP_TX_CAN_NODE = _Can_Node; + } else { + return RC_CANNOTTRANSMIT; /* 不能发送,因为TP协议已经建立虚拟链接,并且未断开 */ + } + + TP_TX_MSG.tp_tx_msg.PGN = PGN; + TP_TX_MSG.tp_tx_msg.SA = DA; + TP_TX_MSG.tp_tx_msg.byte_count = data_num; + + for (_byte_count = 0; _byte_count < data_num; _byte_count++) { + TP_TX_MSG.tp_tx_msg.data[_byte_count] = data[_byte_count]; + } + + TP_TX_MSG.packet_offset_p = 0; + TP_TX_MSG.packets_request_num = 0; + TP_TX_MSG.packets_total = data_num / 7; + + if ((data_num % 7) != 0) { + TP_TX_MSG.packets_total++; + } + + TP_TX_MSG.time = J1939_TP_T3; + /* 触发开始CM_START */ + TP_TX_MSG.state = J1939_TP_TX_CM_START; + + return RC_SUCCESS; } /** -* @param[in] msg.data 读取数据的缓存 -* @param[in] msg.data_num 读取数据的缓存大小 -* @param[in] _Can_Node 要入队的CAN硬件编号(要选择的使用的CAN硬件编号) -* @param[out] msg.SA 数据源地址 -* @param[out] msg.byte_count 数据大小 -* @param[out] msg.PGN 数据参数群编号 -* @return RC_CANNOTRECEIVE 不能接受,TP协议正在接受数据中 -* @return RC_SUCCESS 读取数据成功 -* @note TP的接受函数 , 接受缓存的大小必须大于接受数据的大小,建议初始化缓存大小用 J1939_TP_MAX_MESSAGE_LENGTH\n - 请正确带入 缓存区的大小,参数错误程序运行有风险 -*/ -j1939_int8_t J1939_TP_RX_Message(TP_RX_MESSAGE *msg, CAN_NODE _Can_Node) + * @param[in] msg.data 读取数据的缓存 + * @param[in] msg.data_num 读取数据的缓存大小 + * @param[in] _Can_Node 要入队的CAN硬件编号(要选择的使用的CAN硬件编号) + * @param[out] msg.SA 数据源地址 + * @param[out] msg.byte_count 数据大小 + * @param[out] msg.PGN 数据参数群编号 + * @return RC_CANNOTRECEIVE 不能接受,TP协议正在接受数据中 + * @return RC_SUCCESS 读取数据成功 + * @note TP的接受函数 , 接受缓存的大小必须大于接受数据的大小,建议初始化缓存大小用 J1939_TP_MAX_MESSAGE_LENGTH\n + 请正确带入 缓存区的大小,参数错误程序运行有风险 + */ +J1939_Status_t J1939_TP_RX_Message(TP_RX_MESSAGE_t *msg, CAN_NODE_t _Can_Node) { - j1939_uint16_t _a = 0; - /*判断是否能读取数据*/ - if(J1939_TP_Flags_t.state == J1939_TP_NULL && TP_RX_MSG.tp_rx_msg.PGN != 0) - { - J1939_TP_Flags_t.state = J1939_TP_OSBUSY; - }else - { - return RC_CANNOTRECEIVE;//不能接受,TP协议正在接受数据中,或没有数据 - } - //判断是不是要读取那一路CAN数据 - if(_Can_Node != J1939_TP_Flags_t.TP_RX_CAN_NODE) - { - /*释放TP接管权限*/ - if(J1939_TP_Flags_t.state == J1939_TP_OSBUSY) - { + j1939_uint16_t _a = 0; + + /* 判断是否能读取数据 */ + if (J1939_TP_Flags_t.state == J1939_TP_NULL && TP_RX_MSG.tp_rx_msg.PGN != 0) { + J1939_TP_Flags_t.state = J1939_TP_OSBUSY; + } else { + return RC_CANNOTRECEIVE; /* 不能接受,TP协议正在接受数据中,或没有数据 */ + } + + /* 判断是不是要读取那一路CAN数据 */ + if (_Can_Node != J1939_TP_Flags_t.TP_RX_CAN_NODE) { + /* 释放TP接管权限 */ + if (J1939_TP_Flags_t.state == J1939_TP_OSBUSY) { J1939_TP_Flags_t.state = J1939_TP_NULL; } - return RC_CANNOTRECEIVE; - } - //判断数据缓存够不够 - if((msg->data_num) < TP_RX_MSG.tp_rx_msg.byte_count) - { - return RC_CANNOTRECEIVE;//不能接受,缓存区太小 - } - - /*获取数据*/ - for(_a = 0;_a < msg->data_num;_a++) - { + + return RC_CANNOTRECEIVE; + } + + /* 判断数据缓存够不够 */ + if ((msg->data_num) < TP_RX_MSG.tp_rx_msg.byte_count) { + return RC_CANNOTRECEIVE; /* 不能接受,缓存区太小 */ + } + + /* 获取数据 */ + for (_a = 0; _a < msg->data_num; _a++) { msg->data[_a] = TP_RX_MSG.tp_rx_msg.data[_a]; - } - /*获取数据 源地址*/ - msg->SA = TP_RX_MSG.tp_rx_msg.SA; - /*获取数据的大小*/ - msg->byte_count = TP_RX_MSG.tp_rx_msg.byte_count; - /*获取数据PGN*/ - msg->PGN = TP_RX_MSG.tp_rx_msg.PGN; - - /*丢弃读取过的数据*/ - TP_RX_MSG.tp_rx_msg.byte_count= 0u; - TP_RX_MSG.tp_rx_msg.PGN = 0; - - /*释放TP接管权限*/ - if(J1939_TP_Flags_t.state == J1939_TP_OSBUSY) - { - J1939_TP_Flags_t.state = J1939_TP_NULL; - } - - return RC_SUCCESS; + } + + /* 获取数据 源地址 */ + msg->SA = TP_RX_MSG.tp_rx_msg.SA; + /* 获取数据的大小 */ + msg->byte_count = TP_RX_MSG.tp_rx_msg.byte_count; + /* 获取数据PGN */ + msg->PGN = TP_RX_MSG.tp_rx_msg.PGN; + + /* 丢弃读取过的数据 */ + TP_RX_MSG.tp_rx_msg.byte_count = 0u; + TP_RX_MSG.tp_rx_msg.PGN = 0; + + /* 释放TP接管权限 */ + if (J1939_TP_Flags_t.state == J1939_TP_OSBUSY) { + J1939_TP_Flags_t.state = J1939_TP_NULL; + } + + return RC_SUCCESS; } + /** -* @param[in] pgn 被请求的参数群 -* @param[in] DA 目标地址(DestinationAddress) 当DA = 0xff表示是全局请求 -* @param[in] _Can_Node 要入队的CAN硬件编号(要选择的使用的CAN硬件编号) -* @note 请求(从全局范围或则特定目的地的)参数群,请求规则J1939-21的16-17页,有明确的说明 -*/ -void J1939_Request_PGN(j1939_uint32_t pgn ,j1939_uint8_t DA, CAN_NODE _Can_Node) + * @param[in] pgn 被请求的参数群 + * @param[in] DA 目标地址(DestinationAddress) 当DA = 0xff表示是全局请求 + * @param[in] _Can_Node 要入队的CAN硬件编号(要选择的使用的CAN硬件编号) + * @note 请求(从全局范围或则特定目的地的)参数群,请求规则J1939-21的16-17页,有明确的说明 + */ +void J1939_Request_PGN(j1939_uint32_t PGN, j1939_uint8_t DA, CAN_NODE_t _Can_Node) { - J1939_MESSAGE _msg; - - _msg.Mxe.DataPage = 0; - _msg.Mxe.Priority = J1939_REQUEST_PRIORITY; - _msg.Mxe.DestinationAddress = DA; - _msg.Mxe.DataLength = 3; - _msg.Mxe.PDUFormat = J1939_PF_REQUEST; - _msg.Mxe.Data[0] = (j1939_uint8_t)(pgn & 0x000000FF); - _msg.Mxe.Data[1] = (j1939_uint8_t)((pgn & 0x0000FF00) >> 8); - _msg.Mxe.Data[2] = (j1939_uint8_t)((pgn & 0x00FF0000) >> 16); - - while (J1939_EnqueueMessage( &_msg, _Can_Node) != RC_SUCCESS); + J1939_MESSAGE_t _msg; + + _msg.Mxe.DataPage = 0; + _msg.Mxe.Priority = J1939_PRIORITY_REQUEST; + _msg.Mxe.DestinationAddress = DA; + _msg.Mxe.DataLength = 3; + _msg.Mxe.PDUFormat = J1939_PF_REQUEST; + _msg.Mxe.Data[0] = (j1939_uint8_t) (PGN & 0x000000FF); + _msg.Mxe.Data[1] = (j1939_uint8_t) ((PGN & 0x0000FF00) >> 8); + _msg.Mxe.Data[2] = (j1939_uint8_t) ((PGN & 0x00FF0000) >> 16); + + while (J1939_EnqueueMessage(&_msg, _Can_Node) != RC_SUCCESS); } + /** -* @param[in] data 需要发送数据的缓存 -* @param[in] dataLenght 发送数据的缓存大小 -* @param[in] PGN 需要发送数据的PGN(参数群编号) -* @param[in] void (*dataUPFun)() 用于更新缓存data 的函数地址指针 -* @param[in] _Can_Node 要入队的CAN硬件编号(要选择的使用的CAN硬件编号) -* @note 创建一个PGN 的 请求 对应的 响应\n 如果收到改请求则先运行 REQUEST_LIST.dataUPFun(),在将数据REQUEST_LIST.data发送出去 -* @warning 本函数只能被串行调用,(多线程)并行调用请在函数外加互斥操作 -*/ -void J1939_Create_Response(j1939_uint8_t data[],j1939_uint16_t dataLenght,j1939_uint32_t PGN,void (*dataUPFun)(),CAN_NODE _Can_Node) + * @param[in] data 需要发送数据的缓存 + * @param[in] dataLength 发送数据的缓存大小 + * @param[in] PGN 需要发送数据的PGN(参数群编号) + * @param[in] void (*dataUPFun)() 用于更新缓存data 的函数地址指针 + * @param[in] _Can_Node 要入队的CAN硬件编号(要选择的使用的CAN硬件编号) + * @note 创建一个PGN 的 请求 对应的 响应\n 如果收到改请求则先运行 REQUEST_LIST.dataUPFun(),在将数据REQUEST_LIST.data发送出去 + * @warning 本函数只能被串行调用,(多线程)并行调用请在函数外加互斥操作 + */ +void J1939_Create_Response(j1939_uint8_t data[], j1939_uint16_t dataLength, j1939_uint32_t PGN, void (*dataUPFun)(), + CAN_NODE_t _Can_Node) { - /*查找可用的链表项*/ - struct Request_List * _requestList = &REQUEST_LIST; - while(J1939_NULL != _requestList->next) - { - _requestList = _requestList->next; - } - _requestList->next = (struct Request_List *)malloc(sizeof(struct Request_List)); - _requestList = _requestList->next; - - /*对新的链表项赋值*/ - _requestList->data = data; - _requestList->lenght = dataLenght; - _requestList->PGN = PGN; - _requestList->update = dataUPFun; + /* 查找可用的链表项 */ + struct RequestList *_requestList = &REQUEST_LIST; + + while (J1939_NULL != _requestList->next) { + _requestList = _requestList->next; + } + + _requestList->next = (struct RequestList *) malloc(sizeof(struct RequestList)); + _requestList = _requestList->next; + + /* 对新的链表项赋值 */ + _requestList->data = data; + _requestList->length = dataLength; + _requestList->PGN = PGN; + _requestList->update = dataUPFun; _requestList->Can_Node = _Can_Node; - _requestList->next = J1939_NULL; + _requestList->next = J1939_NULL; } + /** -* @note 当收到一个PGN请求后,如果有REQUEST_LIST中有相应的PGN,则会自动发送REQUEST_LIST中的PGN。\n - 如果没有则会发送一个NACK; 本函数的响应逻辑,参考J1939-21 17页表4 -*/ -void J1939_Response(const j1939_uint32_t PGN) + * @note 当收到一个PGN请求后,如果有REQUEST_LIST中有相应的PGN,则会自动发送REQUEST_LIST中的PGN。\n + 如果没有则会发送一个NACK; 本函数的响应逻辑,参考J1939-21 17页表4 + */ +static void J1939_Response(const j1939_uint32_t PGN) { - J1939_MESSAGE _msg; - - /*查找可用的链表项*/ - struct Request_List * _requestList = &REQUEST_LIST; - while((PGN != _requestList->PGN) || (Can_Node != _requestList->Can_Node)) - { - if(_requestList->next == J1939_NULL) - { - /*原文档规定 全局请求不被支持时不能响应 NACK*/ - if(OneMessage.Mxe.PDUSpecific == J1939_GLOBAL_ADDRESS) - { - return; - } - if((PGN & 0xFF00) >= 0xF000) - { - return; - } - - /*没有相应的PGN响应被创建,向总线发送一个NACK*/ - _msg.Mxe.Priority = J1939_ACK_PRIORITY; - _msg.Mxe.DataPage = 0; - _msg.Mxe.PDUFormat = J1939_PF_ACKNOWLEDGMENT; - _msg.Mxe.DestinationAddress = OneMessage.Mxe.SourceAddress; - _msg.Mxe.DataLength = 8; - _msg.Mxe.SourceAddress = J1939_Address; - _msg.Mxe.Data[0] = J1939_NACK_CONTROL_BYTE; - _msg.Mxe.Data[1] = 0xFF; - _msg.Mxe.Data[2] = 0xFF; - _msg.Mxe.Data[3] = 0xFF; - _msg.Mxe.Data[4] = 0xFF; - _msg.Mxe.Data[5] = (PGN & 0x0000FF); - _msg.Mxe.Data[6] = ((PGN >> 8) & 0x0000FF); - _msg.Mxe.Data[7] = ((PGN >> 16) & 0x0000FF); - - SendOneMessage( (J1939_MESSAGE *) &_msg); - return ; - }else - { - _requestList = _requestList->next; - } - } - - /*调用dataUPFun()函数,主要用于参数群数据更新*/ - if(J1939_NULL != _requestList->update) - { - _requestList->update(); - } - - /*响应请求*/ - if(_requestList->lenght > 8) - { - /*回一个确认响应多帧(非广播多帧)*/ - if(RC_SUCCESS != J1939_TP_TX_Message(_requestList->PGN,OneMessage.Mxe.SourceAddress,_requestList->data,_requestList->lenght,Can_Node)) - { - /*原文档规定 全局请求不被支持时不能响应 NACK*/ - if(OneMessage.Mxe.PDUSpecific == J1939_GLOBAL_ADDRESS) - { - return; - } - - /*如果长帧发送不成功*/ - _msg.Mxe.Priority = J1939_ACK_PRIORITY; - _msg.Mxe.DataPage = 0; - _msg.Mxe.PDUFormat = J1939_PF_ACKNOWLEDGMENT; - _msg.Mxe.DestinationAddress = OneMessage.Mxe.SourceAddress; - _msg.Mxe.DataLength = 8; - _msg.Mxe.SourceAddress = J1939_Address; - _msg.Mxe.Data[0] = J1939_ACCESS_DENIED_CONTROL_BYTE; - _msg.Mxe.Data[1] = 0xFF; - _msg.Mxe.Data[2] = 0xFF; - _msg.Mxe.Data[3] = 0xFF; - _msg.Mxe.Data[4] = 0xFF; - _msg.Mxe.Data[5] = (PGN & 0x0000FF); - _msg.Mxe.Data[6] = ((PGN >> 8) & 0x0000FF); - _msg.Mxe.Data[7] = ((PGN >> 16) & 0x0000FF); - - SendOneMessage( (J1939_MESSAGE *) &_msg); - return ; - } - - /*回一个确认响应*/ - _msg.Mxe.Priority = J1939_ACK_PRIORITY; - _msg.Mxe.DataPage = 0; - _msg.Mxe.PDUFormat = J1939_PF_ACKNOWLEDGMENT; - /*原文档规定 全局请求响应到全局*/ - if(OneMessage.Mxe.PDUSpecific == J1939_GLOBAL_ADDRESS) - { - _msg.Mxe.DestinationAddress = 0XFF; - }else{ - _msg.Mxe.DestinationAddress = OneMessage.Mxe.SourceAddress; - } - _msg.Mxe.DataLength = 8; - _msg.Mxe.SourceAddress = J1939_Address; - _msg.Mxe.Data[0] = J1939_ACK_CONTROL_BYTE; - _msg.Mxe.Data[1] = 0xFF; - _msg.Mxe.Data[2] = 0xFF; - _msg.Mxe.Data[3] = 0xFF; - _msg.Mxe.Data[4] = 0xFF; - _msg.Mxe.Data[5] = (PGN & 0x0000FF); - _msg.Mxe.Data[6] = ((PGN >> 8) & 0x0000FF); - _msg.Mxe.Data[7] = ((PGN >> 16) & 0x0000FF); - SendOneMessage( (J1939_MESSAGE *) &_msg); - }else{ - - /*回一个确认响应*/ - _msg.Mxe.Priority = J1939_ACK_PRIORITY; - _msg.Mxe.DataPage = 0; - _msg.Mxe.PDUFormat = J1939_PF_ACKNOWLEDGMENT; - _msg.Mxe.SourceAddress = J1939_Address; - /*原文档规定 全局请求响应到全局*/ - if((OneMessage.Mxe.PDUSpecific == J1939_GLOBAL_ADDRESS) || ((PGN & 0xFF00) >= 0xF000)) - { - _msg.Mxe.DestinationAddress = 0XFF; - }else{ - _msg.Mxe.DestinationAddress = OneMessage.Mxe.SourceAddress; - } - _msg.Mxe.DataLength = 8; - _msg.Mxe.SourceAddress = J1939_Address; - _msg.Mxe.Data[0] = J1939_ACK_CONTROL_BYTE; - _msg.Mxe.Data[1] = 0xFF; - _msg.Mxe.Data[2] = 0xFF; - _msg.Mxe.Data[3] = 0xFF; - _msg.Mxe.Data[4] = 0xFF; - _msg.Mxe.Data[5] = (PGN & 0x0000FF); - _msg.Mxe.Data[6] = ((PGN >> 8) & 0x0000FF); - _msg.Mxe.Data[7] = ((PGN >> 16) & 0x0000FF); - SendOneMessage( (J1939_MESSAGE *) &_msg); - - /*回一个确认响应单帧*/ - _msg.Mxe.Priority = J1939_ACK_PRIORITY; - _msg.Mxe.DataPage = (((_requestList->PGN)>>16) & 0x1); - _msg.Mxe.PDUFormat = ((_requestList->PGN)>>8) & 0xFF; - _msg.Mxe.SourceAddress = J1939_Address; - /*原文档规定 全局请求响应到全局*/ - if(OneMessage.Mxe.PDUSpecific == J1939_GLOBAL_ADDRESS) - { - _msg.Mxe.DestinationAddress = 0XFF; - }else{ - _msg.Mxe.DestinationAddress = OneMessage.Mxe.SourceAddress; - } - _msg.Mxe.DataLength = _requestList->lenght; - { - j1939_uint8_t _i = 0; - for(_i = 0;_i < (_requestList->lenght);_i++) - { - _msg.Mxe.Data[_i] = _requestList->data[_i]; - } - for(;_i<8;_i++) - { - _msg.Mxe.Data[_i] = 0xFF; - } - } - SendOneMessage( (J1939_MESSAGE *) &_msg); - } + J1939_MESSAGE_t _msg; + + /* 查找可用的链表项 */ + struct RequestList *_requestList = &REQUEST_LIST; + + while ((PGN != _requestList->PGN) || (Can_Node != _requestList->Can_Node)) { + if (_requestList->next == J1939_NULL) { + /* 原文档规定 全局请求不被支持时不能响应 NACK */ + if (OneMessage.Mxe.PDUSpecific == J1939_PS_DA_GLOBAL) { + return; + } + + if ((PGN & 0xFF00) >= 0xF000) { + return; + } + + /* 没有相应的PGN响应被创建,向总线发送一个NACK */ + _msg.Mxe.Priority = J1939_PRIORITY_ACK; + _msg.Mxe.DataPage = 0; + _msg.Mxe.PDUFormat = J1939_PF_ACKNOWLEDGMENT; + _msg.Mxe.DestinationAddress = OneMessage.Mxe.SourceAddress; + _msg.Mxe.DataLength = 8; + _msg.Mxe.SourceAddress = J1939_Address; + _msg.Mxe.Data[0] = J1939_CONTROL_BYTE_NACK; + _msg.Mxe.Data[1] = 0xFF; + _msg.Mxe.Data[2] = 0xFF; + _msg.Mxe.Data[3] = 0xFF; + _msg.Mxe.Data[4] = 0xFF; + _msg.Mxe.Data[5] = (PGN & 0x0000FF); + _msg.Mxe.Data[6] = ((PGN >> 8) & 0x0000FF); + _msg.Mxe.Data[7] = ((PGN >> 16) & 0x0000FF); + + SendOneMessage((J1939_MESSAGE_t *) &_msg); + return; + } else { + _requestList = _requestList->next; + } + } + + /* 调用dataUPFun()函数,主要用于参数群数据更新 */ + if (J1939_NULL != _requestList->update) { + _requestList->update(); + } + + /* 响应请求 */ + if (_requestList->length > 8) { + /* 回一个确认响应多帧(非广播多帧) */ + if (RC_SUCCESS + != J1939_TP_TX_Message(_requestList->PGN, OneMessage.Mxe.SourceAddress, _requestList->data, + _requestList->length, Can_Node)) { + /* 原文档规定 全局请求不被支持时不能响应 NACK */ + if (OneMessage.Mxe.PDUSpecific == J1939_PS_DA_GLOBAL) { + return; + } + + /* 如果长帧发送不成功 */ + _msg.Mxe.Priority = J1939_PRIORITY_ACK; + _msg.Mxe.DataPage = 0; + _msg.Mxe.PDUFormat = J1939_PF_ACKNOWLEDGMENT; + _msg.Mxe.DestinationAddress = OneMessage.Mxe.SourceAddress; + _msg.Mxe.DataLength = 8; + _msg.Mxe.SourceAddress = J1939_Address; + _msg.Mxe.Data[0] = J1939_CONTROL_BYTE_ACCESS_DENIED; + _msg.Mxe.Data[1] = 0xFF; + _msg.Mxe.Data[2] = 0xFF; + _msg.Mxe.Data[3] = 0xFF; + _msg.Mxe.Data[4] = 0xFF; + _msg.Mxe.Data[5] = (PGN & 0x0000FF); + _msg.Mxe.Data[6] = ((PGN >> 8) & 0x0000FF); + _msg.Mxe.Data[7] = ((PGN >> 16) & 0x0000FF); + + SendOneMessage((J1939_MESSAGE_t *) &_msg); + return; + } + + /* 回一个确认响应 */ + _msg.Mxe.Priority = J1939_PRIORITY_ACK; + _msg.Mxe.DataPage = 0; + _msg.Mxe.PDUFormat = J1939_PF_ACKNOWLEDGMENT; + + /* 原文档规定 全局请求响应到全局 */ + if (OneMessage.Mxe.PDUSpecific == J1939_PS_DA_GLOBAL) { + _msg.Mxe.DestinationAddress = 0XFF; + } else { + _msg.Mxe.DestinationAddress = OneMessage.Mxe.SourceAddress; + } + + _msg.Mxe.DataLength = 8; + _msg.Mxe.SourceAddress = J1939_Address; + _msg.Mxe.Data[0] = J1939_CONTROL_BYTE_ACK; + _msg.Mxe.Data[1] = 0xFF; + _msg.Mxe.Data[2] = 0xFF; + _msg.Mxe.Data[3] = 0xFF; + _msg.Mxe.Data[4] = 0xFF; + _msg.Mxe.Data[5] = (PGN & 0x0000FF); + _msg.Mxe.Data[6] = ((PGN >> 8) & 0x0000FF); + _msg.Mxe.Data[7] = ((PGN >> 16) & 0x0000FF); + SendOneMessage((J1939_MESSAGE_t *) &_msg); + } else { + + /* 回一个确认响应 */ + _msg.Mxe.Priority = J1939_PRIORITY_ACK; + _msg.Mxe.DataPage = 0; + _msg.Mxe.PDUFormat = J1939_PF_ACKNOWLEDGMENT; + _msg.Mxe.SourceAddress = J1939_Address; + + /* 原文档规定 全局请求响应到全局 */ + if ((OneMessage.Mxe.PDUSpecific == J1939_PS_DA_GLOBAL) || ((PGN & 0xFF00) >= 0xF000)) { + _msg.Mxe.DestinationAddress = 0XFF; + } else { + _msg.Mxe.DestinationAddress = OneMessage.Mxe.SourceAddress; + } + + _msg.Mxe.DataLength = 8; + _msg.Mxe.SourceAddress = J1939_Address; + _msg.Mxe.Data[0] = J1939_CONTROL_BYTE_ACK; + _msg.Mxe.Data[1] = 0xFF; + _msg.Mxe.Data[2] = 0xFF; + _msg.Mxe.Data[3] = 0xFF; + _msg.Mxe.Data[4] = 0xFF; + _msg.Mxe.Data[5] = (PGN & 0x0000FF); + _msg.Mxe.Data[6] = ((PGN >> 8) & 0x0000FF); + _msg.Mxe.Data[7] = ((PGN >> 16) & 0x0000FF); + SendOneMessage((J1939_MESSAGE_t *) &_msg); + + /* 回一个确认响应单帧 */ + _msg.Mxe.Priority = J1939_PRIORITY_ACK; + _msg.Mxe.DataPage = (((_requestList->PGN) >> 16) & 0x1); + _msg.Mxe.PDUFormat = ((_requestList->PGN) >> 8) & 0xFF; + _msg.Mxe.SourceAddress = J1939_Address; + + /* 原文档规定 全局请求响应到全局 */ + if (OneMessage.Mxe.PDUSpecific == J1939_PS_DA_GLOBAL) { + _msg.Mxe.DestinationAddress = 0XFF; + } else { + _msg.Mxe.DestinationAddress = OneMessage.Mxe.SourceAddress; + } + + _msg.Mxe.DataLength = _requestList->length; + { + j1939_uint8_t _i = 0; + + for (_i = 0; _i < (_requestList->length); _i++) { + _msg.Mxe.Data[_i] = _requestList->data[_i]; + } + + for (; _i < 8; _i++) { + _msg.Mxe.Data[_i] = 0xFF; + } + } + SendOneMessage((J1939_MESSAGE_t *) &_msg); + } } #endif diff --git a/source/J1939_Config.H b/source/J1939_Config.H index 69eb51e..744734e 100644 --- a/source/J1939_Config.H +++ b/source/J1939_Config.H @@ -1,322 +1,59 @@ -/********************************************************************* - * - * J1939 Main Source Code - * - ********************************************************************* - * - * 本程序是由XieTongXueFlyMe对现有的J1939协议文档分析,和对前辈的贡献总结, - * 写出的一套开源的J1939驱动。 - * 本协议特点: - * 1.易移植(不针对特定的CAN硬件,只要满足CAN2.0B即可) - * 2.轻量级(可适应低端的MCU) - * 3.支持多任务调用接口(可用于嵌入式系统) - * 4.双模式(轮询或者中断,逻辑更加简单明了) - * 5.不掉帧(数据采用收发列队缓存) - * - * 源代码下载: - * https://github.com/XeiTongXueFlyMe/J1939 - * 源代码临时手册Web站点: - * https://xeitongxueflyme.github.io/j1939doc.github.io/ - * - * Version Date Description - * ------------------------------------------------------------------- - * v1.0.0 2017/06/04 首个版本 Version 1 测试版发布 - * v1.0.1 2017/08/04 完善功能 - * v1.1.0 2017/11/22 Version 1 稳定发布版 - * v2.0.1 2017/11/24 Version 2 测试版发布 - * v2.0.2 2018/01/03 解决V2.0.1 遗留问题 - * v2.1.0 2018/01/20 Version 2 稳定发布版 - * Author Date changes - *~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - *XeiTongXueFlyMe 7/06/04 首个版本 - *XeiTongXueFlyMe 7/08/04 增加对TP的支持 - *XeiTongXueFlyMe 7/11/24 增加对多路CAN硬件的收发,和报文处理 - *XeiTongXueFlyMe 7/11/29 增加请求和响应API - *XeiTongXueFlyMe 7/12/07 重做TP接受API函数 - *XeiTongXueFlyMe 7/12/08 增加软件滤波器 - *XeiTongXueFlyMe 8/01/03 重做接受发送API,简化协议栈初始化调用逻辑 - **********************************************************************/ +#ifndef __J1939_Config_H +#define __J1939_Config_H -#ifndef __J1939_Config_H -#define __J1939_Config_H +#include "J1939.h" -#include "J1939.H" -extern CAN_NODE Can_Node; //CAN硬件选择 +/******************************J1939功能配置******************************/ +#define J1939_NODE_NUM 4 -/***************************J1939 地址配置*****************************/ -//设备默认的地址(地址命名是有规定的,参考J1939的附录B 地址和标识符的分配) -#define J1939_STARTING_ADDRESS_1 0x01 -#define J1939_STARTING_ADDRESS_2 244 -#define J1939_STARTING_ADDRESS_3 247 -#define J1939_STARTING_ADDRESS_4 0 +#define J1939_RX_QUEUE_SIZE 3 +/* 当MCU来不及处理消息,接收消息队列是否允许被新的消息覆盖 */ +#define J1939_OVERWRITE_RX_QUEUE J1939_FALSE +#define J1939_TX_QUEUE_SIZE 3 +/* 当MCU来不及处理消息,发送消息队列是否允许被新的消息覆盖 */ +#define J1939_OVERWRITE_TX_QUEUE J1939_FALSE -/******************************J1939功能配置***************************/ -#define J1939_RX_QUEUE_SIZE 3 -//当mcu来不及处理消息,接收消息列队是否允许被新的消息覆盖 -#define J1939_OVERWRITE_RX_QUEUE J1939_FALSE -#define J1939_TX_QUEUE_SIZE 3 -//当mcu来不及处理消息,发送消息列队是否允许被新的消息覆盖 -#define J1939_OVERWRITE_TX_QUEUE J1939_FALSE -//是否使用轮询模式(否则使用中断模式) -#define J1939_POLL_ECAN J1939_TRUE -//是否启用软件滤波器 -#define J1939SoftwareFilterEn J1939_TRUE -/******************************J1939移植配置函数************************/ +/* 是否使用轮询模式(否则使用中断模式) */ +#define J1939_POLL_ECAN J1939_TRUE +/* 是否启用软件滤波器 */ +#define J1939SoftwareFilterEn J1939_TRUE -#define Port_CAN_Transmit(MsgPtr) J1939_CAN_Transmit(MsgPtr) -#define Port_CAN_Receive(MsgPtr) J1939_CAN_Receive(MsgPtr) -#define Port_SetAddressFilter(Address) J1939_SetAddressFilter(Address) -/*不使用中断模式,不对下面的函数进行移植*/ -#if J1939_POLL_ECAN == J1939_FALSE - #define Port_RXinterruptEnable() J1939_RXinterruptEnable() - #define Port_RXinterruptDisable() J1939_RXinterruptDisable() - #define Port_TXinterruptEnable() J1939_TXinterruptEnable() - #define Port_TXinterruptDisable() J1939_TXinterruptDisable() - #define Port_TXinterruptOk() J1939_TXinterruptOk() - #define Port_CAN_identifier_clc() CAN_identifier_clc() -#endif - -/***************************************************************************************/ - -/* -*输入: -*输出: -*说明:基于SAE J1939协议,我们需要CAN控制器提供至少3个滤波器给J1939协议代码。三个滤波器分别配置如下: - 1. 设置滤波器0,只接受广播信息(PF = 240 -255)。 - 2. 设置设置滤波器1,2只接受全局地址(J1939_GLOBAL_ADDRESS) - 3. 随着程序的运行,将改变滤波器2,来适应程序逻辑。 - J1939_SetAddressFilter() 是用来设置滤波器2的, 函数主要设置PS位(目标地址),其目的是,让控制器 - 只接受发送给本设备的消息。 -*警告: 滤波器0,1是在CAN驱动里配置,如果对硬件滤波配置不是很熟练,可以使能软件滤波器,#define J1939SoftwareFilterEn -*则可跳过本函数的移植和CAN硬件滤波器的配置,为了J1939协议栈性能最优化,建议只是用硬件滤波。 -*/ -void J1939_SetAddressFilter(unsigned char Ps_Address) -{ - switch (Can_Node) - { - case Select_CAN_NODE_1: - { - break; - } - case Select_CAN_NODE_2: - { - break; - } - case Select_CAN_NODE_3: - { - break; - } - case Select_CAN_NODE_4: - { - break; - } - default : - { - break; - } - } -} - -/* -*输入: *MsgPtr ,协议要发送的消息, -*输出: -*说明: 将数据 从MsgPtr结构体赋值到CAN驱动自带的结构体中 - 先将传入函数的MsgPtr中的数据写到CAN的结构体,再调用CAN驱动的发送函数 - 默认支持4路CAN硬件的收发。如少于4路,只需配置相应的Can_Node开关代码区, - 其他(Select_CAN_NODE)保持不变。就直接返回(break)。 -*/ -void J1939_CAN_Transmit(J1939_MESSAGE *MsgPtr) -{ - - switch (Can_Node) - { - case Select_CAN_NODE_1: - { - - /*加载第一路CAN硬件的29位ID*/ - - /*CAN硬件加载数据长度*/ - - /*CAN硬件加载数据*/ - - /*CAN硬件加载RTR*/ - - //CAN硬件开始发送数据 - - break; - } - case Select_CAN_NODE_2: - { - - /*加载第二路CAN硬件的29位ID*/ - - /*CAN硬件加载数据长度*/ - - /*CAN硬件加载数据*/ - - /*CAN硬件加载RTR*/ +extern CAN_NODE_t Can_Node; /* CAN硬件选择 */ +extern const j1939_uint8_t J1939_STARTING_ADDRESS[J1939_NODE_NUM]; - //CAN硬件开始发送数据 - break; - } - case Select_CAN_NODE_3: - { - - /*加载第三路CAN硬件的29位ID*/ +/******************************J1939移植配置函数******************************/ - /*CAN硬件加载数据长度*/ - - /*CAN硬件加载数据*/ +void J1939_SetAddressFilter(j1939_uint8_t Ps_Address); +void J1939_CAN_Transmit(J1939_MESSAGE_t *MsgPtr); +int J1939_CAN_Receive(J1939_MESSAGE_t *MsgPtr); - /*CAN硬件加载RTR*/ +#define Port_CAN_Transmit(MsgPtr) J1939_CAN_Transmit(MsgPtr) +#define Port_CAN_Receive(MsgPtr) J1939_CAN_Receive(MsgPtr) +#define Port_SetAddressFilter(Address) J1939_SetAddressFilter(Address) - //CAN硬件开始发送数据 - break; - } - case Select_CAN_NODE_4: - { - /*加载第四路CAN硬件的29位ID*/ - - /*CAN硬件加载数据长度*/ - - /*CAN硬件加载数据*/ - - /*CAN硬件加载RTR*/ - - //CAN硬件开始发送数据 - break; - } - default : - { - break; - } - } -} -/* -*输入: *MsgPtr 数据要存入的内存的指针 -*输出: 1 | 0 -*说明: 读取CAN驱动的数据,如果没有数据,返回0 - 将CAN中的数据取出,存入J1939_MESSAGE结构体中 - 默认支持4路CAN硬件的收发。如少于4路,只需配置相应的Can_Node开关代码区, - 其他(Select_CAN_NODE)保持不变。就直接返回(return 0) -*/ - -int J1939_CAN_Receive(J1939_MESSAGE *MsgPtr) -{ - - switch (Can_Node) - { - case Select_CAN_NODE_1: - { - if("你的代码")//判断CAN硬件1是否有数据到来 - { - //你的代码,从CAN硬件1 中将数据读取后,存入 MsgPtr - return 1; - } - return 0; - break; - } - case Select_CAN_NODE_2: - { - if("你的代码")//判断CAN硬件2是否有数据到来 - { - //你的代码,从CAN硬件2 中将数据读取后,存入 MsgPtr - return 1; - } - return 0; - break; - - } - case Select_CAN_NODE_3: - { - if("你的代码")//判断CAN硬件3是否有数据到来 - { - //你的代码,从CAN硬件3 中将数据读取后,存入 MsgPtr - return 1; - } - return 0; - break; - - } - case Select_CAN_NODE_4: - { - if("你的代码")//判断CAN硬件4是否有数据到来 - { - //你的代码,从CAN硬件4 中将数据读取后,存入 MsgPtr - return 1; - } - return 0; - break; - } - default : - { - return 0;//没有消息 - break; - } - } - return 0;//没有消息 -} - -/*不使用中断模式,不对下面的函数进行移植*/ +/* 不使用中断模式,不对下面的函数进行移植 */ #if J1939_POLL_ECAN == J1939_FALSE -/* -*输入: -*输出: -*说明:使能接受中断 -*/ - void J1939_RXinterruptEnable() - { - ; - } -/* -*输入: -*输出: -*说明:失能接受中断 -*/ - void J1939_RXinterruptDisable() - { - ; - } -/* -*输入: -*输出: -*说明:使能发送中断 -*/ - void J1939_TXinterruptEnable() - { - ; - } -/* -*输入: -*输出: -*说明:失能发送中断 -*/ - void J1939_TXinterruptDisable() - { - ; - } -/* -*输入: -*输出: -*说明:触发发送中断标致位,当协议栈在中断模式下,要发送消息,将调用此函数 - CAN驱动函数,就将直接把消息发送出去,不需要协议在调用任何can驱动函数 -*/ - void J1939_TXinterruptOk() - { - ; - } -/* -*输入: -*输出: -*说明:清除CAN驱动相关的中断产生标识位,包括(发送中断标志位,接受中断标 - 志位,can总线错误标识位) -*/ - void CAN_identifier_clc() - { - ; - } -#endif - -#endif +void J1939_RXinterruptEnable(); +void J1939_RXinterruptDisable(); +void J1939_TXinterruptEnable(); +void J1939_TXinterruptDisable(); +void J1939_TXinterruptOk(); +void CAN_identifier_clc(); +#define Port_RXinterruptEnable() J1939_RXinterruptEnable() +#define Port_RXinterruptDisable() J1939_RXinterruptDisable() +#define Port_TXinterruptEnable() J1939_TXinterruptEnable() +#define Port_TXinterruptDisable() J1939_TXinterruptDisable() +#define Port_TXinterruptOk() J1939_TXinterruptOk() +#define Port_CAN_identifier_clc() CAN_identifier_clc() +#else +#define Port_RXinterruptEnable() +#define Port_RXinterruptDisable() +#define Port_TXinterruptEnable() +#define Port_TXinterruptDisable() +#define Port_TXinterruptOk() +#define Port_CAN_identifier_clc() +#endif /* #if J1939_POLL_ECAN == J1939_FALSE */ + +#endif /* #ifndef __J1939_Config_H */ diff --git a/source/J1939_Config.c b/source/J1939_Config.c new file mode 100644 index 0000000..2edf510 --- /dev/null +++ b/source/J1939_Config.c @@ -0,0 +1,228 @@ +#include "J1939_Config.h" + +/******************************J1939 地址配置******************************/ + +/* 设备默认的地址(地址命名是有规定的,参考J1939的附录B 地址和标识符的分配) */ +const j1939_uint8_t J1939_STARTING_ADDRESS[J1939_NODE_NUM] = { + [Select_CAN_NODE_1] = 0x01, + [Select_CAN_NODE_2] = 244, + [Select_CAN_NODE_3] = 247, + [Select_CAN_NODE_4] = 0, +}; + +/* + * 输入: + * 输出: + * 说明:基于SAE J1939协议,我们需要CAN控制器提供至少3个滤波器给J1939协议代码。三个滤波器分别配置如下: + 1. 设置滤波器0,只接受广播信息(PF = 240 -255)。 + 2. 设置滤波器1,2只接受全局地址(J1939_GLOBAL_ADDRESS) + 3. 随着程序的运行,将改变滤波器2,来适应程序逻辑。 + J1939_SetAddressFilter() 是用来设置滤波器2的, 函数主要设置PS位(目标地址),其目的是,让控制器 + 只接受发送给本设备的消息。 + * 警告: 滤波器0,1是在CAN驱动里配置,如果对硬件滤波配置不是很熟练,可以使能软件滤波器,#define J1939SoftwareFilterEn + * 则可跳过本函数的移植和CAN硬件滤波器的配置,为了J1939协议栈性能最优化,建议只是用硬件滤波。 + */ +void J1939_SetAddressFilter(j1939_uint8_t Ps_Address) +{ + switch (Can_Node) { + case Select_CAN_NODE_1: { + break; + } + + case Select_CAN_NODE_2: { + break; + } + + case Select_CAN_NODE_3: { + break; + } + + case Select_CAN_NODE_4: { + break; + } + + default: { + break; + } + } +} + +/* + * 输入: *MsgPtr,协议要发送的消息, + * 输出: + * 说明: 将数据 从MsgPtr结构体赋值到CAN驱动自带的结构体中 + 先将传入函数的MsgPtr中的数据写到CAN的结构体,再调用CAN驱动的发送函数 + 默认支持4路CAN硬件的收发。如少于4路,只需配置相应的Can_Node开关代码区, + 其他(Select_CAN_NODE)保持不变。就直接返回(break)。 + */ +void J1939_CAN_Transmit(J1939_MESSAGE_t *MsgPtr) +{ + switch (Can_Node) { + case Select_CAN_NODE_1: { + /* 加载第一路CAN硬件的29位ID */ + + /* CAN硬件加载数据长度 */ + + /* CAN硬件加载数据 */ + + /* CAN硬件加载RTR */ + + /* CAN硬件开始发送数据 */ + + break; + } + + case Select_CAN_NODE_2: { + /* 加载第二路CAN硬件的29位ID */ + + /* CAN硬件加载数据长度 */ + + /* CAN硬件加载数据 */ + + /* CAN硬件加载RTR */ + + /* CAN硬件开始发送数据 */ + + break; + } + + case Select_CAN_NODE_3: { + /* 加载第三路CAN硬件的29位ID */ + + /* CAN硬件加载数据长度 */ + + /* CAN硬件加载数据 */ + + /* CAN硬件加载RTR */ + + /* CAN硬件开始发送数据 */ + + break; + } + + case Select_CAN_NODE_4: { + /* 加载第四路CAN硬件的29位ID */ + + /* CAN硬件加载数据长度 */ + + /* CAN硬件加载数据 */ + + /* CAN硬件加载RTR */ + + /* CAN硬件开始发送数据 */ + + break; + } + + default: { + break; + } + } +} + +/* + * 输入:*MsgPtr 数据要存入的内存的指针 + * 输出: 1 | 0 + * 说明: 读取CAN驱动的数据,如果没有数据,返回0 + 将CAN中的数据取出,存入J1939_MESSAGE结构体中 + 默认支持4路CAN硬件的收发。如少于4路,只需配置相应的Can_Node开关代码区, + 其他(Select_CAN_NODE)保持不变。就直接返回(return 0) + */ +int J1939_CAN_Receive(J1939_MESSAGE_t *MsgPtr) +{ + switch (Can_Node) { + case Select_CAN_NODE_1: { + if ("你的代码") + { + /* 你的代码,从CAN硬件1 中将数据读取后,存入 MsgPtr */ + return 1; + } + + return 0; + break; + } + + case Select_CAN_NODE_2: { + break; + } + + case Select_CAN_NODE_3: { + break; + } + + case Select_CAN_NODE_4: { + break; + } + + default: { + return 0; /* 没有消息 */ + break; + } + } + + return 0; /* 没有消息 */ +} + +/*不使用中断模式,不对下面的函数进行移植*/ +#if J1939_POLL_ECAN == J1939_FALSE +/* + * 输入: + * 输出: + * 说明:使能接受中断 + */ +void J1939_RXinterruptEnable() +{ + ; +} + +/* + * 输入: + * 输出: + * 说明:失能接受中断 + */ +void J1939_RXinterruptDisable() +{ + ; +} + +/* + * 输入: + * 输出: + * 说明:使能发送中断 + */ +void J1939_TXinterruptEnable() +{ + ; +} + +/* + * 输入: + * 输出: + * 说明:失能发送中断 + */ +void J1939_TXinterruptDisable() +{ + ; +} + +/* + * 输入: + * 输出: + * 说明:触发发送中断标致位,当协议栈在中断模式下,要发送消息,将调用此函数, + CAN驱动函数,就将直接把消息发送出去,不需要协议在调用任何can驱动函数 + */ +void J1939_TXinterruptOk() +{ + ; +} + +/* + * 输入: + * 输出: + * 说明:清除CAN驱动相关的中断产生标识位,包括(发送中断标志位,接受中断标志位,can总线错误标识位) + */ +void CAN_identifier_clc() +{ + ; +} +#endif