c_cpp CAN设备远程通信

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了c_cpp CAN设备远程通信相关的知识,希望对你有一定的参考价值。

/* 定义通信报文类型 */



struct car_frame{			
	short int head;		//报文头
	short int identification;	//报文标识

	/* 手机APP */
	short int Left;				//左转
	short int Right;			//右转
	short int Brake;			//刹车
	short int Accelerator;		//油门
	short int Gear;				//档位
	short int EmergencyBrake;	//紧急制动
	short int Lock;				//车门锁定
	int 	  Window;			//车窗调节
	short int Flag;				//遥控标志位
	unsigned int AccAim;		//车辆加速度

	/* 模拟驾驶舱 */
	short int CarID;			//车辆ID
	int 	  Speed;			//控制速度
	int 	  Angle;			//方向盘转角
//	short int Flag;				//遥控标志位
	unsigned short CheckBit;	//校验位

};
#include <can_config.h>

#include <errno.h>
#include <getopt.h>
#include <libgen.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <limits.h>
#include <stdint.h>

#include <arpa/inet.h>
#include <netinet/in.h>

#include <net/if.h>

#include <sys/ioctl.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <sys/uio.h>

#include <linux/can.h>
#include <linux/can/raw.h>

/* 通信相关协议 */
#include <can_socket.h>	

extern int optind, opterr, optopt;

static int	s = -1;		
static int	running = 1;		

enum {
	VERSION_OPTION = CHAR_MAX + 1,
	FILTER_OPTION,
};

static void sigterm(int signo)
{
	running = 0;
}

static struct can_filter *filter = NULL;
static int filter_count = 0;

/* 定义全局报文 */
struct car_frame send_frame ;
struct car_frame recv_frame;

int add_filter(u_int32_t id, u_int32_t mask);

#define BUF_SIZ	(255)

int main(int argc, char **argv)
{
	//修改部分
	struct sockaddr_in server_addr_in;
	int cfd;							//创建Socket描述符
	int port = 1234;

	struct ifreq ifr;
	struct sockaddr_can addr;
	FILE *out = stdout;				//文件输出
	char *interface = "can0";
	char *optout = NULL;
	char *ptr;
	char buf[BUF_SIZ];
	int family = PF_CAN, type = SOCK_RAW, proto = CAN_RAW;
	int n = 0, err;
	int nbytes, i, j;
	int opt, optdaemon = 0;
	int canID_flag;	//不同类型帧标志位
	struct can_frame frame = {
		.can_id = 1,
	};
	struct can_frame Final_CAN = {
		.can_id = 1,
	};	//最终发送CAN报文

	int flag = 1;

	__u8 temp_buf[15] = {0};
	
	int s, ret,dlc = 0, rtr = 0, extended = 0;

	__u8* r_temp;

	__u8 temp[7] = {0};		//存储待转换的数值和转换后的数值
	__u8 bin_frame[64];

	uint32_t id, mask;

	signal(SIGPIPE, SIG_IGN);


	/* 网络Socket建立连接 */
	cfd = socket( AF_INET, SOCK_STREAM, 0 );	//创建Socket连接

	bzero( &server_addr_in, sizeof(server_addr_in) );

	server_addr_in.sin_family = AF_INET;
	server_addr_in.sin_port = htons(port);	
	inet_pton( AF_INET, "118.25.187.160", &server_addr_in.sin_addr );
 

	if (optind != argc)
		interface = argv[optind];
	
	printf("interface = %s, family = %d, type = %d, proto = %d\n",
	       interface, family, type, proto);

	/* 本地CAN设备的Socket连接 */
	if ((s = socket(family, type, proto)) < 0) {
		perror("socket");
		return 1;
	}

	addr.can_family = family;
	strncpy(ifr.ifr_name, interface, sizeof(ifr.ifr_name));
	if (ioctl(s, SIOCGIFINDEX, &ifr)) {
		perror("ioctl");
		return 1;
	}
	addr.can_ifindex = ifr.ifr_ifindex;

	if (bind(s, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
		perror("bind");
		return 1;
	}

	if (filter) {
		if (setsockopt(s, SOL_CAN_RAW, CAN_RAW_FILTER, filter,
			filter_count * sizeof(struct can_filter)) != 0) {
			perror("setsockopt");
			exit(1);
		}
	}

	if (optdaemon)
		daemon(1, 0);
	else {
		signal(SIGTERM, sigterm);
		signal(SIGHUP, sigterm);
	}

	if (optout) {
		out = fopen(optout, "a");
		if (!out) {
			perror("fopen");
			exit (EXIT_FAILURE);
		}
	}
	//修改部分,实现网络Socket连接
	if(connect( cfd, (struct sockaddr *)&server_addr_in, sizeof(server_addr_in) ) < 0){
		printf("can't connect to server!\n");
		exit(1);
	}
	printf("Connecting success!\n");

	while (1) {
		if(flag){ //进行时间片轮转
			//-------------------------------------------------------------------
			//开发板-->服务器
			//-------------------------------------------------------------------
			if ((nbytes = read(s, &frame, sizeof(struct can_frame))) < 0) {
				perror("read");
				return 1;
			} 
			if (frame.can_id & CAN_EFF_FLAG)
				n = snprintf(buf, BUF_SIZ, "<0x%08x> ", frame.can_id & CAN_EFF_MASK);
			else {
				n = snprintf(buf, BUF_SIZ, "<0x%03x> ", frame.can_id & CAN_SFF_MASK); 			
			}
			n += snprintf(buf + n, BUF_SIZ - n, "[%d] ", frame.can_dlc);

			
			//----------------------------------------------
			//报文修改
			//----------------------------------------------

			//汽车方向盘转角
			send_frame.Angle =  (frame.data[7] + (frame.data[6]<<8) )*0.01;

			//汽车加速度
			send_frame.AccAim = frame.data[5]*0.05-7;

			printf("send_frame.Angle = %d\n",send_frame.Angle);
			printf("send_frame.AccAim = %d\n",send_frame.AccAim);

			send(cfd,&send_frame,sizeof(send_frame),0);

			n = 0;flag = 0;
		}
		else {
			//-------------------------------------------------------------------
			//服务器-->开发板
			//-------------------------------------------------------------------
			if((recv(cfd,&recv_frame,sizeof(recv_frame),0)) < 0){
				printf("Error comes when receive data\n");
				exit(1);
			}
			//----------------------------------------------
			//报文修改
			//----------------------------------------------

			printf("recv_frame.Angle = %d\n",recv_frame.Angle);
			printf("recv_frame.AccAim = %d\n",recv_frame.AccAim);

			//汽车方向盘转角
			temp[7] = (recv_frame.Angle)*100 		&  0xff;
			temp[6] = ((recv_frame.Angle)*100)>>8 	&  0xf;

			//汽车加速度
			temp[5] = (recv_frame.AccAim)*20 +7;


			dlc = 0;	
			for(i = 0;i < 8 ; i ++){
				Final_CAN.data[dlc++] = temp[i];
				if(dlc == 8)
					break;
			}

			memset(temp,0,sizeof(temp));
			memset(&recv_frame,0,sizeof(recv_frame));

			Final_CAN.can_dlc = dlc;
			Final_CAN.can_id &= CAN_SFF_MASK;

			//往CAN设备写数据
			ret = write(s,&Final_CAN,sizeof(Final_CAN));
			if(ret == -1){
				perror("write");
				break; 
			}	
			flag = 1;
		}			
	}
	close(cfd);
	exit (EXIT_SUCCESS);
}


int add_filter(u_int32_t id, u_int32_t mask)
{
	filter = realloc(filter, sizeof(struct can_filter) * (filter_count + 1));
	if(!filter)
		return -1;

	filter[filter_count].can_id = id;
	filter[filter_count].can_mask = mask;
	filter_count++;

	printf("id: 0x%08x mask: 0x%08x\n",id,mask);
	return 0;
}

以上是关于c_cpp CAN设备远程通信的主要内容,如果未能解决你的问题,请参考以下文章

CAN与CAN FD通信之间存在的问题

物联网智能网关-09CAN总线通信演示(TinyGUI触屏)

CAN总线每帧含多少字节

ROS基于SocketCAN的通信方式

c_cpp CAN总线模拟器(初始)

stm32 常见错误之can线通信