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

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

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

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