1.測試準備工作
1.1. 開發板硬件資源介紹:
1.2. 首先通過國民技術的技術資料網址,用瀏覽器打開后如下所示:
選擇下載了N32L40XXX_V2.1.0.zip資料包后,解壓得到官方Demo,數據手冊,評估板,軟件開發套件,應用筆記,測試資料等等。如下圖所示:
1.3. 引腳資源分配介紹
本例中CAN的引腳使用GPIOB的引腳8和引腳9配置CAN的接收和發送引腳。將GPIOC的引腳11和引腳10配置為USART3的接收和發送引腳,通過USB轉UART模塊,晶振等公共資源就不一一介紹。
1.4. 功能模塊介紹
本方案從軟件上主要分為三部份,CAN模塊,串口通訊模塊和日志輸出模塊。
CAN模塊:主要負責CAN報文的收發,報文解析。
串口通訊模塊:將CAN模塊接收的CAN報文傳輸至上位機,將上位機發送的CAN報文轉給CAN模塊發送到CAN網絡中。
日志輸出模塊:輸出系統運行過程中的日志。
1.5. 性能指標
本案例測試中,將測試波特率為500kbps,250kbps,125kbps三個波特率,具體指標為:
錯誤率:幀錯誤率:99%
采樣率:85%
連續測試時長:72小時
2.環境搭建及創建工程。
2.1.首先到RT-Thread官方網站下載RT-Thread Studio,并安裝好,啟動RT-Thread Studio.點擊SDK安裝按鈕,彈出下圖所示界面。
2.3.還需要安裝PyOCD,防止在下載程序時報錯
2.4.在文件選擇新建,由于不支持RT-Thread Nano,所以只能選擇RT-Thread項目。
2.5. 在彈出菜單中,選擇項目存放路徑,輸入項目名,選擇基于開發板,并選擇本次的測試開發板,點擊確定,就創建了基于模板的工程。
2.6.在項目內的RT-Thread Settings中打開CAN模塊功能,串口1用于日志打印。
3.RTThread的CAN驅動機制介紹
3.1. rtconfig.h配置文件介紹
在RT-Thread Setting中,打開USART3和CAN后,在rtconfig.h配置文件中可以看到定義了BSP_USING_CAN,RT_USING_PIN,RT_USING_SERIAL宏,表示啟動了CAN驅動與設備。
3.2.CAN Drive 驅動介紹,
3.2.1.RT-Thread提供I/O設備管理接口來訪問CAN硬件控制,接口如下:
3.2.2.通過INIT_BOARD_EXPORT將CAN的硬件驅動加載到初始化列表中,通過rt_hw_can_register將CAN注冊到RT-Thread的設備列表中。
3.2.3.在調用rt_device_register函數,將設備注冊到OS的設備列表中。
3.2.4.CAN波特率配置
3.3.測試代碼
#include
#include
#include
#include
/* defined the LED3 pin: PB5 /
#define LED3_PIN GET_PIN(B, 5)
#define LED2_PIN GET_PIN(B, 4)
int main(void)
{
/ set LED3 pin mode to output /
rt_pin_mode(LED3_PIN, PIN_MODE_OUTPUT);
rt_pin_mode(LED2_PIN, PIN_MODE_OUTPUT);
thread_CanDriver_Entry(RT_NULL);
while (1)
{
rt_pin_write(LED2_PIN, PIN_LOW);
rt_pin_write(LED3_PIN, PIN_HIGH);
rt_thread_mdelay(500);
rt_pin_write(LED3_PIN, PIN_LOW);
rt_pin_write(LED2_PIN, PIN_HIGH);
rt_thread_mdelay(500);
}
}
#include
/
Copyright (c) 2006-2021, RT-Thread Development Team
SPDX-License-Identifier: Apache-2.0
Change Logs:
Date Author Notes
2023-04-22 chunyang.jiang the first version
/
#include "rtdevice.h"
#include
#include
#include
#define CAN_DEV_NAME "bxcan" / CAN 設備名稱 /
struct rt_semaphore rx_sem; / 用于接收消息的信號量 /
static rt_device_t can_device; / CAN 設備名稱 */
struct rt_can_msg can_msg = {0};
struct rt_can_msg canrx_msg = {0};
static rt_thread_t thread_rec;
static rt_thread_t thread_send;
static void thread_can_send(void *parameter);
static void thread_can_Receiver(void *parameter);
static rt_err_t Can_ReceiverMessage_Call(rt_device_t dev, rt_size_t size)
{
rt_sem_release(&rx_sem);
// rt_kprintf("Can Receiver message!rn");
return RT_EOK;
}
static void thread_can_Receiver(void parameter)
{
rt_err_t ret;
int i;
/ 設置接收回調函數 /
rt_device_set_rx_indicate(can_device, Can_ReceiverMessage_Call);
/
struct rt_can_filter_item items[5] =
{
{0x100, 0, 0, 0, 0x700, RT_NULL},
{0x300, 0, 0, 0, 0x700, RT_NULL},
{0x211, 0, 0, 0, 0x7ff, RT_NULL},
{0x486, 0, 0, 0, 0x7ff, RT_NULL},
{0x555, 0, 0, 0, 0x7ff, 7}
};
struct rt_can_filter_config cfg = {5,1,items};
ret = rt_device_control(can_device,RT_CAN_CMD_SET_FILTER,&cfg);
RT_ASSERT(ret == RT_EOK);
*/
while(1)
{
canrx_msg.hdr = -1;
rt_sem_take(&rx_sem, RT_WAITING_FOREVER);
rt_device_read(can_device, 0, &canrx_msg, sizeof(canrx_msg));
rt_kprintf("ID:%x",canrx_msg.id);
for(i=0; i <8; i++)
{
rt_kprintf(" %2x",canrx_msg.data[i]);
}
rt_kprintf("rn");
}
}
static void thread_can_send(void *parameter)
{
rt_size_t res;
static uint32_t i = 0;
static uint32_t a = 0xFFFFFFFF;
while(1)
{
i ++;
a --;
can_msg.id = 0x78;
can_msg.ide = RT_CAN_STDID;
can_msg.rtr = RT_CAN_DTR;
can_msg.len = 0x08;
can_msg.data[0] = i;
can_msg.data[1] = (i>>8);
can_msg.data[2] = (i>>16);
can_msg.data[3] = (i>>24);
can_msg.data[4] = 0x05;
can_msg.data[5] = 0x06;
can_msg.data[6] = 0x07;
can_msg.data[7] = 0x08;
res = rt_device_write(can_device, 0, &can_msg, sizeof(can_msg));
if(res == 0)
{
// rt_kprintf("Can Send a frame failed!rn");
}
else
{
// rt_kprintf("Can Send a frame success!rn");
}
can_msg.id = 0x778;
can_msg.ide = RT_CAN_STDID;
can_msg.rtr = RT_CAN_DTR;
can_msg.len = 0x08;
can_msg.data[0] = a;
can_msg.data[1] = (a>>8);
can_msg.data[2] = (a>>16);
can_msg.data[3] = (a>>24);
can_msg.data[4] = 0x05;
can_msg.data[5] = 0x06;
can_msg.data[6] = 0x07;
can_msg.data[7] = 0x08;
res = rt_device_write(can_device, 0, &can_msg, sizeof(can_msg));
if(res == 0)
{
// rt_kprintf("Can Send a frame failed!rn");
}
else
{
// rt_kprintf("Can Send a frame success!rn");
}
can_msg.id = 0x508;
can_msg.ide = RT_CAN_STDID;
can_msg.rtr = RT_CAN_DTR;
can_msg.len = 0x08;
can_msg.data[0] = 8;
can_msg.data[1] = 8;
can_msg.data[2] = 8;
can_msg.data[3] = 8;
can_msg.data[4] = 0x05;
can_msg.data[5] = 0x06;
can_msg.data[6] = 0x07;
can_msg.data[7] = 0x08;
res = rt_device_write(can_device, 0, &can_msg, sizeof(can_msg));
if(res == 0)
{
// rt_kprintf("Can Send a frame failed!rn");
}
else
{
// rt_kprintf("Can Send a frame success!rn");
}
rt_thread_mdelay(1);
}
}
int thread_CanDriver_Entry(void *parameter)
{
static char can_name[RT_NAME_MAX];
static uint32_t can_name_len = 0;
rt_err_t ret;
can_name_len = sizeof(CAN_DEV_NAME);
rt_strncpy(can_name, CAN_DEV_NAME, RT_NAME_MAX);
/ 在設備列表中查找設備 /
can_device = rt_device_find(can_name);
if(!can_device)
{
rt_kprintf("find %s failed!rn",can_name);
return RT_ERROR;
}
/ 初始化信號量 /
rt_sem_init(&rx_sem, "rx_sem", 0 ,RT_IPC_FLAG_FIFO);
/ 打開設備 /
ret = rt_device_open(can_device, RT_DEVICE_FLAG_INT_TX | RT_DEVICE_FLAG_INT_RX);
RT_ASSERT(ret == RT_EOK);
thread_send = rt_thread_create("thread_send", thread_can_send,RT_NULL, 1024,25,1);
if(thread_send == NULL)
{
rt_kprintf("Create Can Send failed!rn");
return RT_ERROR;
}
else
{
rt_thread_startup(thread_send);
}
thread_rec = rt_thread_create("thread_Receiver", thread_can_Receiver,RT_NULL, 1024,25,1);
if(thread_send == NULL)
{
rt_kprintf("Create Can Send failed!rn");
return RT_ERROR;
}
else
{
rt_thread_startup(thread_rec);
}
}
MSH_CMD_EXPORT(thread_CanDriver_Entry, can device Driver sample);
4.測試效果圖
測試效果圖連接:
在測試時,測試500Kbps,250bps,125bps波特率,報文發送時間間隔為10ms,開發板發送3幀,接收一幀(由于測試CAN只支持1幀發送)
5.測試總結
在測試中發現在沒有安裝PyOCD,無法燒錄的問題,同時還發現在發送CAN數據時,執行res = rt_device_write(can_device, 0, &can_msg, sizeof(can_msg));發送一幀CAN數據時,通過CAN測試盒,明顯看到有報文發出,但返回狀態一直為0,于是跟蹤測試后發現在等待CAN發送后,沒有對發送結果進行返回導致,于是修改代碼,如下圖所示:
另外也發現如果CAN的TX,RX不接CAN驅動器時,執行發送數據后,代碼會進入死循環。這個問題是驅動機制導致,如果遇到這個問題可以查一下CAN驅動接接線,驅動器是否工作。
總的說來,本次測試挺順利的,除了部分Bug外,CAN能夠實現10ms多幀發送,并同時處理接收報文。滿足日常設計中的CAN通訊需求。
-
驅動器
+關注
關注
53文章
8260瀏覽量
146647 -
串口通訊
+關注
關注
1文章
260瀏覽量
24976 -
上位機
+關注
關注
27文章
944瀏覽量
54895 -
CAN模塊
+關注
關注
0文章
24瀏覽量
8772 -
RT-Thread
+關注
關注
31文章
1296瀏覽量
40245
發布評論請先 登錄
相關推薦
評論