imx6ul+can使用

Source-lib第四弹:  can总线使用。

can总线的具体原理我就不说了,我也是第一次使用。可以看下下面的博客:
http://blog.csdn.net/righthek/article/details/17515465

老套路先看代码:
unsigned char send_buf[10] = {0xA5, 0xB4, 0xC3, 0xD2};
unsigned char rev_buf[10] = {0};
int rev_can_id = 0;

int main(int argc, char** argv)
{
        pid_t pid = -1;
        int master_fd;
        int slave_fd;
        master_fd = can_init(CAN0, 1000000, 0xA5A6, EXTENDED_FRAME);
        slave_fd = can_init(CAN1, 1000000, 0xA5A6, EXTENDED_FRAME);

        if (master_fd == -1 || slave_fd == -1) {
                ERR("get fd\n");
                return -1;
        }
        
         pid = fork();
         if (pid == -1) {
                ERR("fork\n");
         } else if (pid == 0) {/* 子进程 */
                while (1) {
                        can_send_data(master_fd, send_buf, 4);
                        sleep(1);
                }
         } else {
                while (1) {
                        rev_can_id = read_frame(slave_fd, rev_buf, 4);
                        //DEBUG("rev_can_id= %x\n", rev_can_id);
                        /* 扩展帧最高位为1,定义的又是无符号型所以会被识别为负数 */
                        if (rev_can_id != -1) {
                                INFO("rev_can_id = %x\n", rev_can_id);
                                INFO("rev_buf: %x %x %x %x\n", rev_buf[0], rev_buf[1], rev_buf[2], rev_buf[3]);
                        }
                        sleep(1);
                }
         }
        return 0;
}
1、先初始化了两个can口
2、然后创建了个子进程
3、子进程用于1秒发送一帧数据。父进程用于接收数据,并打印到串口上。

1.初始化了两个can口
EXPORT int can_init(int port,
                                        int bitrate,
                                        int can_id,
                                        int frame_type
                                        )
{
        int socket_fd = -1;
        close_can(port);
        set_bitrate(port, bitrate);
        open_can(port);
        socket_fd = socket_can_listen(port);
        if (socket_fd < 0) {
                ERR("socket_can_listen\n");
                return -1;
        }
        set_can_filter(socket_fd, can_id, frame_type);
        g_can_id = can_id;
        g_frame_type = frame_type;
        return socket_fd;
}
要设置can口必须先关闭can口,而且要先设置波特率。不然无法打开can口。
还有can的驱动框架已经套用网络框架了,所以可以使用socket。
接下来做了一个socket连接。

2、子进程发送
EXPORT int can_send_data(int socket_fd, unsigned char *data_buf, int len)
{
        return send_frame(socket_fd, g_can_id, g_frame_type, data_buf, len);
}
按指定的can_id,指定的帧格式进程一定长度的数据发送。
帧格式一共有三种:标准帧,扩展帧,远程帧。

3、父进程接收
EXPORT int read_frame(int socket_fd, unsigned char *rev_buf, int len)
{
        struct can_frame frame;
        int ret = read_hardware(socket_fd, &frame, sizeof(struct can_frame));
        if (ret < 0) {
                DEBUG("can raw socket read\n");
                return -1;
        }
        memcpy(rev_buf, frame.data, len);
        return frame.can_id;
}
就是read函数,读取一个can_frame结构体的数据,返回can_id

这个结构体如下:
/*
        struct can_frame {
        canid_t can_id;  // 32 bit CAN_ID + EFF/RTR/ERR flags
        __u8    can_dlc; // frame payload length in byte (0 .. CAN_MAX_DLEN)
        __u8    data[CAN_MAX_DLEN] __attribute__((aligned(8)));
};
*/

这是个can0和can1的通信例子,接线如下:


效果图如下:


你可能感兴趣的:(linux学习过程)