【全志T113-i】OK113i-S开发板CAN通信C代码测试

飞凌官方手册中关于CAN测试部分使用的是命令行进行的简单测试,实际开发过程中还是要使用C代码去操作CAN设备,本帖主要讲解怎么使用C代码对CAN设备进行读写的收发操作。

First of all ,先查看所有网卡信息,看看板上是否有CAN设备网络:

root@ok113i:/# ifconfig -a
can0      Link encap:UNSPEC  HWaddr 00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00  
          NOARP  MTU:16  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:10 
          RX bytes:0 (0.0 B)  TX bytes:0 (0.0 B)

can1      Link encap:UNSPEC  HWaddr 00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00  
          NOARP  MTU:16  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:10 
          RX bytes:0 (0.0 B)  TX bytes:0 (0.0 B)
          Interrupt:1 

eth0      Link encap:Ethernet  HWaddr BA:E9:F2:1C:9D:87  
          inet addr:192.168.0.232  Bcast:0.0.0.0  Mask:255.255.255.0
          inet6 addr: fe80::b8e9:f2ff:fe1c:9d87/64 Scope:Link
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:421 errors:0 dropped:14 overruns:0 frame:0
          TX packets:9 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000 
          RX bytes:27272 (26.6 KiB)  TX bytes:726 (726.0 B)
          Interrupt:39 

ip6tnl0   Link encap:UNSPEC  HWaddr 00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00  
          NOARP  MTU:1452  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 (0.0 B)  TX bytes:0 (0.0 B)

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:1000 
          RX bytes:0 (0.0 B)  TX bytes:0 (0.0 B)

sit0      Link encap:IPv6-in-IPv4  
          NOARP  MTU:1480  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 (0.0 B)  TX bytes:0 (0.0 B)

wlan0     Link encap:Ethernet  HWaddr 2C:C3:E6:67:4D:3B  
          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 (0.0 B)  TX bytes:0 (0.0 B)

1. CAN组网前的准备,设置CAN通信服务的通信速率。

使用如下命令分别设置CAN0和CAN1的通信速率:

root@ok113i:/home/forlinx# ip link set can0 up type can bitrate 500000
[ 4075.425084] IPv6: ADDRCONF(NETDEV_CHANGE): can0: link becomes ready
root@ok113i:/home/forlinx# ip link set can1 up type can bitrate 500000                                   
[ 4086.037967] IPv6: ADDRCONF(NETDEV_CHANGE): can1: link becomes ready

以上设置can0 和 can1 通信速率均为500kbps,这个速率值务必记住,所有接入组网的的can节点都是以这个速率通信。

2. 使用C语言写一个CAN通信的发送接收测试程序,主要验证CAN发送和接收数据是否正常。

#include 
#include 
#include 
#include 
#include 
#include 

#include "can_apply.h"


#define MASTR_CAN1_ID      0x100
#define MASTR_CAN2_ID      0x101

#define RX_MSG_NUM           16
#define MAX_BUF_LEN          64

typedef enum
{
	CAN_1,
	CAN_2,
	CAN_RES
}can_type;

typedef struct{
	int can_id;
	unsigned char can_dlc;
	unsigned char data[MAX_BUF_LEN];
}can_msg_t;


static int bexit = 0;
static int can0_sock,can1_sock;
can_msg_t can_rx_msg[RX_MSG_NUM];
unsigned int can1_id = 0;
unsigned int can2_id = 0;


void signal_handler(int signo)
{

    printf("signal %d(%s) received\n", signo, strsignal(signo));


	bexit = 1;

}

int can_send_data(can_type type, unsigned char *buf, int len)
{
    int i, j;
    int cnt;
    int sock;
    int ret = 0;
    struct can_frame frame;

    if(type == CAN_1)
    {
        sock = can0_sock;
        frame.can_id = can1_id;
    }
    else {
        sock = can1_sock;
        frame.can_id = can2_id;
    }

    for(i = 0; i < len; i += 8)
    {
        cnt = len - i;

        if(cnt > 8)
            frame.can_dlc =  8;
        else
            frame.can_dlc = cnt;

        for(j=0; j

测试程序主要实现了如下功能:

  • 建立两个接收数据线程接收CAN设备的数据并打印CAN网络上的数据。
  • 通过CAN0设备定时1秒发送一串"hello,can!"数据到CAN网络。

3. 运行并验证程序功能。

PC上使用CAN分析工具按下图接好线
​编辑

打开CAN调试软件,配置成500kbps的速率并打开设备,如下:
​编辑
使用CAN调试软件给设备发送数据,如下:
​编辑

将编译好的程序上传到板子上并运行,以下是正常收到数据后程序的打印信息:

root@ok113i:/home/forlinx# ./can_test 
can open sucess can0_sock:3, can1_sock:4
## PC往CAN0口发送测试数据接收打印
CAN0 dlc = 6, can_id = 201
data:0x30 0x31 0x32 0x33 0x34 0x55 
CAN0 dlc = 6, can_id = 201
data:0x30 0x31 0x32 0x33 0x34 0x55 
CAN0 dlc = 6, can_id = 201
data:0x30 0x31 0x32 0x33 0x34 0x55 
CAN0 dlc = 6, can_id = 201
data:0x30 0x31 0x32 0x33 0x34 0x55 
CAN0 dlc = 6, can_id = 201
data:0x30 0x31 0x32 0x33 0x34 0x55 
CAN0 dlc = 6, can_id = 201
data:0x30 0x31 0x32 0x33 0x34 0x55 
CAN0 dlc = 6, can_id = 201
data:0x30 0x31 0x32 0x33 0x34 0x55 
CAN0 dlc = 6, can_id = 201
data:0x30 0x31 0x32 0x33 0x34 0x55 
CAN0 dlc = 6, can_id = 201
data:0x30 0x31 0x32 0x33 0x34 0x55 
## PC往CAN1 口发送测试数据接收打印
CAN1 dlc = 6, can_id = 201
data:0x30 0x31 0x32 0x33 0x34 0x55 
CAN1 dlc = 6, can_id = 201
data:0x30 0x31 0x32 0x33 0x34 0x55
CAN1 dlc = 6, can_id = 201
data:0x30 0x31 0x32 0x33 0x34 0x55 
CAN1 dlc = 6, can_id = 201
data:0x30 0x31 0x32 0x33 0x34 0x55 
CAN1 dlc = 6, can_id = 201
data:0x30 0x31 0x32 0x33 0x34 0x55 
CAN1 dlc = 6, can_id = 201
data:0x30 0x31 0x32 0x33 0x34 0x55 
CAN1 dlc = 6, can_id = 201
data:0x30 0x31 0x32 0x33 0x34 0x55 
CAN1 dlc = 6, can_id = 201
data:0x30 0x31 0x32 0x33 0x34 0x55 
CAN1 dlc = 6, can_id = 201
data:0x30 0x31 0x32 0x33 0x34 0x55 
CAN1 dlc = 6, can_id = 201
data:0x30 0x31 0x32 0x33 0x34 0x55

测试程序工程结构

├── build # 编译目录
├── can_apply.c                           # CAN 操作简单封装C源码
├── can_apply.h                           # CAN 操作简单封装头文件 
├── CMakeLists.txt                      # cmake 编译规则文件
├── cross-t113-i.cmake               # CMake嵌入式交叉编译工具链文件
└── main.c                                   # 测试程序主体源代码

工程源代码编译

cd build
cmake .. -DCMAKE_TOOLCHAIN_FILE=../cross-t113-i.cmake
make
Scanning dependencies of target can_test
[ 33%] Building C object CMakeFiles/can_test.dir/main.c.o
[ 66%] Building C object CMakeFiles/can_test.dir/can_apply.c.o
[100%] Linking C executable can_test
[100%] Built target can_test

工程使用cmake进行编译,需要注意的是要根据实际情况修改cross-t113-i.cmake中的GCC交叉编译工具的路径。

#
# CMake Toolchain file for crosscompiling on ARM.
#
# This can be used when running cmake in the following way:
#  cd build-t113/
#  cmake .. -DCMAKE_TOOLCHAIN_FILE=../cross-t113-i.cmake
#  or



set(CROSS_PATH /home/luoyang/Dev/sdk/T113-i/OK113i-linux-sdk/out/t113_i/ok113i/longan/buildroot/host)

# Target operating system name.
set(CMAKE_SYSTEM_NAME Linux)

set (CMAKE_C_FLAGS "-std=gnu11" CACHE STRING "Set C Compiler Flags" FORCE)

# Name of C compiler.
set(CMAKE_C_COMPILER "${CROSS_PATH}/bin/arm-linux-gnueabi-gcc")
set(CMAKE_CXX_COMPILER "${CROSS_PATH}/bin/arm-linux-gnueabi-g++")

set (CMAKE_C_FLAGS "-std=gnu11 -mcpu=cortex-a7 -mfloat-abi=softfp -mfpu=neon-vfpv4 -mno-unaligned-access -fno-aggressive-loop-optimizations -ffunction-sections" CACHE STRING "Set C Compiler Flags" FORCE)
set (CMAKE_CXX_FLAGS "-mcpu=cortex-a7 -mfloat-abi=softfp -mfpu=neon-vfpv4 -mno-unaligned-access -fno-aggressive-loop-optimizations -ffunction-sections" CACHE STRING "Set C++ Compiler Flags" FORCE)

# link flags
set(CMAKE_LINK_FLAGS "${CMAKE_LINK_FLAGS} -mcpu=cortex-a7 -mfloat-abi=softfp -mfpu=neon-vfpv4 -mno-unaligned-access -fno-aggressive-loop-optimizations"  CACHE STRING "Set link Flags" FORCE)


SET(CMAKE_SYSTEM_PROCESSOR "armv7-a_hardfp")

add_definitions(-fPIC)
add_definitions(-DARMLINUX)
add_definitions(-D__gnu_linux__)


# Where to look for the target environment. (More paths can be added here)
set(CMAKE_FIND_ROOT_PATH "${CROSS_PATH}/arm-buildroot-linux-gnueabi/sysroot")

# Adjust the default behavior of the FIND_XXX() commands:
# search programs in the host environment only.
set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)

# Search headers and libraries in the target environment only.
set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)

你可能感兴趣的:(全志-工具&测试,linux,网络,CAN,c++,通信)