SocketCAN 仅从套接字读取 returns 11cobid
SocketCAN read from socket only returns 11cobid
我正在尝试从 socketCAN 中读取,并且始终针对 11 位标识符过滤消息。
这应该是一个可以通过为 29 位标识符设置 rperper 标志来解决的问题,但我找不到任何人可以提供帮助的地方...
struct can_frame message;
struct sockaddr_can addr;
struct ifreq ifr;
int fd = -1; // file descriptor (it´s a socket)
if((fd = socket(PF_CAN, SOCK_RAW, CAN_RAW)) < 0)
{
LE_INFO("cannot open socket");
return;
}
strcpy(ifr.ifr_name, "can0");
ioctl(fd, SIOCGIFINDEX, &ifr);
addr.can_family = AF_CAN;
addr.can_ifindex = ifr.ifr_ifindex;
if(bind(fd, (struct sockaddr *)&addr, sizeof(addr)) < 0)
{
printf("cannot bind socket\n");
return;
}
uint8_t nbytes;
message.can_id |= CAN_EFF_FLAG;
while(1)
{
nbytes = read(fd, &message, sizeof(struct can_frame));
if (nbytes < 0) {
perror("can raw socket read");
return;
}
/* paranoid check ... */
if (nbytes < sizeof(struct can_frame)) {
fprintf(stderr, "read: incomplete CAN frame\n");
return;
}
printf("READ COB_ID:%x\n",message.can_id | CAN_EFF_FLAG);
}
return;
我正在发送一个带有 idx x901 的 CAN 帧,这是打印的内容:
阅读COB_ID:80000101
阅读COB_ID:80000101
阅读COB_ID:80000101
我已经用很多不同的方法解决了这个问题,看起来 C 代码可以正常工作,但我怀疑问题出在 mcp251x 的内核模块上,它没有正确接收扩展标志?或者它可能是我需要在 运行 内核模块之前做一些初始化???
提前感谢任何可以提供帮助的人。
您对 CAN 标志和过滤的理解不正确。看看摘自 linux can.h:
/* 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 */
这是一个适用于 SFF 和 EFF 消息的示例:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <net/if.h>
#include <sys/ioctl.h>
#include <sys/socket.h>
#include <linux/can.h>
#include <linux/can/raw.h>
int main(int argc, char **argv)
{
struct can_frame message;
struct sockaddr_can addr;
struct ifreq ifr;
int fd = -1; // file descriptor (it´s a socket)
if((fd = socket(PF_CAN, SOCK_RAW, CAN_RAW)) < 0)
{
printf("cannot open socket");
return -9;
}
strcpy(ifr.ifr_name, "vcan0");
ioctl(fd, SIOCGIFINDEX, &ifr);
addr.can_family = AF_CAN;
addr.can_ifindex = ifr.ifr_ifindex;
if(bind(fd, (struct sockaddr *)&addr, sizeof(addr)) < 0)
{
printf("cannot bind socket\n");
return -1;
}
u_int8_t nbytes;
message.can_id |= CAN_EFF_FLAG | CAN_RTR_FLAG | CAN_EFF_MASK;
while(1)
{
nbytes = read(fd, &message, sizeof(struct can_frame));
if (nbytes < 0) {
perror("can raw socket read");
return -2;
}
/* paranoid check ... */
if (nbytes < sizeof(struct can_frame)) {
fprintf(stderr, "read: incomplete CAN frame\n");
return -3;
}
printf("READ COB_ID: %x\n", message.can_id & CAN_EFF_MASK);
}
return 0;
}
现在发送这些消息:
cansend vcan0 00000123#FFFFFFFFFFFFFFFF
cansend vcan0 12345678#FFFFFFFFFFFFFFFF
给出正确的输出:
READ COB_ID: 123
READ COB_ID: 12345678
我正在尝试从 socketCAN 中读取,并且始终针对 11 位标识符过滤消息。 这应该是一个可以通过为 29 位标识符设置 rperper 标志来解决的问题,但我找不到任何人可以提供帮助的地方...
struct can_frame message;
struct sockaddr_can addr;
struct ifreq ifr;
int fd = -1; // file descriptor (it´s a socket)
if((fd = socket(PF_CAN, SOCK_RAW, CAN_RAW)) < 0)
{
LE_INFO("cannot open socket");
return;
}
strcpy(ifr.ifr_name, "can0");
ioctl(fd, SIOCGIFINDEX, &ifr);
addr.can_family = AF_CAN;
addr.can_ifindex = ifr.ifr_ifindex;
if(bind(fd, (struct sockaddr *)&addr, sizeof(addr)) < 0)
{
printf("cannot bind socket\n");
return;
}
uint8_t nbytes;
message.can_id |= CAN_EFF_FLAG;
while(1)
{
nbytes = read(fd, &message, sizeof(struct can_frame));
if (nbytes < 0) {
perror("can raw socket read");
return;
}
/* paranoid check ... */
if (nbytes < sizeof(struct can_frame)) {
fprintf(stderr, "read: incomplete CAN frame\n");
return;
}
printf("READ COB_ID:%x\n",message.can_id | CAN_EFF_FLAG);
}
return;
我正在发送一个带有 idx x901 的 CAN 帧,这是打印的内容:
阅读COB_ID:80000101
阅读COB_ID:80000101
阅读COB_ID:80000101
我已经用很多不同的方法解决了这个问题,看起来 C 代码可以正常工作,但我怀疑问题出在 mcp251x 的内核模块上,它没有正确接收扩展标志?或者它可能是我需要在 运行 内核模块之前做一些初始化???
提前感谢任何可以提供帮助的人。
您对 CAN 标志和过滤的理解不正确。看看摘自 linux can.h:
/* 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 */
这是一个适用于 SFF 和 EFF 消息的示例:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <net/if.h>
#include <sys/ioctl.h>
#include <sys/socket.h>
#include <linux/can.h>
#include <linux/can/raw.h>
int main(int argc, char **argv)
{
struct can_frame message;
struct sockaddr_can addr;
struct ifreq ifr;
int fd = -1; // file descriptor (it´s a socket)
if((fd = socket(PF_CAN, SOCK_RAW, CAN_RAW)) < 0)
{
printf("cannot open socket");
return -9;
}
strcpy(ifr.ifr_name, "vcan0");
ioctl(fd, SIOCGIFINDEX, &ifr);
addr.can_family = AF_CAN;
addr.can_ifindex = ifr.ifr_ifindex;
if(bind(fd, (struct sockaddr *)&addr, sizeof(addr)) < 0)
{
printf("cannot bind socket\n");
return -1;
}
u_int8_t nbytes;
message.can_id |= CAN_EFF_FLAG | CAN_RTR_FLAG | CAN_EFF_MASK;
while(1)
{
nbytes = read(fd, &message, sizeof(struct can_frame));
if (nbytes < 0) {
perror("can raw socket read");
return -2;
}
/* paranoid check ... */
if (nbytes < sizeof(struct can_frame)) {
fprintf(stderr, "read: incomplete CAN frame\n");
return -3;
}
printf("READ COB_ID: %x\n", message.can_id & CAN_EFF_MASK);
}
return 0;
}
现在发送这些消息:
cansend vcan0 00000123#FFFFFFFFFFFFFFFF
cansend vcan0 12345678#FFFFFFFFFFFFFFFF
给出正确的输出:
READ COB_ID: 123
READ COB_ID: 12345678