SAE J1939 协议源代码分析(二)-程序移植

预备知识

1.熟悉CAN2.0B协议,及相关硬件驱动开发
2.熟悉SAE J1939协议<http://blog.csdn.net/xietongxueflyme/article/details/74276702/>

 
 
  • 1
  • 2

程序移植流程

Created with Raphaël 2.1.0 将代码加载到你的工程 打开配置文件J1939_Config.h 明白默认地址和 标识符配置规则? 了解J1939支持的 功能配置使用的功能 熟悉AN2.0B驱动编写 按J1939_Config.h文件提示说 明,移植相关的函数功能 移植完成 练习CAN2.0B扩展帧驱动编写 参考J1939-21 查阅J1939附录B( 地址和标识符分配) yes no yes no yes no

移植示例(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() 
/******************************J1939CAN驱动接口函数************************************/
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];
    /*加载29ID*/
    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()
{
    INTERRUPT_Enable(&CAN_RInterrupt_DEBUG);
}

void J1939_RXinterruptDisable()
{
    INTERRUPT_Disable(&CAN_RInterrupt_DEBUG);
}
void J1939_TXinterruptEnable()
{
    ;
}

void J1939_TXinterruptDisable()
{
    ;
}
#endif
 
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • 129
  • 130
  • 131
  • 132
  • 133
  • 134
  • 135
  • 136
  • 137
  • 138
  • 139
  • 140
  • 141
  • 142
  • 143
  • 144
  • 145
  • 146
  • 147
  • 148

备注

J1939与CAN2.0B驱动接口函数在后面,将逐一的分析。

  • 1
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值