123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331 |
- /*********************************************************************
- *
- * 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
- #include "J1939.H"
- #include "queue.h"
- #include <stdint.h>
- #include <string.h>
- extern uint8_t push_can_message_to_queue(uint32_t id, uint8_t len, uint8_t *p_data);
- extern CAN_NODE Can_Node; // CAN硬件选择
- /***************************J1939 地址配置*****************************/
- // 设备默认的地址(地址命名是有规定的,参考J1939的附录B 地址和标识符的分配)
- #define J1939_STARTING_ADDRESS_1 0xF4
- #define J1939_STARTING_ADDRESS_2 244
- #define J1939_STARTING_ADDRESS_3 247
- #define J1939_STARTING_ADDRESS_4 0
- /******************************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 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)
- {
- pdu_tag j1939_tx_data;
- switch (Can_Node)
- {
- case Select_CAN_NODE_1:
- {
- j1939_tx_data.id.b.sa = MsgPtr->Mxe.SourceAddress;
- j1939_tx_data.id.b.ps = MsgPtr->Mxe.PDUSpecific;
- j1939_tx_data.id.b.pf = MsgPtr->Mxe.PDUFormat;
- j1939_tx_data.id.b.dp = 0; // MsgPtr->Mxe.DataPage;
- j1939_tx_data.id.b.r = 0; // MsgPtr->Mxe.Res;
- j1939_tx_data.id.b.p = MsgPtr->Mxe.Priority;
- j1939_tx_data.reg.dlc = MsgPtr->Mxe.DataLength;
- memcpy(j1939_tx_data.data.u8_buf, MsgPtr->Mxe.Data, MsgPtr->Mxe.DataLength);
- push_can_message_to_queue(j1939_tx_data.id.r, j1939_tx_data.reg.dlc, j1939_tx_data.data.u8_buf);
- 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)
- */
- queue_entry(J1939_MESSAGE, 10) j1939_rx_queue;
- int J1939_CAN_Receive(J1939_MESSAGE *MsgPtr)
- {
- j1939_uint8_t rec = RC_SUCCESS;
- QUEUE_STATUS status;
- switch (Can_Node)
- {
- case Select_CAN_NODE_1:
- {
- de_queue(&j1939_rx_queue, (*MsgPtr), status);
- if (status == Q_EMPTY)
- {
- return 0;
- }
- return 1;
- 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
|