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

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

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

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