【全志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:1RX packets:0 errors:0 dropped:0 overruns:0 frame:0TX packets:0 errors:0 dropped:0 overruns:0 carrier:0collisions: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:1RX packets:0 errors:0 dropped:0 overruns:0 frame:0TX packets:0 errors:0 dropped:0 overruns:0 carrier:0collisions: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.0inet6 addr: fe80::b8e9:f2ff:fe1c:9d87/64 Scope:LinkUP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1RX packets:421 errors:0 dropped:14 overruns:0 frame:0TX packets:9 errors:0 dropped:0 overruns:0 carrier:0collisions: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:1RX packets:0 errors:0 dropped:0 overruns:0 frame:0TX packets:0 errors:0 dropped:0 overruns:0 carrier:0collisions: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.0inet6 addr: ::1/128 Scope:HostUP LOOPBACK RUNNING  MTU:65536  Metric:1RX packets:0 errors:0 dropped:0 overruns:0 frame:0TX packets:0 errors:0 dropped:0 overruns:0 carrier:0collisions: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:1RX packets:0 errors:0 dropped:0 overruns:0 frame:0TX packets:0 errors:0 dropped:0 overruns:0 carrier:0collisions: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:1RX packets:0 errors:0 dropped:0 overruns:0 frame:0TX packets:0 errors:0 dropped:0 overruns:0 carrier:0collisions: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 <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <signal.h>
#include <string.h>#include "can_apply.h"#define MASTR_CAN1_ID      0x100
#define MASTR_CAN2_ID      0x101#define RX_MSG_NUM           16
#define MAX_BUF_LEN          64typedef 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;elseframe.can_dlc = cnt;for(j=0; j<frame.can_dlc; j++){frame.data[j] = buf[i+j];}if(can_send(sock, frame) < 0){ret = -1;break;}}return ret;
}void can_recv_data(int sock)
{static unsigned char tail = 0;int i;int can_id;unsigned char can_dlc;unsigned char *data;struct can_frame frame;int index = can0_sock == sock ? 0 : 1;if(can_recv(sock, &frame) < 0)return ;can_id = frame.can_id;can_dlc = frame.can_dlc;data = frame.data;printf("CAN%d dlc = %d, can_id = %x\ndata:", index,frame.can_dlc, frame.can_id);for(i=0; i<frame.can_dlc; i++)printf("0x%02x ", frame.data[i]);printf("\n");}void *can_proc_start(void *arg)
{int nready;int maxfd;fd_set readfds;int sock = *(int *)arg;FD_ZERO(&readfds);FD_SET(sock, &readfds);maxfd = sock;while(!bexit){nready = select(maxfd+1, &readfds, NULL, NULL, NULL);if(nready < 0){perror("can select");break;}else if(nready == 0){continue;}/* data is ready */if(FD_ISSET(sock, &readfds)){can_recv_data(sock);}else { ; }}close(sock);pthread_detach(pthread_self());pthread_exit(0);
}// 初始化CAN0和CAN1设备,并创建两个接收数据处理线程
static void can_sock_init()
{pthread_t tid;can0_sock = can_open("can0");if(can0_sock < 0)return ;can1_sock = can_open("can1");if(can1_sock < 0)return ;if (0 != pthread_create(&tid, NULL, can_proc_start, (void *)&can0_sock)){return ;}if (0 != pthread_create(&tid, NULL, can_proc_start, (void *)&can1_sock)){return ;}can1_id = MASTR_CAN1_ID;can2_id = MASTR_CAN2_ID;printf("can open sucess can0_sock:%d, can1_sock:%d\n", can0_sock, can1_sock);
}int main(int argc, char *argv[])
{char *send_data = "hello,can!";signal(SIGINT, signal_handler);signal(SIGPIPE, signal_handler);signal(SIGTERM, signal_handler);can_sock_init(); // 初始化CAN0和CAN1设备数据,并创建接收线程do {sleep(1);can_send_data(CAN_1, (unsigned char *)send_data, strlen(send_data) - 1);} while (!bexit);return 0;
}

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

  • 建立两个接收数据线程接收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
#  orset(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)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/633188.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

TypeScript依赖注入框架Typedi的使用、原理、源码解读

简介 typedi是一个基于TS的装饰器和reflect-metadata的依赖注入轻量级框架&#xff0c;使用简单易懂&#xff0c;方便拓展。 使用typedi的前提是安装reflect-metadata&#xff0c;并在项目的入口文件的第一行中声明import ‘reflect-metadata’&#xff0c;这样就会在原生的R…

【图解数据结构】深度解析时间复杂度与空间复杂度的典型问题

&#x1f308;个人主页&#xff1a;聆风吟 &#x1f525;系列专栏&#xff1a;图解数据结构、算法模板 &#x1f516;少年有梦不应止于心动&#xff0c;更要付诸行动。 文章目录 一. ⛳️上期回顾二. ⛳️常见时间复杂度计算举例1️⃣实例一2️⃣实例二3️⃣实例三4️⃣实例四5…

FPGA引脚选择(Select IO)--认知1

主要考虑功能角度&#xff08;速度&#xff0c;电平匹配&#xff0c;内部程序编写&#xff09;去找研究芯片内部资源 1. 关键字 HP I/O Banks, High performance The HP I/O banks are deisgned to meet the performance requirements of high-speed memory and other chip-to-…

参照oracle按名称排序,用js在前端对附件封装排序方法

此前因客户需求需要附件按照名称排序 而后台无法对单个文件夹做单独处理。虽可以在每次点击之后重新调用接口&#xff0c;再组装数据&#xff0c;但效率太低&#xff0c;且无须存储&#xff0c;而存储在当前文件夹的排序方法也需要更新。索性自己写了一个通用的方法。经测试排序…

彩超框架EchoSight开发日志记录

EchoSight开发记录 蒋志强 我会不定期的更新 开发进展。最近更新进展于2024年1月15日 1.背景 由于某些不可抗逆的原因&#xff0c;离开了以前的彩超大厂&#xff0c;竞业在家&#xff0c;难得有空闲的时间。我计划利用这段时间 自己独立 从零开始 搭建一套 彩超系统的软件工…

【陈老板赠书活动 - 22期】- 人工智能(第三版)

陈老老老板&#x1f9d9;‍♂️ &#x1f46e;‍♂️本文专栏&#xff1a;赠书活动专栏&#xff08;为大家争取的福利&#xff0c;免费送书&#xff09; &#x1f934;本文简述&#xff1a;活就像海洋,只有意志坚强的人,才能到达彼岸。 &#x1f473;‍♂️上一篇文章&#xff…

浅谈CPU进入保护模式的方法

看程序要想思路不乱&#xff0c;最重要的就是要抓到程序的主线&#xff0c;不要被一些只是用来保护的代码打乱。如何抓到主线呢&#xff1f;比较法学习代码是比较有效的&#xff0c;比如对于CPU如何进入保护模式的理解。 不同的操作系统作者有自己的方法&#xff0c;代码看起来…

高级编程JavaScript中的数据类型?存储上能有什么差别?

在JavaScript中&#xff0c;我们可以分成两种类型&#xff1a; 基本类型复杂类型 两种类型的区别是&#xff1a;存储位置不同 一、基本类型 基本类型主要为以下6种&#xff1a; NumberStringBooleanUndefinednullsymbol Number 数值最常见的整数类型格式则为十进制&…

Liunx:线程控制

目录 创建线程&#xff1a;pthread_create(); 线程等待&#xff1a;pthread_join(); 线程退出&#xff1a;pthread_exit(); 线程取消&#xff1a;pthread_cancel() 说线程的时候说过&#xff0c;liunx没有选择单独定义线程的数据结构和适配算法&#xff0c;而是用轻量级进程…

【计算机网络】OSI七层模型与TCP/IP四层模型的对应与各层介绍

1 OSI七层模型与TCP/IP四层模型对应 2 OSI七层模型介绍 OSI&#xff08;Open Systems Interconnection&#xff09;模型是一个由国际标准化组织&#xff08;ISO&#xff09;定义的七层网络体系结构&#xff0c;用于描述计算机网络中的通信协议。每一层都有特定的功能&#xff…

Python Web开发:构建高效、可扩展的Web应用

引言&#xff1a; 随着互联网的快速发展&#xff0c;Web应用已经成为人们日常生活中不可或缺的一部分。Python作为一种简单易学、功能强大的编程语言&#xff0c;在Web开发领域也有着广泛的应用。本文将介绍如何使用Python来构建高效、可扩展的Web应用&#xff0c;并提供一些实…

基于arcgis js api 4.x开发点聚合效果

一、代码 <html> <head><meta charset"utf-8" /><meta name"viewport"content"initial-scale1,maximum-scale1,user-scalableno" /><title>Build a custom layer view using deck.gl | Sample | ArcGIS API fo…

启动低轨道卫星LEO通讯产业与6G 3GPP NTN标准

通讯技术10年一个大跃进&#xff0c;从1990年的2G至2000年的3G网路&#xff0c;2010年的4G到近期2020年蓬勃发展的5G&#xff0c;当通讯技术迈入融合网路&#xff0c;当前的 5G 技术不仅可提供高频宽、低延迟&#xff0c;同时可针对企业与特殊需求以 5G 专网的模式提供各式服务…

yii2 手动安装第三方扩展

1复制第三方扩展到C:\Users\xpz\Documents\NetBeansProjects\yiicms\admincms.china.com\vendor\yiisoft\目录下 2 添加自动加载&#xff1a;打开vendor/yiisoft/extensions.php 文件&#xff0c;在里面的数组里增加一项&#xff0c;如下面代码 yiisoft/yii2-elasticsearch &…

【.NET Core】 多线程之(Thread)详解

【.NET Core】 多线程之&#xff08;Thread&#xff09;详解 文章目录 【.NET Core】 多线程之&#xff08;Thread&#xff09;详解一、概述二、线程的创建和使用2.1 ThreadStart用于无返回值&#xff0c;无参数的方法2.2 ParameterizedThreadStart:用于带参数的方法 三、线程的…

【机器学习】DBSCAN算法

参考链接&#xff1a; https://blog.csdn.net/haveanybody/article/details/113092851 https://www.jianshu.com/p/dd6ce77bfb8a 1 介绍 DBSCAN(Density-Based Spatial Clustering of Applica tion with Noise)算法是于1996年提出的一种简单的、有效的基于密度的聚类算法&…

使用 Python 第三方库 xlwt 写入数据到 Excel 工作表

1. 安装 xlwt 库 Python 写入数据到 Excel 工作簿中可以使用第三方库 xlwt. xlwt 拆分下来看就是 excel 和 write 的简化拼接&#xff0c;意思就是写数据到 Excel. 这个第三方库的 pip 安装命令如下所示&#xff1a; pip install xlwt -i https://mirrors.aliyun.com/pypi/si…

线性表的顺序存储实现

前言 线性表的顺序存储及基本操作的实现 一、数据对象集 线性表&#xff08;List&#xff09;是由n个元素构成的有序序列&#xff0c;用户处理线性表数据时常常需要初始化、查找、插入、删除、计算数据长度等操作。 数据Data利用数组存储&#xff0c;利用下标使得查找 等操作…

【手把手带你玩转MyBatis】进阶篇:强强联手,深度解析如何无缝整合MyBatis与Spring框架

在实际开发中&#xff0c;将MyBatis持久层框架与Spring框架进行整合&#xff0c;可以充分利用Spring的依赖注入&#xff08;DI&#xff09;和面向切面编程&#xff08;AOP&#xff09;等特性&#xff0c;进一步提升项目的可维护性和扩展性。以下是详细步骤&#xff1a; 1. 添加…

FairGuard游戏安全2023年度报告

导 读&#xff1a;2023年&#xff0c;游戏行业摆脱了疫情带来诸多负面影响&#xff0c;国内游戏市场收入与用户规模双双实现突破&#xff0c;迎来了历史新高点。但游戏黑灰产规模也在迅速扩大&#xff0c;不少游戏饱受其侵扰&#xff0c;游戏厂商愈发重视游戏安全问题。 为帮助…