1. CAN簡介
使用Socket CAN的主要目的就是為用戶空間的應(yīng)用程序提供基于Linux網(wǎng)絡(luò)層的套接字接口。與廣為人知的TCP/IP協(xié)議以及以太網(wǎng)不同,CAN總線沒有類似以太網(wǎng)的MAC層地址,只能用于廣播。CAN ID僅僅用來進行總線的仲裁。因此CAN ID在總線上必須是唯一的。當設(shè)計一個CAN-ECU(Electronic Control Unit 電子控制單元)網(wǎng)絡(luò)的時候,CAN報文ID可以映射到具體的ECU。因此CAN報文ID可以當作發(fā)送源的地址來使用。
1.1 開發(fā)板的CAN資源

1.2 硬件連接

通常由CPU出來的CAN信號是TTL信號,并不是差分信號。因此需要一個CAN TTL信號轉(zhuǎn)CAN差分信號的模塊。其具體的接線圖如下所示。

2. 快速上手
2.1 開發(fā)環(huán)境準備
如果您初次閱讀此文檔,請閱讀《入門指南/開發(fā)環(huán)境準備/Easy-Eai編譯環(huán)境準備與更新》,并按照其相關(guān)的操作,進行編譯環(huán)境的部署。
在PC端Ubuntu系統(tǒng)中執(zhí)行run腳本,進入EASY-EAI編譯環(huán)境,具體如下所示。
cd ~/develop_environment ./run.sh

2.2 源碼下載以及例程編譯
首先,在虛擬機后臺終端,執(zhí)行以下命令,創(chuàng)建外設(shè)單例源碼管理目錄:
cd /opt mkdir -p EASY-EAI-Nano-TB/demo
首先,到【百度網(wǎng)盤】上下載相關(guān)的單例程序:
鏈接:https://pan.baidu.com/s/1Br608Hiff2Xs65PzWO_qWQ?pwd=1234
提取碼:1234
比如把單例程序下載到:此電腦\D:\BaiduNetdisk (無規(guī)定,用戶可自主選擇),如下圖所示。

再將下載好的單例復(fù)制進入虛擬機的文件系統(tǒng),過程如下圖所示。



最后,進入到對應(yīng)的例程目錄執(zhí)行編譯操作,具體命令如下所示:
cd EASY-EAI-Nano-TB/demo/11_CAN ./build.sh
注:
* 由于依賴庫部署在板卡上,因此交叉編譯過程中必須保持/mnt掛載。

編譯成功后,會生成2個demo,一個是發(fā)送端:test-can_send,另一個是接收端:test-can_reception。并會自動部署到開發(fā)板的/userdata/目錄中。
* 此例程需要2個板卡做收發(fā)測試,所以2個板卡都需要重復(fù)上述操作。
2.3 例程運行
通過串口調(diào)試或ssh調(diào)試,進入板卡后臺,定位到例程部署的位置,如下所示:
cd /userdata

首先在一臺板卡上運行發(fā)送端,運行命令如下:
sudo ./test-can-send
然后【再在另外一臺】板卡上,運行接收端,運行命令如下:
cd /userdata sudo ./test-can-reception
【接收端】執(zhí)行效果如下所示。

API的詳細說明,以及API的調(diào)用(本例程源碼),詳細信息見下方說明。
3. CAN操作API說明
3.1 創(chuàng)建socketcan套接字操作
創(chuàng)建socketcan套接字操作函數(shù)原型如下所示。
int socket(int domain, int type, int protocol);
具體介紹如下所示。

3.2 指定本地網(wǎng)絡(luò)接口地址操作
指定本地網(wǎng)絡(luò)接口地址函數(shù)原型如下所示。
int ioctl(int fd, unsigned long request, ...);
具體介紹如下所示。


3.3 綁定地址結(jié)構(gòu)操作
綁定地址結(jié)構(gòu)函數(shù)原型如下所示。
int bind(int sockfd, const struct sockaddr *addr,socklen_t addrlen);
具體介紹如下所示。

3.4 設(shè)置CAN過濾器操作
設(shè)置CAN過濾器操作函數(shù)原型如下所示。
int setsockopt(int sockfd, int level, int optname, const void *optval, socklen_t optlen);


3.5 CAN定義報文格式操作
CAN定義報文格式如下所示。

4. CAN通信例程
【發(fā)送端】例程源碼為11_CAN/test-can_send/main.c,操作流程如下。

【接收端】例程源碼為11_CAN/test-can_send/main.c,操作流程如下。

參考例程如下所示。
發(fā)送端例程:
/* 將CAN0波特率設(shè)置為500000 bps */ #define ip_cmd_set_can_params "ip link set can0 type can bitrate 500000 triple-sampling on" /* 打開CAN0 */ #define ip_cmd_open "ifconfig can0 up" /* 關(guān)閉CAN0 */ #define ip_cmd_close "ifconfig can0 down" int main() { int fd, nbytes; struct sockaddr_can addr; struct ifreq ifr; struct can_frame frame[2] = {{0}}; system(ip_cmd_close); system(ip_cmd_set_can_params); system(ip_cmd_open); fd = socket(PF_CAN, SOCK_RAW, CAN_RAW);//創(chuàng)建套接字 strcpy(ifr.ifr_name, "can0" ); ioctl(fd, SIOCGIFINDEX, &ifr); //指定 can0 設(shè)備 addr.can_family = AF_CAN; addr.can_ifindex = ifr.ifr_ifindex; bind(fd, (struct sockaddr *)&addr, sizeof(addr));//將套接字與 can0 綁定 //禁用過濾規(guī)則,本進程不接收報文,只負責發(fā)送 setsockopt(fd, SOL_CAN_RAW, CAN_RAW_FILTER, NULL, 0); //生成兩個報文 frame[0].can_id = 0x11; frame[0]. can_dlc = 1; frame[0].data[0] = 'Y'; frame[1].can_id = 0x22; frame[1]. can_dlc = 1; frame[1].data[0] = 'N'; //循環(huán)發(fā)送兩個報文 while(1) { nbytes = write(fd, &frame[0], sizeof(frame[0])); //發(fā)送 frame[0] printf("write ret:%d",nbytes); if(nbytes != sizeof(frame[0])) { printf("Send Error frame[0]\n!"); break; //發(fā)送錯誤,退出 } sleep(1); nbytes = write(fd, &frame[1], sizeof(frame[1])); //發(fā)送 frame[1] if(nbytes != sizeof(frame[1])) { printf("Send Error frame[1]\n!"); break; } sleep(1); } close(fd); return 0; }
接收端例程:
/* 將CAN0波特率設(shè)置為500000 bps */ #define ip_cmd_set_can_params "ip link set can0 type can bitrate 500000 triple-sampling on" /* 打開CAN0 */ #define ip_cmd_open "ifconfig can0 up" /* 關(guān)閉CAN0 */ #define ip_cmd_close "ifconfig can0 down" int main() { int fd, nbytes; struct sockaddr_can addr; struct ifreq ifr; struct can_frame frame; struct can_filter rfilter[1]; system(ip_cmd_close); system(ip_cmd_set_can_params); system(ip_cmd_open); fd = socket(PF_CAN, SOCK_RAW, CAN_RAW); //創(chuàng)建套接字 strcpy(ifr.ifr_name, "can0" ); ioctl(fd, SIOCGIFINDEX, &ifr); //指定 can0 設(shè)備 addr.can_family = AF_CAN; addr.can_ifindex = ifr.ifr_ifindex; bind(fd, (struct sockaddr *)&addr, sizeof(addr)); //將套接字與 can0 綁定 //定義接收規(guī)則,只接收表示符等于 0x11 的報文 rfilter[0].can_id = 0x11; rfilter[0].can_mask = CAN_SFF_MASK; //設(shè)置過濾規(guī)則 setsockopt(fd, SOL_CAN_RAW, CAN_RAW_FILTER, &rfilter, sizeof(rfilter)); while(1) { nbytes = read(fd, &frame, sizeof(frame)); //接收報文 //顯示報文 if(nbytes > 0) { printf("ID=0x%X DLC=%d data[0]=0x%X\n", frame.can_id, frame.can_dlc, frame.data[0]); } } close(fd); return 0; }
-
Linux
+關(guān)注
關(guān)注
88文章
11760瀏覽量
219036 -
瑞芯微
+關(guān)注
關(guān)注
27文章
794瀏覽量
54321 -
EASY-EAI靈眸科技
+關(guān)注
關(guān)注
4文章
67瀏覽量
3617 -
RV1126B
+關(guān)注
關(guān)注
0文章
54瀏覽量
182
發(fā)布評論請先 登錄
瑞芯微(EASY EAI)RV1126B 音頻輸入
瑞芯微(EASY EAI)RV1126B PWM使用
如何用瑞芯微RV1126B核心板贏得AI紅利?
【EASY EAI Nano-TB(RV1126B)開發(fā)板試用】+初識篇
【EASY EAI Nano-TB(RV1126B)開發(fā)板試用】命令行功能測試-shell腳本進行IO控制-燈閃
【EASY EAI Nano-TB(RV1126B)開發(fā)板試用】命令行功能測試-shell腳本進行IO控制-紅綠燈項目
【EASY EAI Nano-TB(RV1126B)開發(fā)板試用】命令行功能測試-shell腳本進行IO控制-紅綠燈按鈕項目
請問各位大佬,如何解決,瑞芯微 RV1126B 使用 mpp 自帶工具 調(diào)試時,內(nèi)核直接報錯崩潰!
【EASY EAI Nano-TB(RV1126B)開發(fā)板試用】+1、開箱上電
【EASY EAI Nano-TB(RV1126B)開發(fā)板試用】介紹、系統(tǒng)安裝
RV1126系列選型指南:從RV1126到RV1126B,一文看懂升級差異
【免費試用】EASY EAI Nano-TB(RV1126B)開發(fā)套件評測
瑞芯微RV1126B特性概述
替代升級實錘!實測RV1126B,CPU性能吊打RV1126
瑞芯微(EASY EAI)RV1126B 人體關(guān)鍵點識別
瑞芯微(EASY EAI)RV1126B CAN使用
評論