SAE J1939 协议源代码分析(二)-程序移植
来源:互联网 发布:淘宝店铺行业排名下跌 编辑:程序博客网 时间:2024/06/05 07:21
预备知识
1.熟悉CAN2.0B协议,及相关硬件驱动开发2.熟悉SAE J1939协议<http://blog.csdn.net/xietongxueflyme/article/details/74276702/>
程序移植流程
备注:ECU板子必须是支持CAN2.0B。如果移植设备需要处理高并发数据流,建议使用中断模式,例如J1939网络管理器,行车控制器。发动机控制器等。其他应用皆可以用轮询。轮询完全可以满足毫秒级别的响应速度。
备注:特殊情况,如果不用TP功能,关闭此功能的申明在J1939.H,这是配置唯一不再J1939config.h中的配置。默认TP协议时开启的。
移植示例(demo)
以下示例,对德国英飞凌XMC4500(MCU)芯片自带的CAN模块上移植J1939协议源代码,代码中can驱动函数,can的驱动结构体,可供移植参考
#ifndef __J1939_Config_H #define __J1939_Config_H #include "J1939.H"#include "../UserApp/includes.h"//用户,自己工程必要的声明头文件/******************************J1939地址和标识符配*********************************///设备默认的地址(地址命名是有规定的,参考J1939的附录B 地址和标识符的分配)#define J1939_STARTING_ADDRESS 243//如果声明不为0,表示我们的ECU(电子控制单元)支持网络中申请的任意地址,(参考J1939的网络层)#define J1939_ARBITRARY_ADDRESS 0x00#define J1939_INDUSTRY_GROUP 0#define J1939_VEHICLE_INSTANCE 0#define J1939_CA_NAME7 (J1939_ARBITRARY_ADDRESS | (J1939_INDUSTRY_GROUP << 4) | J1939_VEHICLE_INSTANCE)#define J1939_VEHICLE_SYSTEM 0#define J1939_CA_NAME6 (J1939_VEHICLE_SYSTEM << 1)#define J1939_FUNCTION 0#define J1939_CA_NAME5 J1939_FUNCTION#define J1939_FUNCTION_INSTANCE 0#define J1939_ECU_INSTANCE 0#define J1939_CA_NAME4 ((J1939_FUNCTION_INSTANCE << 3) | J1939_ECU_INSTANCE)#define J1939_MANUFACTURER_CODE 0#define J1939_IDENTITY_NUMBER 50#define J1939_CA_NAME3 (J1939_MANUFACTURER_CODE >> 3)#define J1939_CA_NAME2 (((J1939_MANUFACTURER_CODE & 0x07) << 5) | (J1939_IDENTITY_NUMBER >> 16))#define J1939_CA_NAME1 ((J1939_IDENTITY_NUMBER >> 8) & 0xFF)#define J1939_CA_NAME0 (J1939_IDENTITY_NUMBER & 0xFF)/******************************J1939功能配置******************************************///是否使用接受协议(对TP协议的支持,参考J1939-21)#define J1939_ACCEPT_CMDADD J1939_FALSE#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 J1939_PRIORITIZED_INT 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)#define Port_RXinterruptEnable() J1939_RXinterruptEnable() #define Port_RXinterruptDisable() J1939_RXinterruptDisable() #define Port_TXinterruptEnable() J1939_TXinterruptEnable() #define Port_TXinterruptDisable() J1939_TXinterruptDisable() /******************************J1939与CAN驱动接口函数************************************/void J1939_SetAddressFilter(unsigned char Ps_Address){ CAN_NODE3_DEBUG.lmobj_ptr[0]->mo_ptr->can_id_mask &=0XFFFF00FF; CAN_NODE3_DEBUG.lmobj_ptr[0]->mo_ptr->can_id_mask |= (Ps_Address<<8); CAN_NODE_MO_Init(CAN_NODE3_DEBUG.lmobj_ptr[0]);}void ChangeGroupIDofLMO(const CAN_NODE_LMO_t *lmo_ptr,J1939_MESSAGE *MsgPtr){ int _i=0; lmo_ptr->mo_ptr->can_identifier = 0; for(_i=0;_i<4;_i++) { lmo_ptr->mo_ptr->can_identifier = (lmo_ptr->mo_ptr->can_identifier << 8) + MsgPtr->Array[_i]; } // 在线修改lmo配置 CAN_NODE_MO_Init(lmo_ptr);}/*从MsgPtr加载到CAN自带的结构体中*/void J1939_CAN_Transmit(J1939_MESSAGE *MsgPtr){ CAN_NODE_LMO_t *lmo_ptr = CAN_NODE3_DEBUG.lmobj_ptr[1]; /*加载29位ID*/ ChangeGroupIDofLMO((const CAN_NODE_LMO_t * const)(CAN_NODE3_DEBUG.lmobj_ptr[1]),MsgPtr); /*加载数据长度*/ lmo_ptr->mo_ptr->can_data_length = MsgPtr->Mxe.DataLength; CAN_NODE_MO_Init(lmo_ptr); /*加载数据*/ lmo_ptr->mo_ptr->can_data_byte[0] = MsgPtr->Mxe.Data[0]; lmo_ptr->mo_ptr->can_data_byte[1] = MsgPtr->Mxe.Data[1]; lmo_ptr->mo_ptr->can_data_byte[2] = MsgPtr->Mxe.Data[2]; lmo_ptr->mo_ptr->can_data_byte[3] = MsgPtr->Mxe.Data[3]; lmo_ptr->mo_ptr->can_data_byte[4] = MsgPtr->Mxe.Data[4]; lmo_ptr->mo_ptr->can_data_byte[5] = MsgPtr->Mxe.Data[5]; lmo_ptr->mo_ptr->can_data_byte[6] = MsgPtr->Mxe.Data[6]; lmo_ptr->mo_ptr->can_data_byte[7] = MsgPtr->Mxe.Data[7]; /*加载RTR*/ //你的代码 //开始发送数据 (CAN_NODE_STATUS_t) CAN_NODE_MO_Transmit(lmo_ptr) ;}//将设备CAN中的数据取出,存入J1939_MESSAGE结构体中int J1939_CAN_Receive(J1939_MESSAGE *MsgPtr){ uint32_t receive_status=0; uint32_t _id=0; receive_status = CAN_NODE_MO_GetStatus( ((CAN_NODE_t *)&CAN_NODE3_DEBUG)->lmobj_ptr[0]); if ( receive_status & XMC_CAN_MO_STATUS_RX_PENDING) //XMC_CAN_MO_STATUS_NEW_DATA { // 清除接受标识位 CAN_NODE_MO_ClearStatus(((CAN_NODE_t *)&CAN_NODE3_DEBUG)->lmobj_ptr[0],XMC_CAN_MO_RESET_STATUS_RX_PENDING); // 读取数据 CAN_NODE_MO_Receive( ((CAN_NODE_t *)&CAN_NODE3_DEBUG)->lmobj_ptr[0]); //将29位标志位(can_identifier)写入J1939的结构中 _id = ((CAN_NODE_t *)&CAN_NODE3_DEBUG)->lmobj_ptr[0]->mo_ptr->can_identifier; MsgPtr->Array[0] = _id>>(8*3); MsgPtr->Array[1] = _id>>(8*2); MsgPtr->Array[2] = _id>>(8*1); MsgPtr->Array[3] = _id>>(8*0); //读取数据长度 MsgPtr->Mxe.DataLength = ((CAN_NODE_t *)&CAN_NODE3_DEBUG)->lmobj_ptr[0]->mo_ptr->can_data_length; if (MsgPtr->Mxe.DataLength > 8) MsgPtr->Mxe.DataLength = 8; //读取数据 MsgPtr->Mxe.Data[0] = ((CAN_NODE_t *)&CAN_NODE3_DEBUG)->lmobj_ptr[0]->mo_ptr->can_data_byte[0]; MsgPtr->Mxe.Data[1] = ((CAN_NODE_t *)&CAN_NODE3_DEBUG)->lmobj_ptr[0]->mo_ptr->can_data_byte[1]; MsgPtr->Mxe.Data[2] = ((CAN_NODE_t *)&CAN_NODE3_DEBUG)->lmobj_ptr[0]->mo_ptr->can_data_byte[2]; MsgPtr->Mxe.Data[3] = ((CAN_NODE_t *)&CAN_NODE3_DEBUG)->lmobj_ptr[0]->mo_ptr->can_data_byte[3]; MsgPtr->Mxe.Data[4] = ((CAN_NODE_t *)&CAN_NODE3_DEBUG)->lmobj_ptr[0]->mo_ptr->can_data_byte[4]; MsgPtr->Mxe.Data[5] = ((CAN_NODE_t *)&CAN_NODE3_DEBUG)->lmobj_ptr[0]->mo_ptr->can_data_byte[5]; MsgPtr->Mxe.Data[6] = ((CAN_NODE_t *)&CAN_NODE3_DEBUG)->lmobj_ptr[0]->mo_ptr->can_data_byte[6]; MsgPtr->Mxe.Data[7] = ((CAN_NODE_t *)&CAN_NODE3_DEBUG)->lmobj_ptr[0]->mo_ptr->can_data_byte[7]; return 1; }else { return 0;//没有消息 }}void J1939_RXinterruptEnable(){ ;}void J1939_RXinterruptDisable(){ ;}void J1939_TXinterruptEnable(){ ;}void J1939_TXinterruptDisable(){ ;}#endif
选着性的移植函数
如果不要此功能,可以不用编写下面的移植函数
//设备默认的地址(地址命名是有规定的,参考J1939的附录B 地址和标识符的分配)#define J1939_STARTING_ADDRESS 243 //这里填写你设备默认的地址//如果声明不为0,表示我们的ECU(电子控制单元)支持网络中申请的任意地址,(参考J1939的网络层)#define J1939_ARBITRARY_ADDRESS 0x00/**输入:需要改变地址的地址的指针,*输出: *说明:地址竞争重新估算,设备在总线上要重新申请的地址。 设备是固定地址的,不需要移植此函数。 函数为各个厂家想申请的地址,如果默认地址没有申请成功 则调用此函数,重新申请一个希望得到的地址,当然可能再一次 申请不成功,所以函数可以返回多个不同的地址,一次返回一个*/BOOL ECU_RecalculateAddress( unsigned char * Address){ return 0;//没有生成新的地址,返回0}
备注
J1939与CAN2.0B驱动接口函数在后面,将逐一的分析。
阅读全文
5 0
- SAE J1939 协议源代码分析(二)-程序移植
- SAE J1939 协议源代码分析(三)-程序应用分析
- SAE J1939 协议源代码分析(零)-源代码下载
- SAE J1939 协议源代码分析(一)-程序结构框架
- SAE J1939 协议源代码分析(五)-ChangeGroupIDofLMO()
- SAE J1939 协议源代码分析(六)-J1939_CAN_Transmit(J1939_MESSAGE *MsgPtr)
- SAE J1939 协议源代码分析(七)-J1939_CAN_Receive(J1939_MESSAGE *MsgPtr)
- SAE J1939 协议源代码分析(四)-J1939_SetAddressFilter(unsigned char Ps_Address)
- SAE J1939 协议源代码分析(八)-4大中断使能与使能
- SAE J1939协议
- SAE J1939学习笔记(二)
- VC++中如何实现基于CAN的SAE J1939协议
- SAE J1939 协议入门前须知(一)
- SAE J1939介绍
- SAE J1939学习笔记(一)
- SAE J1939学习笔记(三)
- SAE J1939学习笔记(四)
- SAE J1939学习笔记(五)
- 转:C/C++基本数据类型所占字节数
- 华为优秀员工的16项标准让你的职场之路更顺利
- win10+vs2015配置theano+cuda8.0+cudnn
- GAN入门实践
- FoodMart的15个mdx例子,绝对一一经过测试,保证正确
- SAE J1939 协议源代码分析(二)-程序移植
- Oracle中update关联表
- 《Linux内核设计与实现》读书笔记(十六)- 页高速缓存和页回写
- java.util.concurrent 之TimeUnit
- 产品经理要注重目标用户需求转化
- python:代码缩进
- python+django+djcelery 入门级踩坑
- JavaScript中的数组遍历forEach()与map()方法以及兼容写法介绍
- 进程线程调度