0
  • 聊天消息
  • 系統(tǒng)消息
  • 評論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

介紹一個(gè)用C語言編寫的硬件外設(shè)訪問庫

strongerHuang ? 來源:老吳嵌入式 ? 2023-10-26 10:36 ? 次閱讀

轉(zhuǎn)自 | 老吳嵌入式

今天要介紹的開源軟件叫 c-periphery,一個(gè)用 C 語言編寫的硬件外設(shè)訪問庫。

我們可以用它來讀寫 Serial、SPI、I2C 等,非常適合在嵌入式產(chǎn)品上使用。

我們可以基于它優(yōu)秀的代碼框架,不斷地?cái)U(kuò)展出更多的功能模塊,最終形成自己產(chǎn)品適用的 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 行代碼,每個(gè)硬件模塊的代碼都是相對獨(dú)立,上手難度小。

能收獲什么?
1、降低硬件編程的門檻;

2、了解 Linux 應(yīng)用層如何訪問 GPIO / I2C / SPI / PWM 等硬件;

3、了解如何對硬件外設(shè)進(jìn)行封裝,并提供良好的 API;

4、了解如何將代碼封裝成庫;

5、了解如何為代碼編寫單元測試程序;

c-periphery 很好地示范了如何在 Linux 平臺上進(jìn)行硬件編程,定義出來的接口即豐富又實(shí)用。

另外,它最終輸出的是靜態(tài)庫 libperiphery.a,并且為每一個(gè)硬件模塊功能都編寫了單元測試代碼,代碼質(zhì)量有保障。

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 是對串口設(shè)備的抽象;

serial_new() 用于創(chuàng)建一個(gè)串口設(shè)備, 這里只是申請了數(shù)據(jù),使用完畢后, 要通過 serial_free() 將其釋放掉。

serial_open() 用于初始化串口,設(shè)置設(shè)備節(jié)點(diǎn)、波特率等; 相應(yīng)地,用 serial_close() 可以關(guān)閉串口。

serial_write() 用于給串口發(fā)數(shù)據(jù),模仿了系統(tǒng)調(diào)用 write()。

serial_read() 用于從串口讀數(shù)據(jù),比系統(tǒng)調(diào)用 read() 多了一個(gè) timeout_ms 的參數(shù),有了超時(shí)機(jī)制后,至少可以避免程序一直阻塞。

這就是一個(gè)最簡單的基于 c-periphery 的串口示例。即便是嵌入式初學(xué)者,基于這些接口,也能輕松地讀寫串口了。

另外,這里只用到了最常用的幾個(gè) API。對于串口模塊,c-periphery 還有很多實(shí)用的 API:

4d3374ac-73a0-11ee-939d-92fbcf53809c.png


比較有意思的幾個(gè) API:

serial_poll() 類似 select(),用于監(jiān)控串口是否有數(shù)據(jù),避免死等;

serial_get/set_xxx() 用于讀寫串口的屬性;

serial_fd() 用于獲取文件描述符,有了 fd 就意味這所有 Linux 應(yīng)用編程的機(jī)制都可以使用了。例如我們可以將這個(gè) fd 傳遞給 libev,然后就能進(jìn)行事件驅(qū)動編程了。

c-periphery 的實(shí)現(xiàn)

關(guān)鍵數(shù)據(jù)

c-periphery 里對每個(gè)硬件模塊封裝的方法都是類似,用一個(gè)結(jié)構(gòu)體來保存模塊所有相關(guān)的信息,看下面這幾個(gè)例子。

Serial:

4d393f36-73a0-11ee-939d-92fbcf53809c.png


I2C:

4d483b1c-73a0-11ee-939d-92fbcf53809c.png


GPIO:

4d599376-73a0-11ee-939d-92fbcf53809c.png


它們的成員變量大多都有文件描述符 fd、用于記錄錯(cuò)誤狀態(tài)的 errno / error string,然后再加上一些硬件模塊特有的成員變量。

最終庫的調(diào)用者只會看到 serial_t、i2c_t、gpio_t 這種類似描述符的數(shù)據(jù)類型,使用時(shí)不需要關(guān)心內(nèi)部細(xì)節(jié)。

后續(xù)我們要添加自己的硬件模塊時(shí),可以依葫蘆畫瓢,模仿著定義出屬于該硬件的 xxx_t 結(jié)構(gòu)體,然后一步步地為 c-periphery 擴(kuò)展出新的功能模塊。

幾個(gè)關(guān)鍵 API 的實(shí)現(xiàn)

我們以 Serial 為例,看下其核心 API 的實(shí)現(xiàn)。


分配與釋放:

4d640e64-73a0-11ee-939d-92fbcf53809c.png

就是在申請分配和釋放 serial_t 的內(nèi)存。


寫數(shù)據(jù) serial_write() 就是調(diào)用 write(),讀數(shù)據(jù) serial_read() 則是利用 select() 實(shí)現(xiàn)了超時(shí)的功能:

4d6e816e-73a0-11ee-939d-92fbcf53809c.png


serial_poll() 則是使用 poll() 來完成 io 監(jiān)控。

4d860334-73a0-11ee-939d-92fbcf53809c.png

其他硬件模塊的實(shí)現(xiàn)都是類似的。

到此,c-periphery 的核心實(shí)現(xiàn)代碼就拆解完畢了。


為 c-periphery 添加新的硬件模塊
學(xué)以致用,我們按照 c-periphery 的框架,添加背光 Backlight 功能。

Backlight 的控制方法可以參考這篇文章:一個(gè)控制背光的命令行小工具。

先定義 backlight_t:

4d8a2324-73a0-11ee-939d-92fbcf53809c.png

然后再實(shí)現(xiàn)好下面這些 API:

4d901374-73a0-11ee-939d-92fbcf53809c.png

API 的具體實(shí)現(xiàn)代碼就不再這里展示了,因?yàn)榭刂票彻鉄o非就是讀寫 /sys/class/backlight/ 內(nèi)的文件節(jié)點(diǎn),難度不大。


總結(jié)

c-periphery 是一個(gè) C 語言編寫的硬件訪問庫,已支持 Serial、I2C、SPI、MMIO、PWM、GPIO 等硬件。約 4500 行代碼,每個(gè)硬件模塊的代碼都是相對獨(dú)立,上手難度小,非常使用在嵌入式 Linux 平臺上使用。

另外,我們可以基于它優(yōu)秀的代碼框架,不斷地?cái)U(kuò)展出自己需要的功能模塊,最終形成自己產(chǎn)品專用的 Linux 硬件抽象層,絕對的嵌入式開發(fā)的利器。

審核編輯:湯梓紅

聲明:本文內(nèi)容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點(diǎn)僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問題,請聯(lián)系本站處理。 舉報(bào)投訴
  • 嵌入式
    +關(guān)注

    關(guān)注

    5082

    文章

    19123

    瀏覽量

    305143
  • Linux
    +關(guān)注

    關(guān)注

    87

    文章

    11304

    瀏覽量

    209474
  • SPI
    SPI
    +關(guān)注

    關(guān)注

    17

    文章

    1706

    瀏覽量

    91577
  • C語言
    +關(guān)注

    關(guān)注

    180

    文章

    7604

    瀏覽量

    136808
  • 開源
    +關(guān)注

    關(guān)注

    3

    文章

    3348

    瀏覽量

    42496

原文標(biāo)題:嵌入式開發(fā)神器:硬件外設(shè)訪問庫

文章出處:【微信號:strongerHuang,微信公眾號:strongerHuang】歡迎添加關(guān)注!文章轉(zhuǎn)載請注明出處。

收藏 人收藏

    評論

    相關(guān)推薦

    C語言實(shí)現(xiàn)個(gè)圣誕樹!

    2022年12月25號就是圣誕節(jié)了!圣誕節(jié)當(dāng)然要有個(gè)圣誕樹了,今天給你們C語言編寫
    發(fā)表于 12-07 11:18 ?1921次閱讀

    C語言標(biāo)準(zhǔn)的基本使用

    寫出看起來專業(yè)的C代碼,除了規(guī)范的變量/函數(shù)命名,還需要熟練使用C語言的標(biāo)準(zhǔn)。當(dāng)為了數(shù)組拷貝自己編寫
    發(fā)表于 09-14 14:04 ?702次閱讀

    STM32標(biāo)準(zhǔn)外設(shè)概述

    描述和應(yīng)用實(shí)例,為開發(fā)者訪問底層硬件提供了個(gè)中間API,通過使用固件函數(shù),無需深入掌握底層硬件
    發(fā)表于 08-05 06:59

    STM32標(biāo)準(zhǔn)外設(shè)概述

    描述和應(yīng)用實(shí)例,為開發(fā)者訪問底層硬件提供了個(gè)中間API,通過使用固件函數(shù),無需深入掌握底層硬件
    發(fā)表于 08-06 06:32

    C語言中使用嵌入式SQL訪問Oracle數(shù)據(jù)的方法

    (Oracle Call Interface簡稱OCI),通過調(diào)用系列OCI函數(shù)即可訪問數(shù)據(jù)。我在這里介紹的是前種方法。另外,在本文中
    發(fā)表于 12-15 06:35

    編寫個(gè)C語言為基礎(chǔ)的DSP程序

    實(shí)驗(yàn)2 : 編寫個(gè)C 語言為基礎(chǔ)的DSP程序.實(shí)驗(yàn)?zāi)康?.學(xué)習(xí)用標(biāo)準(zhǔn)
    發(fā)表于 03-17 00:13 ?3492次閱讀
    <b class='flag-5'>編寫</b><b class='flag-5'>一</b><b class='flag-5'>個(gè)</b>以<b class='flag-5'>C</b><b class='flag-5'>語言</b>為基礎(chǔ)的DSP程序

    C語言編寫程序?qū)崿F(xiàn)通過按鍵使LED燈周期閃爍

    C語言編寫程序?qū)崿F(xiàn)通過按鍵使LED燈周期閃爍。
    發(fā)表于 03-30 16:54 ?10次下載

    arduino什么語言編程

    Arduino使用C/C++編寫程序,雖然C++兼容C語言,但這是兩種
    發(fā)表于 11-08 15:21 ?7w次閱讀

    基于keil mdk 標(biāo)準(zhǔn)外設(shè)的軟件開發(fā)

    的性能特征。該函數(shù)還包括每一個(gè)外設(shè)的驅(qū)動描述和應(yīng)用實(shí)例,為開發(fā)者訪問底層硬件提供了
    發(fā)表于 11-24 17:56 ?1222次閱讀
    基于keil mdk 標(biāo)準(zhǔn)<b class='flag-5'>外設(shè)</b><b class='flag-5'>庫</b>的軟件開發(fā)

    ASP訪問數(shù)據(jù)的幾種常見方式

    Connectivity (ODBC) 兼容的數(shù)據(jù)和 OLE DB 兼容的數(shù)據(jù)源。如果您是個(gè)對數(shù)據(jù)連接有定了解的腳本
    發(fā)表于 03-26 14:46 ?4次下載

    STM32開發(fā)標(biāo)準(zhǔn)外設(shè)的詳細(xì)資料說明

    底層硬件提供了個(gè)中間API,通過使用固件函數(shù),無需深入掌握底層硬件細(xì)節(jié),開發(fā)者就可以輕松應(yīng)用每一個(gè)
    發(fā)表于 05-09 18:15 ?1次下載
    STM32開發(fā)標(biāo)準(zhǔn)<b class='flag-5'>外設(shè)</b><b class='flag-5'>庫</b>的詳細(xì)資料說明

    STM32F10x _硬件I2C讀寫EEPROM(標(biāo)準(zhǔn)外設(shè)版本)

    STM32F10x_硬件I2C讀寫EEPROM(標(biāo)準(zhǔn)外設(shè)版本)
    的頭像 發(fā)表于 03-25 11:11 ?1w次閱讀
    STM32F10x _<b class='flag-5'>硬件</b>I2<b class='flag-5'>C</b>讀寫EEPROM(標(biāo)準(zhǔn)<b class='flag-5'>外設(shè)</b><b class='flag-5'>庫</b>版本)

    CC++編寫環(huán)境下LabVIEW如何調(diào)用動態(tài)?

    C語言編寫的動態(tài)鏈接相比,不同的地方在于extern int “C” __declspec(dllexport) add(int x,i
    發(fā)表于 06-11 09:15 ?7775次閱讀
    <b class='flag-5'>C</b>和<b class='flag-5'>C</b>++<b class='flag-5'>編寫</b>環(huán)境下LabVIEW如何調(diào)用動態(tài)<b class='flag-5'>庫</b>?

    c語言hello world程序編寫

    C語言種非常經(jīng)典和常用的編程語言,而"Hello world"程序是每一個(gè)編程入門者的必修課。它是用來熟悉編程
    的頭像 發(fā)表于 11-26 09:23 ?2434次閱讀

    如何解決C語言中的“訪問權(quán)限沖突”異常?C語言引發(fā)異常原因分析

    些措施來解決和防止其發(fā)生。本文將詳細(xì)介紹C語言訪問權(quán)限沖突異常的原因以及解決方法。 、
    的頭像 發(fā)表于 01-12 16:03 ?5710次閱讀