隨著汽車和航空航天領域嵌入式系統(tǒng)的飛速發(fā)展,系統(tǒng)內(nèi)通信對數(shù)據(jù)帶寬和有效載荷容量的需求日益增長。帶有可變數(shù)據(jù)速率的控制器局域網(wǎng)絡(CAN FD)協(xié)議通過增強經(jīng)典 CAN 總線的功能,成功應對了這一挑戰(zhàn)。AS32S601 作為國科安芯推出的一款高性能 32 位 RISC-V 微控制器。盡管 CAN FD 將單幀的最大載荷擴展至 64 字節(jié)^^^^^^^^,但許多應用場景,如無線固件升級(OTA)、高分辨率傳感器數(shù)據(jù)流傳輸以及高級診斷等,仍需傳輸遠超此限制的數(shù)據(jù)塊。
本文旨在為在 AS32S601 微控制器上實現(xiàn)穩(wěn)健的多幀數(shù)據(jù)傳輸解決方案提供一份全面的技術指南,討論內(nèi)容覆蓋了 CAN FD 的核心概念、AS32S601 外設的架構、包括接收狀態(tài)機在內(nèi)的詳細軟件實現(xiàn)策略,以及確保實時性能和系統(tǒng)可靠性的關鍵系統(tǒng)級注意事項。
一、核心機制設計
CAN幀主要包含兩個主要部分:仲裁階段和數(shù)據(jù)階段。在傳統(tǒng)CAN中,全幀以一個固定的比特率發(fā)送。在CAN FD中,如果啟用了BRS位,數(shù)據(jù)階段則以更高的比特率發(fā)送。這種較高的比特率通常是標稱比特率的2至8倍。CAN幀中不包含任何表明比特率具體值的內(nèi)容。

就像在傳統(tǒng)CAN中一樣,比特率作為系統(tǒng)設計的一部分是固定值,總線上的所有設備在發(fā)送和接收數(shù)據(jù)之前都必須知道該值。只是對于CAN FD,如果BRS處于激活狀態(tài),那您必須知道標稱比特率和數(shù)據(jù)比特率。

傳統(tǒng)CAN最大8字節(jié),而CAN FD支持單幀從8字節(jié)擴展至64字節(jié)(DLC編碼對應12/16/20/24/32/48/64字節(jié))。

CAN FD協(xié)議本身單幀最大支持64字節(jié)數(shù)據(jù),若需處理超過64字節(jié)的數(shù)據(jù),需通過以下方式實現(xiàn):
該原理設計通過分段速率控制與協(xié)議層優(yōu)化,在保持CAN總線非破壞性仲裁優(yōu)勢的同時,實現(xiàn)吞吐量5-15倍提升。實際部署時需注意電磁兼容性設計,特別是高速率下的信號完整性。
實現(xiàn)方法:將大數(shù)據(jù)包按CAN FD支持的DLC分段,發(fā)送端拆分數(shù)據(jù),接收端重組。
二、多幀傳輸協(xié)議
在實際應用中,當數(shù)據(jù)量超過單幀CAN FD的最大容量時,就需要采用多幀處理機制。這一機制通常包括首幀(First Frame, FF)、連續(xù)幀(Consecutive Frame, CF)和流控幀(Flow Control, FC)。首幀負責攜帶數(shù)據(jù)總長度和首段數(shù)據(jù),通知接收方開始接收;連續(xù)幀則按照順序傳輸剩余數(shù)據(jù)。流控幀由接收方發(fā)送,用于控制發(fā)送節(jié)奏,包含連續(xù)接收最大幀數(shù)(Block Size, BS)和幀間最小間隔時間(STmin)等參數(shù)。
[首幀F(xiàn)F] → [流控FC] → [連續(xù)幀CF] → ... → [CRC校驗]
接收方通過流控幀(FC)指定:
- 單幀(Single Frame):≤64字節(jié)直接傳輸
- 超時重傳(默認300ms)
- CRC校驗失敗觸發(fā)自動重傳
該代碼實現(xiàn)包含以下核心功能:
- 支持ISO-TP協(xié)議標準的多幀拆分與重組
- 采用狀態(tài)機管理接收流程,處理首幀(FF)和連續(xù)幀(CF)
- 實現(xiàn)序列號校驗和自動重傳機制
- 兼容單幀傳輸(≤64字節(jié))和多幀傳輸(>64字節(jié))場景
#include < string.h >
#define CANFD_MAX_DLC 64
#define ISO_TP_PCI_TYPE_FF 0x10 // 首幀標識
#define ISO_TP_PCI_TYPE_CF 0x20 // 連續(xù)幀標識
typedef **struct** {
uint8_t data[CANFD_MAX_DLC];
} CANFD_Frame;
// 發(fā)送多幀數(shù)據(jù)
**void** send_multiframe(CANFD_TypeDef* CANFDx, uint8_t *data, uint16_t len) {
CANFD_Frame frame;
uint8_t chunk_size=0;
uint8_t seq=0;
uint16_t total_len = len;
// 首幀發(fā)送
**if** (len > CANFD_MAX_DLC - 2)
{
frame.data[0] = ISO_TP_PCI_TYPE_FF
frame.data[1] = len & 0xFF;
memcpy(&frame.data[2], data, CANFD_MAX_DLC - 2);
CANFD_Transmit(CANFDx, TB1, frame.data, CANFD_MAX_DLC);
// 連續(xù)幀發(fā)送
for(int i=0; i< total_len; i+=64)
{
uint8_t chunk_size = (total_len-i) > 64 ? 64 : (total_len-i);
frame.data[0] = ISO_TP_PCI_TYPE_CF| Seq;
memcpy(&frame.data[1], data[chunk_size-1], chunk_size);
CANFD_Transmit(CANFDx, TB1, frame.data, chunk_size);
Seq+=1;
}
}
// 單幀發(fā)送
**else** {
memcpy(frame.data, data, len);
CANFD_Transmit(CANFDx, TB1, frame.data, len);
}
}
// 接收狀態(tài)機
typedef **enum** {
IDLE,
RECEIVING_FF,
RECEIVING_CF
} RxState;
typedef **struct** {
uint8_t buffer[4096];
uint16_t total_len;
uint16_t received;
uint8_t expected_seq;
RxState state;
} CANFD_RxHandler;
**void** process_canfd_frame(CANFD_TypeDef* CANFDx, CANFD_Frame *frame) {
uint8_t data_len =0;
data_len = CANFD_GetReceiveData(CANFD3, frame.data);
uint8_t pci_type = frame- >data[0] & 0xF0;
**switch** (handler- >state) {
**case** IDLE:
**if** (pci_type == ISO_TP_PCI_TYPE_FF) {
handler- >total_len = ((frame- >data[0] & 0x0F) < < 8) | frame- >data[1];
memcpy(handler- >buffer, &frame- >data[2], CANFD_MAX_DLC- 2);
handler- >received = CANFD_MAX_DLC- 2;
handler- >expected_seq = 1;
handler- >state = RECEIVING_CF;
}
**break** ;
**case** RECEIVING_CF:
**if** (pci_type == ISO_TP_PCI_TYPE_CF &&
((frame- >data[0] & 0x0F) == handler- >expected_seq)) {
memcpy(handler- >buffer + handler- >received,
&frame- >data[1], data_len);
handler- >received += data_len;
handler- >expected_seq = (handler- >expected_seq + 1) % 16;
**if** (handler- >received >= handler- >total_len) {
// 完整數(shù)據(jù)接收完成
handler- >state = IDLE;
}
}
**break** ;
}
}
三、定時器模擬多線程任務處理:
中斷標志管理:
can_interrupt_flag 為CAN硬件中斷標志,由CAN接收中斷服務觸發(fā)。
定時器1功能:
每100ms輪詢can_interrupt_flag
檢測到標志位后設置processing_interrupt阻止其他任務
模擬中斷處理過程(此處用usleep模擬處理時間)
定時器2功能:
每1秒嘗試執(zhí)行任務
通過檢查processing_interrupt決定是否執(zhí)行任務
[CAN_ISR] 中斷觸發(fā),設置標志位
[Timer1] 檢測到中斷,暫停其他任務
[Timer2] 任務暫停...
[Timer2] 任務暫停...
[Timer1] 中斷處理完成,恢復任務
[Timer2] 執(zhí)行常規(guī)任務
#include < stdio.h >
#include < stdlib.h >
// 全局標志位
volatile **int** can_interrupt_flag = 0;
volatile **int** processing_interrupt = 0;
// 模擬CAN中斷服務程序(實際應由硬件觸發(fā))
**void** CANFD3_IRQ_Handler()
{
can_interrupt_flag = 1;
printf("[CAN_ISR] 中斷觸發(fā),設置標志位n");
}
// 定時器1線程:檢測CAN中斷標志(每500ms檢查)
**void** timer1_thread( **void** )
{
**if** (can_interrupt_flag) {
processing_interrupt = 1;
printf("[Timer1] 檢測到中斷,暫停其他任務n");
can_buffer_count();
can_interrupt_flag = 0; // 清除中斷標志
processing_interrupt = 0; // 允許恢復任務
printf("[Timer1] 中斷處理完成,恢復任務n");
}
**return** NULL;
}
// 定時器2線程:執(zhí)行其他任務(每1秒執(zhí)行)
**void** timer2_thread( **void** ) {
usleep(1000000); // 1000ms間隔
**if** (!processing_interrupt) {
printf("[Timer2] 執(zhí)行常規(guī)任務n");
} **else** {
printf("[Timer2] 任務暫停...n");
}
**return** NULL;
}
**int** main {
// 創(chuàng)建兩個定時器任務
TIM1_Config(99,0,0);
TIM2_Config(99,0,0);
**while** (1)
{
timer1_thread();
timer2_thread();
}
四、關鍵特性說明:
- 線程安全設計:通過volatile關鍵字確保中斷與主程序間的數(shù)據(jù)可見性。
- 動態(tài)長度校驗:在讀取時驗證數(shù)據(jù)長度是否符合預期。
- 高效內(nèi)存管理:環(huán)形緩沖區(qū)避免內(nèi)存碎片,適合嵌入式環(huán)境。
- 狀態(tài)檢測機制:通過is_full標志避免緩沖區(qū)溢出。
- 擴展性設計:可通過修改CAN_BUF_SIZE適應不同數(shù)據(jù)量需求。
實際應用時需配合CAN中斷服務程序(ISR)調(diào)用can_buffer_put(),在主循環(huán)中處理完整數(shù)據(jù)幀。對于高可靠性場景,建議增加錯誤幀處理和BUS OFF狀態(tài)恢復機制。
五、物理層要求:
- 使用ASM1042等CANFD收發(fā)器芯片
- 分支長度<1米,終端電阻120Ω
- 采樣點設置在75%-82%范圍
六、典型應用場景
- 車載網(wǎng)絡升級
在車載網(wǎng)絡中,CAN FD主要用于域控制器間的大數(shù)據(jù)傳輸,如ADAS(Advanced Driver Assistance Systems)傳感器數(shù)據(jù)的高效傳輸。通過CAN FD網(wǎng)橋,它能夠實現(xiàn)與傳統(tǒng)CAN網(wǎng)絡的兼容,使得車輛在升級過程中無需全面替換現(xiàn)有網(wǎng)絡架構。然而,在實際部署時,需要特別注意電磁兼容性設計,尤其是高速率下的信號完整性,以避免數(shù)據(jù)傳輸錯誤和系統(tǒng)故障。
- 航天領域適配
CAN FD協(xié)議滿足了衛(wèi)星遙測數(shù)據(jù)高速傳輸?shù)男枨螅?Mbps+64字節(jié)幀)。其高可靠性和低延遲特性,使得衛(wèi)星能夠及時、準確地將遙測數(shù)據(jù)傳輸回地面站。在這一領域,CAN FD通常與高性能的CAN FD收發(fā)器芯片配合使用,如ASM1042等,以確保數(shù)據(jù)傳輸?shù)姆€(wěn)定性和準確性。同時,為了適應航天環(huán)境的特殊要求,還需要對CAN FD網(wǎng)絡進行嚴格的可靠性測試和驗證。
審核編輯 黃宇
-
微控制器
+關注
關注
48文章
8309瀏覽量
163574 -
數(shù)據(jù)傳輸
+關注
關注
9文章
2180瀏覽量
67376 -
CANFD
+關注
關注
0文章
105瀏覽量
5862
發(fā)布評論請先 登錄
實時視頻數(shù)據(jù)傳輸中接收端緩存區(qū)的設計
ROHM高速數(shù)據(jù)傳輸方式控制器
以太網(wǎng)控制器控制模塊數(shù)據(jù)傳輸控制代碼實現(xiàn)
下位機與PC機之間的數(shù)據(jù)傳輸問題解方法
請問連續(xù)多包數(shù)據(jù)的數(shù)據(jù)傳輸速度超過DSP的數(shù)據(jù)處理速度怎么解決?
DSP 內(nèi)嵌CAN 控制器的郵箱方式數(shù)據(jù)傳輸
實時視頻數(shù)據(jù)傳輸中接收端緩存區(qū)的設計
數(shù)據(jù)傳輸速率是什么意思
基于PCI總線的數(shù)據(jù)傳輸系統(tǒng)
ARM實現(xiàn)無線數(shù)據(jù)傳輸系統(tǒng)
DM642圖像數(shù)據(jù)傳輸的優(yōu)化
基于AS32S601微控制器的CANFD多幀數(shù)據(jù)傳輸處理方法研究
評論