linux CAN编程(二)

您所在的位置:网站首页 can数据类型 linux CAN编程(二)

linux CAN编程(二)

2023-12-21 06:44| 来源: 网络整理| 查看: 265

转载自:https://blog.csdn.net/qwaszx523/article/details/54984544

/**  * struct can_frame - basic CAN frame structure  * @can_id:  CAN ID of the frame and CAN_*_FLAG flags, see canid_t definition  * @can_dlc: frame payload length in byte (0 .. 8) aka data length code  *           N.B. the DLC field from ISO 11898-1 Chapter 8.4.2.3 has a 1:1  *           mapping of the 'data length code' to the real payload length  * @data:    CAN frame payload (up to 8 byte)  */ struct can_frame {  canid_t can_id;  /* 32 bit CAN_ID + EFF/RTR/ERR flags */  __u8    can_dlc; /* frame payload length in byte (0 .. CAN_MAX_DLEN) */  __u8    data[CAN_MAX_DLEN] __attribute__((aligned(8))); };

can_id定义如下所示,是一个无符号的32位整形数

typedef __u32 canid_t;

can_id数据组织形式如下

/*  * Controller Area Network Identifier structure  *  * bit 0-28 : CAN identifier (11/29 bit)  * bit 29 : error message frame flag (0 = data frame, 1 = error message)  * bit 30 : remote transmission request flag (1 = rtr frame)  * bit 31 : frame format flag (0 = standard 11 bit, 1 = extended 29 bit)  */

0-28位为标识符,如果是扩展帧,则高11位为标准ID

29位标识是数据帧还是错误消息

30位说明是否是远程帧

31位说明是标准帧还是扩展帧。

以下是在处理can_frame时用到的掩码和标识符:

/* special address description flags for the CAN_ID */ #define CAN_EFF_FLAG 0x80000000U /* EFF/SFF is set in the MSB */ #define CAN_RTR_FLAG 0x40000000U /* remote transmission request */ #define CAN_ERR_FLAG 0x20000000U /* error message frame */

/* valid bits in CAN ID for frame formats */ #define CAN_SFF_MASK 0x000007FFU /* standard frame format (SFF) */ #define CAN_EFF_MASK 0x1FFFFFFFU /* extended frame format (EFF) */ #define CAN_ERR_MASK 0x1FFFFFFFU /* omit EFF, RTR, ERR flags */

对can_frame的处理是在mcp251x_hw_tx中进行的,如下:

static void mcp251x_hw_tx(struct spi_device *spi, struct can_frame *frame,      int tx_buf_idx) {  struct mcp251x_priv *priv = spi_get_drvdata(spi);  u32 sid, eid, exide, rtr;  u8 buf[SPI_TRANSFER_BUF_LEN];

 exide = (frame->can_id & CAN_EFF_FLAG) ? 1 : 0; //取can_id的31位,判断是标准帧还是扩展帧  if (exide)   sid = (frame->can_id & CAN_EFF_MASK) >> 18;//如果是扩展帧,can_id的0-28位为ID,其中高11位为标准ID  else   sid = frame->can_id & CAN_SFF_MASK; /* Standard ID */  eid = frame->can_id & CAN_EFF_MASK; /* Extended ID */

 rtr = (frame->can_id & CAN_RTR_FLAG) ? 1 : 0; /* 是否是远程帧*/

 buf[TXBCTRL_OFF] = INSTRUCTION_LOAD_TXB(tx_buf_idx);    //发送缓冲器控制寄存器地址  buf[TXBSIDH_OFF] = sid >> SIDH_SHIFT;        //发送缓冲器标准ID高8位

//5-7位存放发送缓冲器低3位,3位存放帧格式,0-1位存放扩展标识符低18位的高两位(16-17)  buf[TXBSIDL_OFF] = ((sid & SIDL_SID_MASK) SIDL_EID_SHIFT) & SIDL_EID_MASK);  buf[TXBEID8_OFF] = GET_BYTE(eid, 1);     //存放扩展标识符低18位的8-15位  buf[TXBEID0_OFF] = GET_BYTE(eid, 0);    //扩展标识符低18位的低8位(0-7)  buf[TXBDLC_OFF] = (rtr can_dlc; //6位存放远程帧标识符,0-3存放数据长度码  memcpy(buf + TXBDAT_OFF, frame->data, frame->can_dlc);//拷贝要发送的数据  mcp251x_hw_tx_frame(spi, buf, frame->can_dlc, tx_buf_idx);

 /* use INSTRUCTION_RTS, to avoid "repeated frame problem" */  priv->spi_tx_buf[0] = INSTRUCTION_RTS(1 spi, 1); }

static void mcp251x_hw_rx_frame(struct spi_device *spi, u8 *buf,     int buf_idx) {  struct mcp251x_priv *priv = spi_get_drvdata(spi);

 if (mcp251x_is_2510(spi)) {   int i, len;

  for (i = 1; i < RXBDAT_OFF; i++)    buf[i] = mcp251x_read_reg(spi, RXBCTRL(buf_idx) + i);

  len = get_can_dlc(buf[RXBDLC_OFF] & RXBDLC_LEN_MASK);   for (; i < (RXBDAT_OFF + len); i++)    buf[i] = mcp251x_read_reg(spi, RXBCTRL(buf_idx) + i);  } else {   priv->spi_tx_buf[RXBCTRL_OFF] = INSTRUCTION_READ_RXB(buf_idx);   mcp251x_spi_trans(spi, SPI_TRANSFER_BUF_LEN);   memcpy(buf, priv->spi_rx_buf, SPI_TRANSFER_BUF_LEN);  } } ---------------------  作者:qwaszx523  来源:CSDN  原文:https://blog.csdn.net/qwaszx523/article/details/54984544  版权声明:本文为博主原创文章,转载请附上博文链接!



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3