diff --git a/drv/drv_can.c b/drv/drv_can.c index e69de29..d420a5f 100644 --- a/drv/drv_can.c +++ b/drv/drv_can.c @@ -0,0 +1,301 @@ +#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; +} \ No newline at end of file diff --git a/drv/drv_can.h b/drv/drv_can.h index e69de29..d507fd9 100644 --- a/drv/drv_can.h +++ b/drv/drv_can.h @@ -0,0 +1,33 @@ +#ifndef __DRV_CAN_H_ +#define __DRV_CAN_H_ + +#include + +#define CAN_MODE 0 +#define CAN_FD_MODE 1 +#define _DEFAULT_SOURCE + +/*CAN口参数结构体 */ +typedef struct +{ + unsigned long baudrate; /*波特率 5k~1000k*/ + unsigned int id; /*设备ID*/ + struct can_filter filter; /*接收设备过滤ID*/ + unsigned char extend; /*扩展ID*/ + unsigned char loopback_mode; /*回环模式*/ + + unsigned char canfd_mode; /*CANFD模式*/ + unsigned long data_baudrate; /*CANFD模式下需要单独设置数据波特率*/ +} struct_can_param; + +int func_open_can(char *device, struct_can_param para); +int func_set_can(int fd, struct_can_param para); +int func_receive_can_buff(int fd, unsigned char *buff, int len); +int func_send_can_buff(int fd, unsigned char *buff, int len, struct_can_param param); + +// int func_open_canfd(char *device, struct_can_param para); +// int func_set_canfd(int fd, struct_can_param para); +// int func_receive_canfd_buff(int fd, unsigned char *buff, int len); +// int func_send_canfd_buff(int fd, unsigned char *buff, int len, struct_can_param param); + +#endif \ No newline at end of file