#include "lib.h"
//*------------------------------------------------------------------------------------------------
//* 函数名称: InitCanDevice
//* 功能描述: 初始化can接口打开设备描述符
//* 入口参数:
//* -- CanId: - CAN口设备号
//* -- Rate : -CAN口的速率
//*
//* 返回值 : 返回一个int型的can描述符
//* 备注 : 无
//*------------------------------------------------------------------------------------------------
int InitCanDevice(unsigned int CanId,unsigned int Rate)
{
char Command[100];
int sdcan=0;//套接字描述符
char ptr[20];//存放设备名字
char dev[20];
struct sockaddr_can addr;
int nbytes;
struct ifreq ifr;
sprintf(Command,"ifconfig can%d down",CanId);
if(system(Command)>=0)
{
printf("shut down the can%d is sucessful\n",CanId);
}else {
printf("shut down the can%d is failed\n",CanId);
exit(1);
}
sprintf(Command,"ip link set can%d type can bitrate %d",CanId,Rate);
if(system(Command)>=0)
{
printf("set the can%d bitrate %d is sucessful\n",CanId,Rate);
}else {
printf("set the can%d bitrate %d is failed\n",CanId,Rate);
exit(1);
}
sprintf(Command,"ifconfig can%d up",CanId);
if(system(Command)>=0)
{
printf("start the can%d is sucessful\n",CanId);
}else {
printf("start the can%d is failed\n",CanId);
exit(1);
}
sprintf(dev,"can%d",CanId);
strcpy(ptr,dev);
sdcan = socket(PF_CAN, SOCK_RAW, CAN_RAW);// 创建套接字描述符
if (sdcan < 0)
{
perror("socket");
exit (1);
}
nbytes = strlen(ptr);//判断设备名长度
if (nbytes >= IFNAMSIZ) //如果设备名过长,则提示
{
fprintf(stderr, "name of CAN device '%s' is too long!\n", ptr);
exit (1);
}
addr.can_family = AF_CAN;//协议族
memset(&ifr.ifr_name, 0, sizeof(ifr.ifr_name));
strncpy(ifr.ifr_name, ptr, nbytes);//拷贝设备名
printf("using interface name '%s'.\n", ifr.ifr_name);
if (ioctl(sdcan, SIOCGIFINDEX, &ifr) < 0) //把 接口 的 索引 存入 ifr_ifindex
{
perror("SIOCGIFINDEX");
exit(1);
}
addr.can_ifindex = ifr.ifr_ifindex;
if (bind(sdcan, (struct sockaddr *)&addr, sizeof(addr)) < 0)//绑定
{
perror("bind");
exit (1);
}
return sdcan;
}
//*------------------------------------------------------------------------------------------------
//* 函数名称: ReadCanData
//* 功能描述: 读取打开的CAN口缓冲区里的数
//* 入口参数:
//* -- sdcan: - CAN口设备描述符
//* -- frame: -CAN帧结构体
//*
//* 返回值 : 返回一个int型数读成功返回1,失败返回0
//* 备注 : 无
//*------------------------------------------------------------------------------------------------
int ReadCanData(int sdcan,struct can_frame *frame)
{
char *frame_type=NULL;
int nbytes;
int dlc;
struct iovec iov;
struct msghdr msg;
iov.iov_base = &frame;
msg.msg_iov = &iov; // 指向结构体struct iovec指针,记录数据内容
//接受数据帧
nbytes = read(sdcan, frame, sizeof(struct can_frame));
//读取数据失败原因判断
if (nbytes < 0)
{
perror("read");
return 0;
}
if (nbytes < sizeof(struct can_frame)) //如果读取到的数据帧小于can帧的结构,为不完整的数据帧
{
fprintf(stderr, "read: incomplete CAN frame\n");
return 0;
}
dlc = (frame->can_dlc > 8)? 8 :frame->can_dlc;//判断帧的数据长度,最大值为8
//判断帧类型
if (frame->can_id & CAN_ERR_FLAG) //错误帧
{
frame->can_id &= (CAN_ERR_MASK|CAN_ERR_FLAG);
frame_type="ERR";
}
else if (frame->can_id & CAN_EFF_FLAG) //扩展帧
{
frame->can_id &= CAN_EFF_MASK;//标准帧
frame_type="EFF";
}
else
{
frame->can_id &= CAN_SFF_MASK;//标准帧
frame_type="SFF";
}
return 1;
}
//*------------------------------------------------------------------------------------------------
//* 函数名称: WriteCanData
//* 功能描述: 写入数据到CAN设备
//* 入口参数:
//* -- sdcan: - CAN口设备描述符
//* -- frame: -CAN帧结构体
//*
//* 返回值 : 返回一个int型数读成功返回1,失败返回0
//* 备注 : 无
//*------------------------------------------------------------------------------------------------
int WriteCanData(int sdcan,struct can_frame frame)
{
int nbytes=0;
printf("write the %.8x %.2x %.2x %.2x %.2x %.2x %.2x %.2x %.2x %.2x \n",frame.can_id,frame.can_dlc,frame.data[0],frame.data[1],frame.data[2],frame.data[3],frame.data[4],frame.data[5],frame.data[6],frame.data[7]);
nbytes = write(sdcan, &frame, sizeof(struct can_frame)); //发送数据
//数据发送错误原因判断
if (nbytes < 0)
{
if (errno != ENOBUFS)
{
perror("write");
return 0;
}
}else if (nbytes < sizeof(struct can_frame))
{
fprintf(stderr, "write: incomplete CAN frame\n");
return 0;
}
return 1;
}
//*------------------------------------------------------------------------------------------------
//* 函数名称: CloseSd
//* 功能描述:关闭CAN设备
//* 入口参数:
//* -- sdcan: - CAN口设备描述符
//* 返回值 : 无
//* 备注 : 无
//*------------------------------------------------------------------------------------------------
void CloseSd(int sdcan)
{
close(sdcan);
}