STM32中的CAN總線詳解:從原理到實戰

前言:為什么CAN總線是嵌入式通信的"硬通貨"?

在嵌入式通信領域,CAN(Controller Area Network)總線憑借其高可靠性實時性多節點通信能力,成為汽車電子、工業控制、智能設備等領域的"標配"。想象一下:一輛汽車中有幾十個ECU(電子控制單元),從發動機控制到車窗調節,都需要實時交換數據——CAN總線正是為這種多節點、高干擾環境設計的通信協議。

STM32幾乎全系列都集成了高性能CAN控制器(bxCAN),支持標準幀/擴展幀、中斷/DMA傳輸、靈活的濾波功能,完美適配工業級應用。本文將從CAN總線的基本原理講起,深入解析STM32的CAN外設結構、配置方法、通信流程和實戰案例,幫助你徹底掌握STM32 CAN通信開發。

一、CAN總線基礎:為什么它能在惡劣環境中可靠通信?

在學習STM32的CAN外設前,我們需要先理解CAN總線的核心特性——這是掌握后續內容的基礎。

1.1 CAN總線的核心優勢

CAN總線由博世公司在1980年代為汽車電子開發,經過30多年發展,已成為國際標準(ISO 11898),其核心優勢包括:

  • 多主通信:總線上的每個節點都可主動發送數據,無需中央控制器,避免單點故障;
  • 非破壞性仲裁:多個節點同時發送時,通過ID優先級仲裁,優先級高的節點繼續發送,低優先級的自動退讓,不會破壞數據;
  • 差分信號傳輸:通過CAN_H和CAN_L兩根線傳輸差分信號,抗電磁干擾能力極強(適合工業和汽車環境);
  • 遠距離傳輸:速率125kbps時傳輸距離可達500m,滿足大多數工業場景;
  • 錯誤檢測與自動重傳:內置CRC校驗、位填充、應答機制,確保數據可靠傳輸,錯誤幀會自動重傳。

1.2 CAN總線的基本概念

(1)幀結構:CAN數據的"包裝格式"

CAN總線通過"幀"傳輸數據,最常用的是數據幀(用于傳輸有效數據),其結構如下(標準幀):

字段長度(位)功能描述
起始位1幀開始標志(低電平)
仲裁11包含標準ID(11位),用于仲裁
控制場6包含數據長度(DLC,0~8字節)
數據場0~64有效數據(0~8字節,擴展幀支持更多)
CRC場16循環冗余校驗,檢測數據錯誤
應答場2接收節點確認收到正確數據
結束位7幀結束標志(高電平)

擴展幀與標準幀的區別是仲裁場包含29位ID(11位標準ID+18位擴展ID),支持更多節點和更復雜的ID規劃。

(2)位時序:如何保證不同節點的同步?

CAN總線是異步通信,節點間沒有統一的時鐘線,通過位時序實現同步。每個位被分為4個時間段:

  • 同步段(SS):用于同步各節點時鐘,長度1TQ(Time Quantum,時間量子);
  • 傳播段(PS):補償信號傳輸延遲,長度1~8TQ;
  • 相位緩沖段1(PBS1):可延長,用于重同步,長度1~8TQ;
  • 相位緩沖段2(PBS2):等于PBS1或信號傳播時間,長度1~8TQ。

波特率計算:波特率 = 1 / (總TQ),其中總TQ = SS + PS + PBS1 + PBS2(通常總TQ=8~25)。

例如:STM32的CAN時鐘為36MHz,若總TQ=18,則波特率=36MHz / 18 = 2Mbps。

1.3 CAN節點的硬件組成

一個完整的CAN節點包括:

  • MCU中的CAN控制器(如STM32的bxCAN):負責幀的組裝、發送、接收和錯誤檢測;
  • CAN收發器(如SN65HVD230):將控制器輸出的TTL電平轉換為CAN總線的差分信號(CAN_H/CAN_L);
  • 終端電阻(120Ω):接在總線兩端,匹配阻抗,防止信號反射。

典型電路:STM32的CAN_TX(如PB6)和CAN_RX(如PB5)連接到SN65HVD230的TXD和RXD,SN65HVD230的CAN_H和CAN_L接總線,兩端各接120Ω電阻。
典型電路

二、STM32的CAN外設:bxCAN控制器的強大之處

STM32的CAN控制器稱為bxCAN(Basic Extended CAN),支持CAN 2.0A/B標準,不同系列(F1/F4/L4)的CAN外設功能略有差異,但核心結構一致。

2.1 bxCAN控制器的核心特性

  • 支持標準幀(11位ID)和擴展幀(29位ID)
  • 3個發送郵箱:可緩存3幀待發送數據,支持優先級發送;
  • 2個接收FIFO:每個FIFO有3級深度,可緩存3幀接收數據,減輕CPU負擔;
  • 靈活的濾波功能:14個濾波器組,支持屏蔽位模式和列表模式,精準過濾目標報文;
  • 多種中斷源:發送完成、接收FIFO滿、錯誤警告等,支持中斷和DMA傳輸;
  • 總線錯誤管理:檢測總線錯誤(位錯誤、CRC錯誤等),自動進入錯誤狀態。

2.2 bxCAN的硬件結構

理解bxCAN的結構有助于后續配置,核心模塊包括:
bxCAN結構示意圖

(1)發送部分:3個發送郵箱

發送郵箱(Tx Mailbox)是發送數據的"緩沖區",每個郵箱包含:

  • 標識符寄存器(TXID):存儲標準/擴展ID;
  • 數據長度和數據寄存器(TXDLR、TXDATA):存儲數據長度和有效數據;
  • 控制寄存器(TXCTRL):配置發送優先級、幀類型等。

發送流程:當郵箱狀態為"空"時,CPU填充郵箱數據,設置"發送請求",CAN控制器會自動 arbitration(仲裁)并發送,發送完成后郵箱狀態變為"空"。

(2)接收部分:2個FIFO + 14個濾波器
  • 接收FIFO:FIFO0和FIFO1,用于緩存接收的有效報文。當FIFO中的報文數達到閾值(如3幀),會觸發中斷;
  • 濾波器組:共14個(STM32F103),每個濾波器可配置為屏蔽位模式(按ID掩碼過濾)或列表模式(精確匹配ID),過濾后的報文才會存入FIFO。
(3)波特率發生器

根據輸入時鐘(APB1時鐘,最高36MHz for F1)和配置的位時序參數(預分頻器、同步段、相位段),生成CAN總線需要的波特率。

三、STM32 CAN配置步驟:從CubeMX到代碼實現

本節以STM32F103C8T6STM32CubeMX 6.6.0為例,結合HAL庫,詳細講解CAN通信的配置流程。

3.1 硬件準備

  • 開發板:STM32F103C8T6最小系統板;STM32F103C8T6最小系統板

  • CAN收發器:TJA1050模塊(帶120Ω終端電阻,可通過跳線選擇);TJA1050模塊

  • 接線:STM32的PA11(CAN_RX)接TJA1050的RXD,PA12(CAN_TX)接TJA1050的TXD,TJA1050的CAN_H和CAN_L接總線(若單節點測試,可短接CAN_H和CAN_L,或接2個節點形成回路)。

3.2 CubeMX配置步驟

步驟1:新建工程,選擇芯片

打開CubeMX,搜索"STM32F103C8T6",創建新工程。

步驟2:配置時鐘樹

CAN外設掛載在APB1總線上,需確保APB1時鐘正確(最高36MHz for F1):

  1. 配置RCC:HSE選擇"Crystal/Ceramic Resonator"(8MHz外部晶振);
  2. 配置PLL:PLLMUL=×9,使系統時鐘=72MHz;
  3. APB1 Prescaler=×2,使APB1時鐘=36MHz(滿足CAN時鐘需求)。
步驟3:配置CAN外設
  1. 引腳配置:在Pinout視圖中,將PA11配置為"CAN_RX",PA12配置為"CAN_TX";
  2. 配置CAN模式:在Configuration→Connectivity→CAN中,設置:
    • Mode:“Normal”(正常模式,收發數據)或"Loopback"(回環模式,用于自測,發送的報文會自己接收);
    • Prescaler(預分頻器):根據波特率需求設置,例如"6"(后續計算波特率);
    • 位時序參數(Bit Timing):
      • Sync Jump Width (SJW):“1tq”;
      • Time Segment 1 (BS1):“8tq”;
      • Time Segment 2 (BS2):“3tq”;
        (總TQ = Prescaler × (SJW+BS1+BS2) = 6×(1+8+3)=72 → 波特率=36MHz/72=500kbps)
步驟4:配置中斷(可選)

若需要通過中斷處理收發,需配置NVIC:

  1. 在Configuration→NVIC中,勾選"CAN_RX0_IRQn"(FIFO0接收中斷)和"CAN_TX_IRQn"(發送完成中斷);
  2. 設置中斷優先級(如搶占優先級1,子優先級0)。
步驟5:生成代碼

設置工程路徑和IDE(如MDK-ARM),點擊"Generate Code"生成初始化代碼。

3.3 HAL庫CAN核心函數解析

生成的代碼中,CAN相關核心函數位于can.cstm32f1xx_hal_can.h,主要包括:

(1)初始化函數:MX_CAN_Init()

自動生成的初始化函數,配置CAN模式、波特率、濾波器等(后續需手動完善濾波器配置):

CAN_HandleTypeDef hcan;static void MX_CAN_Init(void)
{hcan.Instance = CAN1;hcan.Init.Prescaler = 6;hcan.Init.Mode = CAN_MODE_NORMAL; // 正常模式hcan.Init.SyncJumpWidth = CAN_SJW_1TQ;hcan.Init.TimeSeg1 = CAN_BS1_8TQ;hcan.Init.TimeSeg2 = CAN_BS2_3TQ;hcan.Init.TimeTriggeredMode = DISABLE;hcan.Init.AutoBusOff = ENABLE; // 自動退出總線關閉狀態hcan.Init.AutoRetransmission = ENABLE; // 自動重傳hcan.Init.ReceiveFifoLocked = DISABLE;hcan.Init.TransmitFifoPriority = DISABLE;if (HAL_CAN_Init(&hcan) != HAL_OK){Error_Handler();}
}
(2)濾波器配置函數:CAN_Filter_Config()

濾波器需要手動配置,用于過濾目標ID的報文,示例:

void CAN_Filter_Config(void)
{CAN_FilterTypeDef can_filter_st;can_filter_st.FilterActivation = ENABLE; // 使能濾波器can_filter_st.FilterMode = CAN_FILTERMODE_IDMASK; // 屏蔽位模式can_filter_st.FilterScale = CAN_FILTERSCALE_32BIT; // 32位濾波器// 配置濾波器ID和掩碼(只接收ID=0x123的標準幀)can_filter_st.FilterIdHigh = 0x123 << 5; // 標準ID的高16位(左移5位是因為標準ID占11位)can_filter_st.FilterIdLow = 0x0000;can_filter_st.FilterMaskIdHigh = 0xFFF << 5; // 掩碼高16位(全1表示嚴格匹配)can_filter_st.FilterMaskIdLow = 0x0000;can_filter_st.FilterBank = 0; // 使用第0個濾波器組can_filter_st.FilterFIFOAssignment = CAN_FILTER_FIFO0; // 匹配的報文存入FIFO0if(HAL_CAN_ConfigFilter(&hcan, &can_filter_st) != HAL_OK){Error_Handler();}
}

濾波器配置說明

  • 屏蔽位模式:FilterId是目標ID,FilterMaskId是掩碼,掩碼為1的位必須嚴格匹配,為0的位可忽略;
  • 列表模式:FilterId是需要匹配的ID列表,只有完全匹配的ID才會被接收;
  • 32位/16位模式:32位模式可同時過濾標準幀和擴展幀,16位模式適合單獨過濾。
(3)發送函數:CAN_Send_Message()

封裝發送流程,填充報文并啟動發送:

uint8_t CAN_Send_Message(uint32_t id, uint8_t *data, uint8_t len)
{CAN_TxHeaderTypeDef tx_header;uint8_t tx_mailbox; // 存儲使用的發送郵箱編號// 配置發送頭部tx_header.StdId = id; // 標準IDtx_header.ExtId = 0; // 擴展ID(不使用)tx_header.RTR = CAN_RTR_DATA; // 數據幀tx_header.IDE = CAN_ID_STD; // 標準幀tx_header.DLC = len; // 數據長度(0~8)tx_header.TransmitGlobalTime = DISABLE;// 等待發送郵箱空閑if(HAL_CAN_GetTxMailboxesFreeLevel(&hcan) == 0){return 1; // 郵箱滿,發送失敗}// 發送數據if(HAL_CAN_AddTxMessage(&hcan, &tx_header, data, &tx_mailbox) != HAL_OK){return 2; // 發送失敗}return 0; // 發送成功
}
(4)接收函數:CAN_Receive_Message()

從FIFO接收報文(查詢方式):

uint8_t CAN_Receive_Message(uint32_t *id, uint8_t *data, uint8_t *len)
{CAN_RxHeaderTypeDef rx_header;// 檢查FIFO0是否有數據if(HAL_CAN_GetRxMessage(&hcan, CAN_RX_FIFO0, &rx_header, data) != HAL_OK){return 1; // 接收失敗}*id = rx_header.StdId; // 獲取接收的ID*len = rx_header.DLC; // 獲取數據長度return 0; // 接收成功
}
(5)中斷服務函數

若使用中斷接收,需實現中斷服務函數和回調函數:

// FIFO0接收中斷服務程序
void CAN1_RX0_IRQHandler(void)
{HAL_CAN_IRQHandler(&hcan);
}// 接收回調函數
void HAL_CAN_RxFifo0MsgPendingCallback(CAN_HandleTypeDef *hcan)
{uint32_t id;uint8_t data[8], len;// 接收數據if(CAN_Receive_Message(&id, data, &len) == 0){// 處理接收的數據(如打印)printf("收到ID:0x%X, 數據:", id);for(uint8_t i=0; i<len; i++){printf("%02X ", data[i]);}printf("\r\n");}
}

四、實戰案例:STM32 CAN節點通信測試

本節通過兩個案例(回環測試和雙節點通信),驗證CAN配置的正確性。

4.1 回環模式測試(單節點)

回環模式下,STM32發送的CAN報文會被自己接收,無需外部節點,適合調試:

步驟1:修改CAN模式為回環

MX_CAN_Init()中,將hcan.Init.Mode改為CAN_MODE_LOOPBACK

步驟2:主函數代碼
int main(void)
{HAL_Init();SystemClock_Config();MX_GPIO_Init();MX_USART1_UART_Init(); // 初始化串口(用于打印信息)MX_CAN_Init();// 配置濾波器CAN_Filter_Config();// 啟動CANif(HAL_CAN_Start(&hcan) != HAL_OK){Error_Handler();}// 使能FIFO0接收中斷if(HAL_CAN_ActivateNotification(&hcan, CAN_IT_RX_FIFO0_MSG_PENDING) != HAL_OK){Error_Handler();}uint8_t send_data[8] = {0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88};uint8_t send_cnt = 0;while (1){// 每1秒發送一次數據if(send_cnt >= 100){if(CAN_Send_Message(0x123, send_data, 8) == 0){printf("發送成功: ID=0x123, 數據:11 22 33 44 55 66 77 88\r\n");}else{printf("發送失敗\r\n");}send_cnt = 0;}HAL_Delay(10);send_cnt++;}
}
測試結果

程序運行后,串口會打印"發送成功"和"收到數據"的信息,說明回環通信正常。

4.2 雙節點通信(多節點)

準備兩個STM32節點(Node A和Node B),配置相同波特率(500kbps),實現雙向通信:

  • Node A:發送ID=0x123的報文,接收ID=0x456的報文;
  • Node B:發送ID=0x456的報文,接收ID=0x123的報文。
Node A核心代碼(發送0x123,接收0x456)
// 濾波器配置(接收0x456)
can_filter_st.FilterIdHigh = 0x456 <<5;
can_filter_st.FilterMaskIdHigh = 0xFFF<<5;// 主循環發送0x123
while(1)
{CAN_Send_Message(0x123, send_data, 8);HAL_Delay(1000);
}
Node B核心代碼(發送0x456,接收0x123)
// 濾波器配置(接收0x123)
can_filter_st.FilterIdHigh = 0x123 <<5;
can_filter_st.FilterMaskIdHigh = 0xFFF<<5;// 主循環發送0x456
while(1)
{CAN_Send_Message(0x456, send_data, 8);HAL_Delay(1000);
}
測試結果

兩個節點通過CAN總線連接后,Node A會收到Node B發送的0x456報文,Node B會收到Node A發送的0x123報文,實現雙向通信。

五、CAN高級特性:中斷、DMA與錯誤處理

5.1 中斷與DMA:提高通信效率

  • 中斷方式:適合報文數量少、實時性要求高的場景,接收/發送完成后立即觸發中斷,CPU及時處理;
  • DMA方式:適合大量報文傳輸,通過DMA直接將數據搬運到內存,減少CPU干預(僅部分STM32系列支持,如F4)。

中斷配置補充:除了接收FIFO中斷,還可配置以下中斷:

  • CAN_IT_TX_MAILBOX_EMPTY:發送郵箱空(可用于連續發送);
  • CAN_IT_ERROR:總線錯誤(用于錯誤處理);
  • CAN_IT_WAKEUP:休眠喚醒(低功耗場景)。

5.2 CAN錯誤處理:保證總線可靠性

CAN控制器會檢測總線錯誤,并根據錯誤計數進入不同狀態:

  • 主動錯誤狀態:錯誤較少,可正常發送錯誤幀,通知其他節點;
  • 被動錯誤狀態:錯誤較多,只能接收,發送前需等待總線空閑;
  • 總線關閉狀態:錯誤嚴重,無法參與通信,需軟件復位(HAL_CAN_ResetError)恢復。

錯誤處理示例

void CAN_Error_Handler(void)
{if((hcan.Instance->ESR & CAN_ESR_BOFF) != 0) // 檢測到總線關閉{printf("CAN總線關閉,嘗試恢復...\r\n");HAL_CAN_ResetError(&hcan); // 復位錯誤狀態HAL_CAN_Start(&hcan); // 重新啟動CAN}
}// 在主循環中定期檢查
while(1)
{if(HAL_CAN_GetError(&hcan) != HAL_CAN_ERROR_NONE){CAN_Error_Handler();}// ... 其他代碼 ...
}

六、常見問題與解決方案:避坑指南

6.1 通信失敗:波特率不匹配

現象:發送報文后,接收方收不到,或收到亂碼。

原因

  • 兩個節點的波特率計算錯誤,導致時鐘不同步;
  • 位時序參數(BS1、BS2、SJW)配置不一致。

解決方案

  1. 重新計算波特率:確保APB1時鐘 / (Prescaler × (SJW+BS1+BS2))在兩個節點完全一致;
  2. 推薦位時序參數:對于500kbps,可使用Prescaler=6, SJW=1, BS1=8, BS2=3(總TQ=12,36MHz/6/12=500kbps)。

6.2 接收不到報文:濾波器配置錯誤

現象:總線有數據,但本節點收不到。

原因

  • 濾波器未使能(FilterActivation=DISABLE);
  • 濾波器ID或掩碼配置錯誤,目標ID被過濾;
  • FIFO溢出(報文過多未及時處理,導致新報文被丟棄)。

解決方案

  1. 檢查濾波器使能狀態,確保FilterActivation=ENABLE
  2. 用回環模式測試濾波器:發送目標ID,若能收到,說明濾波器配置正確;
  3. 及時處理FIFO數據,避免溢出(可增加FIFO滿中斷)。

6.3 總線錯誤:硬件或接線問題

現象:頻繁進入總線錯誤狀態,甚至總線關閉。

原因

  • CAN_H和CAN_L接反或短路;
  • 終端電阻缺失或阻值錯誤(應為120Ω);
  • 總線長度過長,超出對應波特率的最大距離;
  • 電源干擾(未接地或紋波過大)。

解決方案

  1. 用萬用表檢查CAN_H和CAN_L是否短路,接線是否正確;
  2. 確保總線兩端各接一個120Ω終端電阻;
  3. 降低波特率(如從1Mbps降為500kbps),延長傳輸距離;
  4. 加強電源濾波,確保接地良好。

七、擴展

  • CAN FD:支持更高數據速率(8Mbps)和更長數據幀(64字節),適合大數據量傳輸;
  • CANopen協議:在CAN基礎上的高層協議,定義了標準化的通信對象和設備模型;
  • 多節點網絡管理:學習如何設計CAN網絡的ID分配、優先級規劃和故障診斷。

掌握STM32 CAN通信,能為工業控制、汽車電子等領域的開發打下堅實基礎——這是嵌入式工程師進階的重要技能。建議結合實際硬件多做測試,尤其是濾波器配置和錯誤處理,才能真正理解CAN總線的精髓。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/915010.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/915010.shtml
英文地址,請注明出處:http://en.pswp.cn/news/915010.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

【鴻蒙HarmonyOS】鴻蒙app開發入門到實戰教程(二):封裝自定義可復用組件

組件的可復用性&#xff0c;對我們開發的app質量影響很大&#xff0c;看看鴻蒙中如何封裝這種組件 實現效果代碼實現 局部封裝 Builder titleBuilder(title:string 默認標題) {// Builder裝飾此函數&#xff0c;使其能以鏈式調用的方式配置并構建Text組件Row(){Text(title).fo…

Volo-HTTP 0.4.0發布:正式支持 HTTP/2,客戶端易用性大幅提升!

&#x1f916; VOLO簡介 Volo 是由字節跳動服務框架團隊開源的一款高性能、易用的 Rust RPC 框架。 Volo 框架自身開銷極低&#xff0c;并提供了命令行工具與靈活的中間件設計&#xff0c;讓開發者可以輕松上手&#xff0c;享受 Rust 帶來的開發樂趣。 本文介紹自 Volo-HTTP 0…

HTTP相關知識

文章目錄一、基礎特性與規范二、頁面元素與布局三、交互與表單四、網絡通信基礎流程&#xff08;以瀏覽器訪問網頁為例&#xff09;五、配套技術與工具六、知識關聯圖&#xff08;簡化版&#xff09;一、基礎特性與規范 技術定位&#xff1a;HTML 是前端技術棧的核心標記語言&…

機器人-組成結構

目錄 一、發展歷程 二、軟件硬件算法深讀耦合 感知 - 決策 - 執行 1.機械系統&#xff1a; 2.驅動系統&#xff1a; 3.感知系統&#xff1a; 4.控制系統&#xff1a; 5.決策/智能系統&#xff1a; 6.電源系統&#xff1a; 7.總結 一、發展歷程 國際標準化組織(ISO)對…

pycharm結構查看器

v表示整個文件中定義的變量&#xff0c;c是類灰色部分是繼承的父類的&#xff0c;明亮的是定義的&#xff0c;其中m表示定義的函數&#xff0c;f表示

AdsPower 功能詳解 | 應用中心使用指南:插件統一管理更高效、更安全!

當你使用 AdsPower 管理多個瀏覽器環境時&#xff0c;插件的統一配置就變得尤為重要。而「應用中心」正是幫助你集中管理瀏覽器插件的功能入口&#xff0c;搭配瀏覽器環境使用&#xff0c;可以讓賬號操作更便捷、團隊協作更高效。這篇教程將帶你快速上手 AdsPower 應用中心的核…

回歸預測 | MATLAB實現DBO-BP蜣螂算法優化BP神經網絡多輸入單輸出回歸預測

回歸預測 | MATLAB實現DBO-BP蜣螂算法優化BP神經網絡多輸入單輸出回歸預測 目錄 回歸預測 | MATLAB實現DBO-BP蜣螂算法優化BP神經網絡多輸入單輸出回歸預測 預測效果 基本介紹 主要功能 邏輯關聯與算法流程 1. 數據準備 2. DBO優化BP參數 3. BP神經網絡構建 4. 預測與評估 運行…

Lsposed/Xposed

1.環境 1.1 xposed: 安卓8以下使用 下載并安裝xposed installer&#xff0c;模擬器需勾選設置-共享磁盤。 若提示未激活&#xff0c;需要下載sdk sdk下載地址 放置目錄 /sdcard/Android/data/de.robv.android.xposed.installer/cache/downloads/framework/文件權限設置 777 …

3D工業相機是什么?如何選擇和使用它?

工業自動化越來越深入&#xff0c;3D成像技術&#xff08;3D工業相機&#xff09;在工業生產中越來越重要。這篇文章就來說說3D工業相機的技術原理、具體能應用在哪以及怎么選3D相機&#xff0c;給大家做個參考。一、 技術定義與核心特點3D工業相機&#xff0c;簡單說就是一種特…

有哪些好用的原型設計軟件?墨刀、Axure等測評對比

下面是幾款常用原型設計軟件的簡介和對比&#xff0c;重點對墨刀和Axure進行了測評分析&#xff0c;幫助你根據需求做出選擇。&#x1f4a1;常見原型設計軟件一覽工具名稱適合人群平臺支持是否協作是否支持交互墨刀&#xff08;MockingBot&#xff09;產品經理/團隊協作Web、Wi…

二叉樹思想草稿

二叉樹解體兩種思路 是否可以通過遍歷一遍二叉樹得到答案&#xff1f; 用一個traverse函數配合外部變量實現遍歷的思維模式 是否可以定義一個遞歸函數&#xff0c;通過子樹的答案推導出原問題的答案&#xff1f; 遞歸三部曲&#xff1a; 函數定義&#xff0c;參數&#xff0c;返…

如何區分Bug是前端問題還是后端問題?

在軟件測試中,精準定位Bug的歸屬(前端 or 后端)是高效協作的關鍵。以下是系統化的排查方法,結合技術細節和實戰技巧: 1. 核心判斷邏輯 「數據 vs 展示」二分法: 后端問題:數據本身錯誤(API返回錯誤數據/邏輯錯誤/數據庫問題) 前端問題:數據正確但展示異常(UI渲染錯…

深入解析操作系統中的文件控制塊(FCB):從原理到現代實現演進

一、FCB的核心概念與基礎結構文件控制塊&#xff08;File Control Block, FCB&#xff09;是操作系統管理文件的核心元數據結構&#xff0c;充當文件系統與物理存儲間的橋梁。FCB本質上是文件在內存中的映射&#xff0c;包含文件的所有管理信息。傳統FCB通常占據32-44字節空間&…

python原生處理properties文件

這個工具類使用 Python 的 configparser 模塊操作 .properties 文件&#xff0c;核心是將 .properties 格式適配為 configparser 支持的 .ini 格式。 核心代碼解釋 1. 類初始化與配置解析 class Properties:def __init__(self, file_path: str, encoding: str utf-8):self.fil…

【java 安全】 IO流

前言 IO是指 Input/Output&#xff0c;即輸入和輸出。以內存為中心&#xff1a; Input指從外部讀入數據到內存&#xff0c;例如把文件從磁盤讀取到內存&#xff0c;從網絡讀取數據到內存等等。Output指把數據從內存輸出到外部&#xff0c;例如把數據從內存寫入到文件&#xff0…

音視頻同步技術初剖析:原理、實現與FFmpeg分析

音視頻同步的基本原理 音視頻同步主要依靠以下幾個關鍵點&#xff1a;時間戳機制&#xff1a; 在封裝格式(如MP4)中&#xff0c;音頻幀和視頻幀都帶有時間戳(PTS, Presentation Time Stamp)這些時間戳表示該幀應該在什么時間被呈現同步策略&#xff1a; 音頻為主時鐘&#xff1…

掌控網頁的魔法之書:JavaScript DOM的奇幻之旅

掌控網頁的魔法之書&#xff1a;JavaScript DOM的奇幻之旅 在網頁開發的世界里&#xff0c;JavaScript就像一位魔法師&#xff0c;而DOM&#xff08;文檔對象模型&#xff09;則是它的魔法之書。沒有DOM&#xff0c;JavaScript就像失去了咒語的巫師&#xff0c;無法操控網頁的元…

【C語言】深入理解柔性數組:特點、使用與優勢分析

C語言學習 柔性數組 友情鏈接&#xff1a;C語言專欄 文章目錄C語言學習前言&#xff1a;柔性數組一、柔性數組的特點二、柔性數組的使用三、柔性數組的優勢總結附錄上文鏈接專欄前言&#xff1a; 在有結構體和動態內存分配的知識后&#xff0c;今天咱們來說說柔性數組吧&…

RV126平臺NFS網絡啟動終極復盤報告

1. 初始目標與環境目標: 將RV1126開發板的啟動方式&#xff0c;由從eMMC內部存儲掛載根文件系統&#xff08;rootfs&#xff09;&#xff0c;切換為通過網絡掛載位于NFS服務器上的根文件系統。動機: 提升開發調試效率&#xff0c;實現代碼修改后僅需重啟即可驗證&#xff0c;免…

一臺顯示器上如何快速切換兩臺電腦主機?

我注意到很多人會遇到一個常見的情況&#xff1a;他們有兩臺電腦&#xff0c;一臺舊的用來處理基本的辦公任務&#xff0c;另一臺新的用來玩游戲。新手通常會用 DP端口連接第一臺電腦的顯示器&#xff0c;用 HDMI 連接第二臺電腦。當他們想在兩臺電腦之間切換時&#xff0c;經常…