文章摘要:本文描述了关于CAN总线应用程序的编程。
内核版本:linux-3.8.13
硬件平台:AM335x


内核配置: 添加CAN驱动程序及协议

[*] Networking support --->
    <*> CAN bus subsystem support  --->
        <*> Raw CAN Protocol (raw access with CAN-ID filtering)
        <*> Broadcast Manager CAN Protocol (with content filtering)
            CAN Device Drivers  --->
                <*> Bosch D_CAN devices  --->
                    <*>   Generic Platform Bus based D_CAN driver

AM335x CAN控制器驱动程序位于:drivers/net/can/c_can目录下
c_can_platform.c
c_can.c


系统设置:命令及说明:

配置CAN总线参数

# ip link set can0 type can bitrate 500000 triple-sampling on

或者

# canconfig can0 bitrate 500000 ctrlmode triple-sampling on

bitrate参数用于设置波特率,此处设置为500K bps.

使能CAN总线接口

# ip link set can0 up

或者

# canconfig can0 start 

此命令完成后,可通过ifconfig查看到相关接口。

关闭CAN总线接口

# ip link set can0 down

或者

# canconfig can0 stop

示例代码:

/*
 * 初始化CAN控制器
 */
int can_open(char* name)
{
    int fd;
    struct ifreq can_ifr;
    struct sockaddr_can can_addr; 
    // int flag = 1; 
       
    // 初始化socket套接字用于CAN设备
    fd = socket(PF_CAN, SOCK_RAW, CAN_RAW);     
            
    strcpy(can_ifr.ifr_name, name);     
    ioctl(fd, SIOCGIFINDEX, &can_ifr);        // 指定can设备   
      
    can_addr.can_family  = AF_CAN;            // 指定协议族
    can_addr.can_ifindex = can_ifr.ifr_ifindex;  
             
    bind(fd, (struct sockaddr *)&can_addr, sizeof(can_addr)); // 绑定
    //ioctl(fd, FIONBIO, &flag);        //设置为非阻塞模式  
    return fd;  
}
/*
 *  向CAN总线发送数据
 */
int can_send(int can, int id, unsigned char* buff)
{
    int ret; 
    struct can_frame can_frm = {0};
    
    can_frm.can_id  = id;      
    can_frm.can_dlc = 8;  
    memcpy(can_frm.data, buff, 8);
    
    ret = write(can, &can_frm, sizeof(can_frm));    
    if(ret != sizeof(can_frm)) 
    {   
        printf("can send error: id = %X\r\n", id);  
    }

    return 0;
}
/*
 *  向CAN总线读取数据
 */
int can_recv(int can, struct can_frame* pcf)
{
    int rxlen;
    
    // 正常情况下返回值为16(struct can_frame的长度)
    rxlen = read(can, pcf, sizeof(struct can_frame));
    if(rxlen != sizeof(struct can_frame))    
    {           
        return -1;    // 读取失败
    }

    return 0;
}