利用與硬體無關的方法簡化嵌入式系統設計:驅動程式建置
利用與硬體無關的方法簡化嵌入式系統設計:驅動程式建置
作者:ADI 現場應用工程師 Giacomo Paterniani
本文探討如何在專案中實現與硬體無關的驅動程式。隨插即用的設計理念能夠明顯降低嵌入式軟體或韌體設計的複雜性,無論設計者的經驗水準如何,都能從中受益。如果您想瞭解驅動程式的基本函數和嵌入式系統的軟體架構,請參見文章「利用與硬體無關的方法簡化嵌入式系統設計:基本知識」。
簡介
在嵌入式系統設計中,設計人員通常要編寫驅動程式和韌體的代碼,確保所選的感測器能夠實現其所需的基本功能。此一過程往往耗時且繁瑣。為解決此一難題,可以透過結合硬體、軟體和韌體的方式,採用隨插即用的設計思路,進而簡化感測器的選擇和系統整合。與硬體無關的驅動程式不僅能夠讓感測器整合變得更加高效,還可以作為一種通用解決方案,便於在未來的設計中重複使用。本文將以慣性測量單元(IMU)感測器為例,說明如何實現與硬體無關的驅動程式,不過,此種方法同樣適用於其他類型的感測器和元件。該驅動程式是採用C語言所編寫,並已經在一款通用微控制器上進行測試。
驅動程式實現
附錄中包含提及的所有圖片和程式碼,可供讀者查閱。
- adis16500_rd_error_flag
附錄中的圖10展示了該函數的實現。該函數讀取ADIS16500_REG_DIAG_STAT暫存器中包含的錯誤標誌,如果未發生錯誤,所有位元都為0。可能的錯誤有10個,因此,該函數會返回一個ADIS16500_ERROR_FLAGS結構,其中包含10個布林(Boolean)欄位,每個欄位代表一個錯誤。該函數唯讀取ADIS16500_REG_ DIAG_STAT暫存器,並使用特定錯誤遮罩檢查該暫存器的各個位元,發現邏輯1時,該結構的相應欄位就會設定為true。
- adis16500_rd_temp
這是一個溫度讀取函數,其實現方法與加速度和陀螺儀相同(詳情請見本系列第一篇文章)。讀取的值用℃為單位表示。其二進位值包含在16位元暫存器ADIS16500_REG_TEMP_OUT中。之後,資料將經過二進位轉二進位補數的轉換。得到的二進位補數值將乘以溫度比例因數(單位為℃/LSB),最終得出以℃為單位的數值,並記錄在作為輸入傳遞的指標中。該函數實現可參見附錄中的圖9。
- adis16500_get_ts_usec
該函數用於獲取IMU的時間戳記,單位為μs。其實現方法與adis16500_rd_temp函數完全相同。具體可參見附錄中的圖9。
- adis16500_rd_data_cntr
該程式讀取已輸出的資料數量。實際上,只需讀取名為ADIS16500_REG_DATA_CNTR的暫存器即可實現。當該暫存器達到最大值時,將從0重新開始。該函數的實現方式可參見附錄中的圖9。
- adis16500_wr_acc_calib
該函數用於執行自訂偏移校準。設計人員透過調用該函數,可將偏移值增加到從輸出資料暫存器讀取的值中,進而將x、y、z校準值增加到x、y、z加速度數據中。該函數的輸入是指向ADIS16500_XL_OUT類型結構的指標,該結構包含x、y和z浮點類型欄位。該函數的目標是從浮點值轉換為二進位補數值,再從二進位補數值轉換為二進位值。所有步驟可參見附錄中的圖11。接下來,需要將二進位值寫入偏置暫存器,例如,對於x軸,需要寫入兩個暫存器:ADIS16500_REG_X_ACCEL_BIAS_L(低16位)和 ADIS16500_REG_X_ACCEL_BIAS_H(高16位)。y軸和z軸也是如此,各自有相應的偏置暫存器。為了檢查該程式是否正確執行,放置IMU感測器時,確保z軸垂直指向天空。在如此情況下,x軸和y軸的加速度值接近0,z軸的加速度值接近–9.81 m/s2 (–g)。調用校準函數並傳遞一個校準結構,其中x、y和z欄位均等於–9.81 m/s2,校準後的讀取結果為x = –9.81;y = –9.81;z = 0,即說明校準偏移函數正常工作。
- adis16500_wr_gyro_calib
這是與陀螺儀有關的偏移校準函數,其實現方法與加速度校準函數完全相同。區別在於,陀螺儀的校準需要按照產品手冊中的說明,使用對應的陀螺儀偏移暫存器來完成。
本文著重介紹IMU感測器驅動程式,但其軟體/韌體結構可用於任何類型的感測器。因此,要實現對所有感測器的通用支援,只需根據感測器與微控制器之間的通訊協議(如 SPI、 I2C、UART 等)進行調整。感測器的初始化方式仍然有效,因為初始化階段記錄了透過通訊協定進行收發的函數。
如何在專案中引入和使用驅動程式
除了關於感測器和微控制器單元(MCU)間硬體連接的基本說明外,本文並提供了相關指南,從軟體和韌體的角度介紹如何引入驅動程式。
感測器驅動程式沒有通用的組織結構。圖1所示為建議的資料夾結構。userlib資料夾中包含所有感測器驅動程式。在本示例中,只有IMU感測器驅動程式,但如果專案包含更多感測器,組織方式基本相同。userlib中有兩個資料夾,分別是include和src。include資料夾包含驅動程式的標頭檔,即本例中的adis16500.h,而src中包含原始檔案,即adis16500.c。userlib中還有一個指定include指令的makefile,如圖2所示。
![]() |
圖1.專案檔案夾結構。
![]() |
圖2.userlib makefile。
圖3所示為主makefile。其位於應用層,靠近main.c。該makefile包含user.mk,如圖3中紅色底線所示(代碼第115行)。
圖3.主makefile。
借助makefile (.mk),設計人員可以在應用層(例如在 main.c內)引入驅動程式的介面,並且可以調用感測器驅動程式的所有公共函數。如此,應用層和感測器驅動層之間就會建立起連結。在應用層可以得知感測器的驅動程式介面(adis16500.h)。因此,在應用層,將透過上文討論的初始化程式建立感測器驅動層和周邊驅動層之間的連結。在IMU感測器的具體用例中,發送器、接收器SPI函數和系統延遲函數將在main.c檔中定義,如附錄中的圖2所示。這三個函數完全遵循驅動程式標頭檔中的原型,即附錄中圖3頂部所示的原型。這三個函數內部是周邊驅動層提供的函數,如spiSelect、spiSend、spiReceive、spiUnselect和chThdSleepMicroseconds。因此,SPI接收器、發送器和系統延遲函數代表周邊驅動層和感測器驅動層之間的連結,這些函數將分配到初始化結構中,如附錄中的圖2所示。以上就是在專案中引入驅動程式的整個過程。
如果要從感測器擷取輸出,設計人員可以使用adis16500_rd_acc和adis16500_rd_gyro部分介紹的函數。感測器讀取並沒有完全通用的方法,圖4僅提供一個示例。
圖4.感測器輸出讀取示例。
在此示例中,main.c中有一個無限迴圈,始終檢查名為_adis16500_data_ready的布林靜態變數。該變數與回呼函數相關,當DR接腳變為高位準時,其將切換到TRUE,這表示已有新資料可用。在此種情況下,主函數將調用adis16500_rd_acc和adis16500_rd_gyro 函數。透過全速運行IMU感測器,設計人員將能夠以2 kHz的輸出資料速率(ODR)擷取資料。
結論
本文介紹了驅動程式功能,以及如何透過與硬體無關的方法簡化感測器整合。與硬體無關的驅動程式可以作為一種通用解決方案,以在未來的設計中重複使用。