轉自 | 老吳嵌入式
今天要介紹的開源軟件叫 c-periphery,一個用 C 語言編寫的硬件外設訪問庫。
我們可以用它來讀寫 Serial、SPI、I2C 等,非常適合在嵌入式產品上使用。
我們可以基于它優秀的代碼框架,不斷地擴展出更多的功能模塊,最終形成自己產品適用的 Linux 硬件抽象層。
源文件:
$tree. ├──src │├──gpio.c │├──gpio.h │├──i2c.c │├──i2c.h │├──led.c │├──led.h │├──mmio.c │├──mmio.h │├──pwm.c │├──pwm.h │├──serial.c │├──serial.h │├──spi.c │├──spi.h │├──version.c │└──version.h
約 4500 行代碼,每個硬件模塊的代碼都是相對獨立,上手難度小。
能收獲什么?
1、降低硬件編程的門檻;
2、了解 Linux 應用層如何訪問 GPIO / I2C / SPI / PWM 等硬件;
3、了解如何對硬件外設進行封裝,并提供良好的 API;
4、了解如何將代碼封裝成庫;
5、了解如何為代碼編寫單元測試程序;
c-periphery 很好地示范了如何在 Linux 平臺上進行硬件編程,定義出來的接口即豐富又實用。
另外,它最終輸出的是靜態庫 libperiphery.a,并且為每一個硬件模塊功能都編寫了單元測試代碼,代碼質量有保障。
c-periphery 的用法
簡單例子
我們以最常見的串口讀寫為例:
intmain(void) { serial_t*serial; uint8_ts[]="HelloWorld!"; uint8_tbuf[128]; intret; serial=serial_new(); /*Open/dev/ttyUSB0withbaudrate115200,anddefaultsof8N1,noflowcontrol*/ if(serial_open(serial,"/dev/ttyUSB0",115200)
serial_t 是對串口設備的抽象;
serial_new() 用于創建一個串口設備, 這里只是申請了數據,使用完畢后, 要通過 serial_free() 將其釋放掉。
serial_open() 用于初始化串口,設置設備節點、波特率等; 相應地,用 serial_close() 可以關閉串口。
serial_write() 用于給串口發數據,模仿了系統調用 write()。
serial_read() 用于從串口讀數據,比系統調用 read() 多了一個 timeout_ms 的參數,有了超時機制后,至少可以避免程序一直阻塞。
這就是一個最簡單的基于 c-periphery 的串口示例。即便是嵌入式初學者,基于這些接口,也能輕松地讀寫串口了。
另外,這里只用到了最常用的幾個 API。對于串口模塊,c-periphery 還有很多實用的 API:
比較有意思的幾個 API:serial_poll() 類似 select(),用于監控串口是否有數據,避免死等;
serial_get/set_xxx() 用于讀寫串口的屬性;
serial_fd() 用于獲取文件描述符,有了 fd 就意味這所有 Linux 應用編程的機制都可以使用了。例如我們可以將這個 fd 傳遞給 libev,然后就能進行事件驅動編程了。
c-periphery 的實現
關鍵數據
c-periphery 里對每個硬件模塊封裝的方法都是類似,用一個結構體來保存模塊所有相關的信息,看下面這幾個例子。
Serial:
I2C:
GPIO:
它們的成員變量大多都有文件描述符 fd、用于記錄錯誤狀態的 errno / error string,然后再加上一些硬件模塊特有的成員變量。最終庫的調用者只會看到 serial_t、i2c_t、gpio_t 這種類似描述符的數據類型,使用時不需要關心內部細節。
后續我們要添加自己的硬件模塊時,可以依葫蘆畫瓢,模仿著定義出屬于該硬件的 xxx_t 結構體,然后一步步地為 c-periphery 擴展出新的功能模塊。
幾個關鍵 API 的實現
我們以 Serial 為例,看下其核心 API 的實現。
分配與釋放:
就是在申請分配和釋放 serial_t 的內存。
寫數據 serial_write() 就是調用 write(),讀數據 serial_read() 則是利用 select() 實現了超時的功能:
serial_poll() 則是使用 poll() 來完成 io 監控。
其他硬件模塊的實現都是類似的。
到此,c-periphery 的核心實現代碼就拆解完畢了。
為 c-periphery 添加新的硬件模塊
學以致用,我們按照 c-periphery 的框架,添加背光 Backlight 功能。Backlight 的控制方法可以參考這篇文章:一個控制背光的命令行小工具。
先定義 backlight_t:
然后再實現好下面這些 API:
API 的具體實現代碼就不再這里展示了,因為控制背光無非就是讀寫 /sys/class/backlight/ 內的文件節點,難度不大。
總結c-periphery 是一個 C 語言編寫的硬件訪問庫,已支持 Serial、I2C、SPI、MMIO、PWM、GPIO 等硬件。約 4500 行代碼,每個硬件模塊的代碼都是相對獨立,上手難度小,非常使用在嵌入式 Linux 平臺上使用。
另外,我們可以基于它優秀的代碼框架,不斷地擴展出自己需要的功能模塊,最終形成自己產品專用的 Linux 硬件抽象層,絕對的嵌入式開發的利器。
審核編輯:湯梓紅
-
嵌入式
+關注
關注
5122文章
19423瀏覽量
312759 -
Linux
+關注
關注
87文章
11414瀏覽量
212248 -
SPI
+關注
關注
17文章
1748瀏覽量
93949 -
C語言
+關注
關注
180文章
7626瀏覽量
139571 -
開源
+關注
關注
3文章
3528瀏覽量
43262
原文標題:嵌入式開發神器:硬件外設訪問庫
文章出處:【微信號:strongerHuang,微信公眾號:strongerHuang】歡迎添加關注!文章轉載請注明出處。
發布評論請先 登錄
相關推薦
C語言中使用嵌入式SQL訪問Oracle數據庫的方法
用ASP訪問數據庫的幾種常見方式
C和C++編寫環境下LabVIEW如何調用動態庫?

評論