读取C中的can总线显示29位can ID的can ID不正确
我用c写了一些代码来读取CAN总线数据 当我读取11位CAN ID时,一切正常 当我试图读取29位ID时,它显示的ID不正确 示例:读取C中的can总线显示29位can ID的can ID不正确,c,linux,can-bus,C,Linux,Can Bus,我用c写了一些代码来读取CAN总线数据 当我读取11位CAN ID时,一切正常 当我试图读取29位ID时,它显示的ID不正确 示例: 接收29位id的消息: 0x01F0A020 并用 printf(“%X\n”,frame.can\u id) 它打印 81F0A020 11位ID消息 0x7DF 并用 printf(“%X\n”,frame.can\u id) 打印正确 7DF 有人能告诉我为什么会这样吗 #include <stdio.h> #include <stdlib
接收29位id的消息:
0x01F0A020
并用
printf(“%X\n”,frame.can\u id)
它打印
81F0A020 11位ID消息
0x7DF
并用
printf(“%X\n”,frame.can\u id)
打印正确
7DF 有人能告诉我为什么会这样吗
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <net/if.h>
#include <fcntl.h>
#include <inttypes.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/ioctl.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <linux/can.h>
#include <linux/can/raw.h>
#define MAX_DATA_LEN 8
#define MAX_FIELDS 23
#define MAX_FIELD_LEN 64
#include <limits.h>
char data_str[MAX_FIELDS][MAX_FIELD_LEN];
int i;
int
main(void)
{
int s;
int nbytes;
struct sockaddr_can addr;
struct can_frame frame;
unsigned short data[MAX_FIELDS];
int sockfd=0;
int bcast=1;
struct sockaddr_in src_addr;
struct sockaddr_in dst_addr;
int numbytes;
int fa;
struct ifreq ifr;
fa = socket(AF_INET, SOCK_DGRAM, 0);
ifr.ifr_addr.sa_family = AF_INET;
strncpy(ifr.ifr_name, "eth0", IFNAMSIZ-1);
ioctl(fa, SIOCGIFHWADDR, &ifr);
close(fa);
//
if((sockfd = socket(PF_INET,SOCK_DGRAM,0)) == -1)
{
perror("Udp sockfd create failed");
exit(1);
}
//Enabled broadcast mode for udp
if((setsockopt(sockfd,SOL_SOCKET,SO_BROADCAST,
&bcast,sizeof bcast)) == -1)
{
perror("setsockopt failed for broadcast mode ");
exit(1);
}
src_addr.sin_family = AF_INET;
src_addr.sin_port = htons(8888);
src_addr.sin_addr.s_addr = INADDR_ANY;
memset(src_addr.sin_zero,'\0',sizeof src_addr.sin_zero);
if(bind(sockfd, (struct sockaddr*) &src_addr, sizeof src_addr) == -1)
{
perror("bind");
exit(1);
}
dst_addr.sin_family = AF_INET;
dst_addr.sin_port = htons(45454);
dst_addr.sin_addr.s_addr = inet_addr("127.0.0.1");
memset(dst_addr.sin_zero,'\0',sizeof dst_addr.sin_zero);
if((s = socket(PF_CAN, SOCK_RAW, CAN_RAW)) < 0) {
perror("Error while opening socket");
return -1;
}
addr.can_family = AF_CAN;
addr.can_ifindex = 0;
if(bind(s, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
perror("Error in socket bind");
return -2;
}
//struct can_frame frame;
while(1)
{
nbytes = read(s, &frame, sizeof(struct can_frame));
if (nbytes < 0) {
perror("can raw socket read");
return 1;
}
/* paranoid check ... */
if (nbytes < sizeof(struct can_frame)) {
fprintf(stderr, "read: incomplete CAN frame\n");
return 1;
}
//Print the received CAN ID
printf("%X\n",frame.can_id);
}
return 0;
}
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#定义最大数据长度8
#定义最大值字段23
#定义最大字段长度64
#包括
char data_str[MAX_FIELDS][MAX_FIELD_LEN];
int i;
int
主(空)
{
int-s;
整数字节;
结构sockaddr\u can addr;
结构can_框架;
无符号短数据[最大字段];
int-sockfd=0;
int-bcast=1;
src_addr中的结构sockaddr_;
dst_addr中的结构sockaddr_;
整数单位;
int-fa;
结构ifreq-ifr;
fa=插座(AF_INET,SOCK_DGRAM,0);
ifr.ifr\u addr.sa\u family=AF\u INET;
strncpy(ifr.ifr_名称,“eth0”,IFNAMSIZ-1);
ioctl(fa、SIOCGIFHWADDR和ifr);
关闭(fa);
//
if((sockfd=socket(PF_INET,SOCK_DGRAM,0))=-1)
{
perror(“Udp sockfd创建失败”);
出口(1);
}
//已启用udp的广播模式
如果((设置锁定选择)(sockfd、SOL_插座、SO_广播、,
&bcast,sizeof bcast))=-1)
{
perror(“广播模式设置锁定失败”);
出口(1);
}
src_addr.sin_family=AF_INET;
src_addr.sin_port=htons(8888);
src_addr.sin_addr.s_addr=INADDR_ANY;
memset(src_addr.sin_zero、\0',src_addr.sin_zero的大小);
if(绑定(sockfd,(结构sockaddr*)&src_addr,src_addr的大小)=-1)
{
佩罗(“绑定”);
出口(1);
}
dst_addr.sin_family=AF_INET;
dst地址sin端口=htons(45454);
dst_addr.sin_addr.s_addr=inet_addr(“127.0.0.1”);
memset(dst地址单零、\0',dst地址单零的大小);
如果((s=插座(PF_CAN、SOCK_RAW、CAN_RAW))<0){
perror(“打开插座时出错”);
返回-1;
}
addr.can_family=AF_can;
地址can\U ifindex=0;
if(绑定(结构sockaddr*)&addr,sizeof(addr))<0{
perror(“套接字绑定错误”);
返回-2;
}
//结构can_框架;
而(1)
{
nbytes=读取(s,&frame,sizeof(struct can_frame));
如果(n字节<0){
perror(“可读取原始套接字”);
返回1;
}
/*偏执狂检查*/
if(n字节
结构can框架的can id
字段包含can id和EFF/RTR/ERR标志。扩展ID有29位,因此有3个空闲位用于表示3个标志
示例ID0x01F0A020
必须是扩展帧,但ID0x7DF
可以作为基本帧或扩展帧发送。这些是不同的信息。要区分具有相同ID的基本帧或扩展帧,需要EFF标志
在您的示例中,您可以看到值0x81F0A020
,它是ID0x01F0A020
和CAN\u EFF\u标志的组合(0x80000000U
)
从中提取
要仅获取不带标志的ID,应根据CAN\U EFF\U标志
位的值应用CAN\U SFF\U掩码
或CAN\U EFF\U掩码
示例代码:
//Print the received CAN ID
printf("%X\n",
(frame.can_id & CAN_EFF_FLAG) ? (frame.can_id & CAN_EFF_MASK)
: (frame.can_id & CAN_SFF_MASK));
struct can_frame
的can_id
字段包含can id和EFF/RTR/ERR标志。扩展ID有29位,因此有3个空闲位用于表示3个标志
示例ID0x01F0A020
必须是扩展帧,但ID0x7DF
可以作为基本帧或扩展帧发送。这些是不同的信息。要区分具有相同ID的基本帧或扩展帧,需要EFF标志
在您的示例中,您可以看到值0x81F0A020
,它是ID0x01F0A020
和CAN\u EFF\u标志的组合(0x80000000U
)
从中提取
要仅获取不带标志的ID,应根据CAN\U EFF\U标志
位的值应用CAN\U SFF\U掩码
或CAN\U EFF\U掩码
示例代码:
//Print the received CAN ID
printf("%X\n",
(frame.can_id & CAN_EFF_FLAG) ? (frame.can_id & CAN_EFF_MASK)
: (frame.can_id & CAN_SFF_MASK));
为什么fishy(struct sockaddr*)
会强制转换?@Bodo在不同结构类型之间强制转换会调用未定义的行为,很可能是一个bug。它们是真正兼容的类型吗?如果是,为什么要使用两种不同的类型。它要么是代码气味,要么是库气味struct sockaddr
与struct sockaddr\u can
完全不兼容,因此它似乎是一个库错误。它们是不兼容的类型,这也是一种严格的别名冲突。@Bodo唯一重要的是,如果结构被反引用为struct sockaddr
anywhere,那么它就是一个bug。否则这只是一个混乱的API设计。@问题是,他们不能检查初始元素,除非它与整个struct sockaddr\u can
具有相同的左值类型,而事实并非如此。在最坏的情况下,您会得到未对齐的访问。充其量,你会收到一个公开邀请,让gcc优化器发疯。为什么可疑的(struct sockaddr*)
强制转换?@Bodo在不同的结构类型之间强制转换调用未定义的
//Print the received CAN ID
printf("%X\n",
(frame.can_id & CAN_EFF_FLAG) ? (frame.can_id & CAN_EFF_MASK)
: (frame.can_id & CAN_SFF_MASK));