can/socket can

1. 概念

參考:Linux-CAN編程詳解linux

can引腳: cn2: 15:CAN1_H 19 CAN1_Landroid


根據每組報文開頭的 11 位標識符(擴展幀爲29位標識符、CAN 2.0A 規範)解釋數據的含義來決定是否接收。編程

 

CAN狀態:網絡

準備狀態:
這個節點的處理器將要發送的數據和本身的標識符傳送給該節點的 CAN 總線接口控制器socket

報文狀態:
當收到總 線分配時,轉爲發送報文狀態。oop

接收狀態:
數據根據協議組織成必定的報文格式後發出,此時網絡上的其餘節點處於接收狀態。處於接收狀態的每一個節點對接
收到的報文進行檢測,判斷這些報文是不是發給本身的以肯定是否接收。測試


層次結構:
對象層:在對象層中能夠爲遠程數據請求以及數據傳輸提供服務,肯定由實際要使用的傳輸層接收哪個報文,而且
爲恢復管理和過載通知提供手段。
傳輸層:傳輸層負責位的定時及同步、報文分幀、仲裁、應答、錯誤檢測和標定、故障界定。
物理層:波特率之類的spa


報文結構:
數據幀:發送數據
遠程幀:請求數據
錯誤幀:檢測到錯誤則發出
過載幀:提供幀與幀之間的延時3d

 


ip link set can0 type can bitrate 125000code

 流程:

1. 建立socket
2. bind將socket綁定can
3. 設置選項setsockopt
4. read/write

 

經常使用命令:

在控制檯上輸入命令:
ifconfig –a
能夠獲得如下結果:

lo Link encap:Local Loopback
inet addr:127.0.0.1 Mask:255.0.0.0
inet6 addr: ::1/128 Scope: Host
UP LOOPBACK RUNNING MTU:65536 Metric:1
RX packets:0 errors:0 dropped:0 overruns:0 frame:0
TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:0
RX bytes:0 TX bytes:0

eth0 Link encap:Ethernet HWaddr F6:88:05:8F:72:8C
UP BROADCAST MULTICAST MTU:1500 Metric:1
RX packets:0 errors:0 dropped:0 overruns:0 frame:0
TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:1000
RX bytes:0 TX bytes:0

can0 Link encap:UNSPEC
UP RUNNING NOARP MTU:16 Metric:1
RX packets:0 errors:0 dropped:0 overruns:0 frame:0
TX packets:4 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:10
RX bytes:0 TX bytes:2
Interrupt:32

 

令來配置 CAN 總線的位速率:

ip link set can0 type cantq 125 prop-seg 6phase-seg1 7 phase-seg2 2 sjw 1


也可使用 ip 命令直接設定位速率:

ip link set can0 type can bitrate 125000


當設置完成後,能夠經過下面的命令查詢 can0 設備的參數設置:

ip -details link show can0


當設置完成後,可使用下面的命令使能 can0 設備:

ifconfig can0 up


使用下面的命令取消 can0 設備使能:

ifconfig can0 down


在設備工做中,可使用下面的命令來查詢工做狀態:

ip -details -statistics link show can0

 

2. 測試流程:

1. 啓動Linux的can0,並初始化

ifconfig can0 down   //要修改can的參數,必須先down
ip link set can0 type can bitrate 1000000
ifconfig can0 up

 

2. 測試代碼

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <net/if.h>
#include <sys/ioctl.h>
#include <sys/socket.h>
#include <linux/can.h>
#include <linux/can/raw.h>




int main()
{
    int fd, nbytes;
    struct sockaddr_can addr;
    struct ifreq ifr;
    int ret;
    
    //1. 初始化
    struct can_frame frame[4] = {{0}};
    fd = socket(PF_CAN, SOCK_RAW, CAN_RAW);//建立套接字

    printf("version=6;fd=%d\n", fd);
    
    strcpy(ifr.ifr_name, "can0" );
    ioctl(fd, SIOCGIFINDEX, &ifr); //指定 can0 設備
    addr.can_family = AF_CAN;
    addr.can_ifindex = ifr.ifr_ifindex;
    ret = bind(fd, (struct sockaddr *)&addr, sizeof(addr));//將套接字與 can0 綁定
    printf("ret=%d\n", ret);
    
    //禁用過濾規則,本進程不接收報文,只負責發送
    setsockopt(fd, SOL_CAN_RAW, CAN_RAW_FILTER, NULL, 0);
    //報文1:數據幀:標準幀、ID=0x11;
    frame[0].can_id = 0x11;
    frame[0]. can_dlc = 1;
    frame[0].data[0] = 0x12;
    
    //報文2:數據幀:擴展幀、ID=0x22
    frame[1].can_id = 0x22 | CAN_EFF_FLAG;
    frame[1]. can_dlc = 1;
    frame[1].data[0] = 0x34;

    //報文3:遠程幀:ID=0x33;
    frame[2].can_id = 0x33 | CAN_RTR_FLAG;

    //報文4:錯誤幀:ID=0x44;
    frame[3].can_id = 0x44 | CAN_ERR_FLAG;


    //循環發送兩個報文
    //while(1)
    {
        nbytes = write(fd, &frame[0], sizeof(frame[0])); //發送 frame[0]
        if(nbytes != sizeof(frame[0]))
        {
            printf("Send Error frame[0]\n!");
            //break; //發送錯誤,退出
        }else{
            printf("Send Sucess frame[0]\n!");
        }
        //usleep(10000);
        sleep(1);
        nbytes = write(fd, &frame[1], sizeof(frame[1])); //發送 frame[1]
        if(nbytes != sizeof(frame[1]))
        {
            printf("Send Error frame[1]\n!");
            //break;
        }else{
                printf("Send Sucess frame[1]\n!");
        }
        //usleep(10000);
        sleep(1);
        nbytes = write(fd, &frame[2], sizeof(frame[2])); //發送 frame[1]
        if(nbytes != sizeof(frame[2]))
        {
            printf("Send Error frame[2]\n!");
            //break;
        }else{
                printf("Send Sucess frame[21]\n!");
        }
        //usleep(10000);
        sleep(1);
        nbytes = write(fd, &frame[3], sizeof(frame[3])); //發送 frame[1]
        if(nbytes != sizeof(frame[3]))
        {
            printf("Send Error frame[3]\n!");
            //break;
        }else{
                printf("Send Sucess frame[3]\n!");
        }
        //usleep(10000);
        sleep(1);
    }
    
    close(fd);
    return 0;
}

 

3. 現象

android上現象:

 

Windows上現象:

 

波形現象:(注:由於上面的發送太少,抓不到數據,因此下面的是我更換了其餘代碼查看的)

CPU出來的CAN信號,是標準信號

 

進過轉換事後的,很難查看出來,可是就是這個差分信號

相關文章
相關標籤/搜索