#include "drv_can.h" #include #include #include #include #include #include #include #include #include #include #include #include #include /*PPSIX 终端控制定义*/ #include "drv_can.h" /* * @description : 字符串按格式输出 * @param - *destpoint : 字符串格式缓冲区 * @param - *fmt : 多个参数 * @return : 按格式输出字符串缓冲区首指针 */ char func_dprintf(char *destpoint, char *fmt, ...) { va_list arg_ptr; char ulen, *tmpBuf; tmpBuf = destpoint; va_start(arg_ptr, fmt); ulen = vsprintf(tmpBuf, fmt, arg_ptr); va_end(arg_ptr); return ulen; } /* * @description : 打开can外设,设置波特率,创建文件描述符 * @param - *device : 设备名称 * @param - para : can应用参数 * @return : 打开设备执成功返回文件描述符,失败返回-1 */ int func_open_can(char *device, struct_can_param para) { FILE *fstream = NULL; char buff[300] = {0}, command[50] = {0}; int fd = -1; struct sockaddr_can addr; struct ifreq ifr; /*关闭can设备 ifconfig can0 down*/ memset(buff, 0, sizeof(buff)); memset(command, 0, sizeof(command)); func_dprintf(command, "ifconfig %s down", device); printf("%s \n", command); if (NULL == (fstream = popen(command, "w"))) { fprintf(stderr, "execute command failed: %s", strerror(errno)); } while (NULL != fgets(buff, sizeof(buff), fstream)) { printf("%s\n", buff); if (strstr(buff, "No such device") || strstr(buff, "Cannot find device")) return -1; } pclose(fstream); sleep(1); /*设置can波特率 ip link set can0 up type can bitrate 250000 triple-sampling on*/ memset(buff, 0, sizeof(buff)); memset(command, 0, sizeof(command)); if (para.loopback_mode == 1) { func_dprintf(command, "ip link set %s up type can bitrate %d triple-sampling on loopback on", device, para.baudrate); } else { func_dprintf(command, "ip link set %s up type can bitrate %d triple-sampling on loopback off", device, para.baudrate); } printf("%s \n", command); if (NULL == (fstream = popen(command, "w"))) { fprintf(stderr, "execute command failed: %s", strerror(errno)); } while (NULL != fgets(buff, sizeof(buff), fstream)) { printf("%s\n", buff); if (strstr(buff, "No such device") || strstr(buff, "Cannot find device")) return -1; } pclose(fstream); sleep(1); /*打开can设备 ifconfig can0 up*/ memset(buff, 0, sizeof(buff)); memset(command, 0, sizeof(command)); func_dprintf(command, "ifconfig %s up", device); printf("%s \n", command); if (NULL == (fstream = popen(command, "w"))) { fprintf(stderr, "execute command failed: %s", strerror(errno)); } while (NULL != fgets(buff, sizeof(buff), fstream)) { printf("%s\n", buff); if (strstr(buff, "No such device") || strstr(buff, "Cannot find device")) return -1; } pclose(fstream); sleep(3); /* 创建 socket */ fd = socket(PF_CAN, SOCK_RAW, CAN_RAW); if (fd < 0) { printf("socket:%s", strerror(errno)); return -1; } /* 设置接口设备名称 */ strcpy(ifr.ifr_name, device); /* 确定接口 index */ if (ioctl(fd, SIOCGIFINDEX, &ifr) < 0) { printf("SIOCGIFINDEX:%s\n", strerror(errno)); return -1; } memset(&addr, 0, sizeof(addr)); addr.can_family = AF_CAN; addr.can_ifindex = ifr.ifr_ifindex; /* 绑定 socket到 CAN 接口 */ if (bind(fd, (struct sockaddr *)&addr, sizeof(addr)) < 0) { printf("bind:%s\n", strerror(errno)); return -1; } return fd; } /* * @description : 设置can回环模式和过滤规则 * @param - fd : 文件描述符 * @param - para: can应用参数 * @return : 设置成功返回1,失败返回-1 */ int func_set_can(int fd, struct_can_param para) { int loopback = 1; int reciveown = 1; if (para.loopback_mode == 1) { //回环设置 0 关闭回环 1 打开回环 setsockopt(fd, SOL_CAN_RAW, CAN_RAW_LOOPBACK, &loopback, sizeof(loopback)); //接收自己的帧 0 不接收自己帧 1 接收自己帧 setsockopt(fd, SOL_CAN_RAW, CAN_RAW_RECV_OWN_MSGS, &reciveown, sizeof(reciveown)); } /* 设置过滤规则 */ if (setsockopt(fd, SOL_CAN_RAW, CAN_RAW_FILTER, ¶.filter, sizeof(para.filter)) < 0) { printf("error when set filter\n"); return -1; } return 1; } /* * @description : can接收一个can帧 * @param - fd : 文件描述符 * @param - *pframe: 一个can帧结构体指针 * @return : 接收数据长度 */ int func_receive_can_frame(int fd, struct can_frame *pframe) { int rx_count = 0; rx_count = recv(fd, pframe, sizeof(*pframe), 0); if (rx_count <= 0) { return rx_count; } else { if (pframe->can_id & CAN_EFF_FLAG) /*如果是扩展帧,清除扩展帧标识*/ { pframe->can_id &= (~CAN_EFF_FLAG); } else { pframe->can_id &= (~CAN_SFF_MASK); } } return pframe->can_dlc; } /* * @description : can接收一组数据包 * @param - fd : 文件描述符 * @param - *buff: 要接收can一组数据的缓冲区首指针 * @param - len : 接收到一组数据的长度 * @return : 接收数据长度 */ int func_receive_can_buff(int fd, unsigned char *buff, int len) { int receive_len = 0, total_receive_len = 0; struct can_frame frame; int i = 0; while (1) { receive_len = func_receive_can_frame(fd, &frame); for (i = 0; i < receive_len; i++) { *(buff + total_receive_len) = frame.data[i]; total_receive_len++; } if ((receive_len < 8) || (total_receive_len > (len - 8))) { return total_receive_len; } } return total_receive_len; } /* * @description : can发送一个can帧 * @param - fd : 文件描述符 * @param - *pframe: 一个can帧结构体指针 * @param - param : can应用参数 * @return : 发送数据长度,发送失败返回-1 */ int func_send_can_frame(int fd, struct can_frame *pframe, struct_can_param param) { int result = 0; if (param.extend == 1) /*扩展帧增加扩展帧标志*/ { pframe->can_id &= CAN_EFF_MASK; pframe->can_id |= CAN_EFF_FLAG; } else { pframe->can_id &= CAN_SFF_MASK; } result = send(fd, pframe, sizeof(struct can_frame), 0); if (result == -1) { printf("send:%s\n", strerror(errno)); return -1; } return result; } /* * @description : can发送一组数据包 * @param - fd : 文件描述符 * @param - *buff: 要发送can一组数据的缓冲区首指针 * @param - len : 发送数据的长度 * @param - param: can应用参数 * @return : 实际发送数据长度 */ int func_send_can_buff(int fd, unsigned char *buff, int len, struct_can_param param) { int remain_frame_len = 0, frame_numb = 0; struct can_frame frame; int i = 0; remain_frame_len = len; while (1) { if (remain_frame_len >= 8) { frame.can_dlc = 8; /*填充发送长度*/ remain_frame_len -= 8; /*剩余数据长度*/ } else { frame.can_dlc = remain_frame_len; /*填充发送长度*/ remain_frame_len = 0; // } frame.can_id = param.id; /*填充发送id*/ for (i = 0; i < frame.can_dlc; i++) { frame.data[i] = buff[frame_numb * 8 + i]; /*填充发送数据*/ } func_send_can_frame(fd, &frame, param); frame_numb++; if (remain_frame_len == 0) { return len; } } return len; }