在线观看www成人影院-在线观看www日本免费网站-在线观看www视频-在线观看操-欧美18在线-欧美1级

0
  • 聊天消息
  • 系統消息
  • 評論與回復
登錄后你可以
  • 下載海量資料
  • 學習在線課程
  • 觀看技術視頻
  • 寫文章/發帖/加入社區
會員中心
創作中心

完善資料讓更多小伙伴認識你,還能領取20積分哦,立即完善>

3天內不再提示

給大家分享一個非常簡單的IO輸入輸出框架

FPGA之家 ? 來源:魚鷹談單片機 ? 作者:魚鷹談單片機 ? 2021-07-23 10:45 ? 次閱讀

在一個嵌入式系統中,可能存在許多輸入或輸出的IO口,輸入有霍爾傳感器紅外對管等,輸出有LED電源控制開關等。

如果說硬件可以一次成型,那么隨便一份代碼都可以完成IO的配置工作,但研發階段的產品,硬件各種修改是難免的,每一次 IO 的修改,對于底層開發人員來說,可能都是一次挑戰。

因為一旦有某一個 IO 配置錯誤,或者原來的配置沒有修改正確(比如一個 IO 在原來的硬件適配中是輸入,之后的硬件需要修改成輸出),那么你很難查出來這是什么問題,因為這個時候不僅硬件修改了,軟件也修改了,你需要先定位到底是軟件問題還是硬件問題,所以一個好用的 IO 的配置框架就顯得很有必要了。

有道友會說,不如使用 CubeMx 軟件進行開發吧。

1、這個軟件適用于 ST 單片機,以前還能用,現在,除非你家里有礦,不然誰用的起STM32?基本上都國產化了(雖然有些單片機號稱兼容,但到底還是有些差異的)。

2、公司原本的代碼就是使用標準庫,只是因為IO 的變化,你就需要把整個庫換掉嗎?時間上允許嗎?你確定修改后不會出現大問題?

3、國產化的芯片可沒有所謂的標準庫和HAL庫供你選擇,每一家都有各自的庫,如果你的產品臨時換方案怎么辦?

4、HAL 效率問題。

今天魚鷹介紹一個簡單實用的框架,可用于快速增加或修改IO配置,甚至修改底層庫。

假設有3個 LED 作為輸出、3 個霍爾傳感器作為輸入:

輸入配置代碼:

#define GPIOx_Def GPIO_TypeDef*#define GPIOMode_Def GPIOMode_TypeDef

typedef struct{ GPIOx_Def gpio; uint16_t msk; GPIOMode_Def pull_up_down; } bsp_input_pin_def;

#define _GPIO_PIN_INPUT(id, pull, gpiox, pinx) [id].gpio = (GPIOx_Def)gpiox, [id].msk = (1 《《 pinx), [id].pull_up_down = (GPIOMode_Def)pull#define GPIO_PIN_INPUT(id, pull, gpiox, pinx) _GPIO_PIN_INPUT(id, pull, gpiox, pinx)

#define bsp_pin_get_port(gpiox) ((uint16_t)((GPIO_TypeDef *)gpiox)-》IDR)#define bsp_pin_get_value(variable,id) do{ bsp_pin_get_port(bsp_input_pin[id].gpio) & bsp_input_pin[id].msk ? variable |= (1 《《 id) : 0;} while(0)

#define BSP_GPIO_PUPD_NONE GPIO_Mode_IN_FLOATING#define BSP_GPIO_PUPD_PULLUP GPIO_Mode_IPU#define BSP_GPIO_PUPD_PULLDOWN GPIO_Mode_IPD

typedef enum{ PIN_INPUT_HALL_0 = 0, // 輸入 IO 定義 PIN_INPUT_HALL_1, PIN_INPUT_HALL_2, PIN_INPUT_MAX}bsp_pin_input_id_def;

static const bsp_input_pin_def bsp_input_pin [PIN_INPUT_MAX] = { GPIO_PIN_INPUT(PIN_INPUT_HALL_0, BSP_GPIO_PUPD_NONE, GPIOA, 0), GPIO_PIN_INPUT(PIN_INPUT_HALL_1, BSP_GPIO_PUPD_NONE, GPIOB, 8), GPIO_PIN_INPUT(PIN_INPUT_HALL_2, BSP_GPIO_PUPD_NONE, GPIOE, 9), };

// 單個 IO 初始化函數 void bsp_pin_init_input(GPIOx_Def gpiox, uint32_t msk, GPIOMode_TypeDef pull_up_down){ uint32_t temp;

assert_param((msk & 0xffff0000) == 0 && gpiox != 0);

temp = ((uint32_t) gpiox - (uint32_t) GPIOA) / ( (uint32_t) GPIOB - (uint32_t) GPIOA);

/* enable the led clock */ RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA 《《 temp, ENABLE);

GPIO_InitTypeDef GPIO_InitStruct;

GPIO_InitStruct.GPIO_Mode = (GPIOMode_Def)pull_up_down; GPIO_InitStruct.GPIO_Pin = msk; GPIO_InitStruct.GPIO_Speed = GPIO_Speed_2MHz;

GPIO_Init((GPIO_TypeDef*)gpiox, &GPIO_InitStruct);}

// 所有 IO 初始化void gpio_input_init(){ bsp_input_pin_def *info;

info = (bsp_input_pin_def *)&bsp_input_pin;

for(int i = 0; i 《 sizeof(bsp_input_pin)/sizeof(bsp_input_pin[0]); i++) { bsp_pin_init_input(info-》gpio, info-》msk, info-》pull_up_down); info++; } }

// 最多支持 32 個 IO 輸入uint32_t bsp_input_all(void){ uint32_t temp = 0;

bsp_pin_get_value(temp, PIN_INPUT_HALL_0); bsp_pin_get_value(temp, PIN_INPUT_HALL_1); bsp_pin_get_value(temp, PIN_INPUT_HALL_2);

return temp;}

// 讀取單個 IO 狀態uint32_t bsp_input_level(bsp_pin_input_id_def id){ return (bsp_pin_get_port(bsp_input_pin[id].gpio) & bsp_input_pin[id].msk) ? 1 : 0;}

typedef enum{ HW_HAL_LEVEL_ACTIVE = 0, // 可直接修改為 0 或 1,另一個枚舉值自動修改為相反值 HW_HAL_LEVEL_NO_ACTIVE = !HW_HAL_LEVEL_ACTIVE,}hw_input_hal_status_def;

typedef struct { hw_input_hal_status_def hal_level0; uint8_t hal_level1; uint8_t hal_level2;}bsp_input_status_def;

bsp_input_status_def bsp_input_status;

int main(void){ USRAT_Init(9600);//必須,進入調試模式后點擊全速運行

gpio_input_init();

while(1) { uint32_t temp = bsp_input_all();

bsp_input_status.hal_level0 = (hw_input_hal_status_def)((temp 》》 PIN_INPUT_HALL_0) & 1); bsp_input_status.hal_level1 = ((temp 》》 PIN_INPUT_HALL_1) & 1); bsp_input_status.hal_level2 = ((temp 》》 PIN_INPUT_HALL_2) & 1); } }

調試的時候,我們可以很方便的查看每個 IO 的狀態是怎樣的,而不用管 0 或 1 到底代表什么意思:

輸出配置代碼:

#define GPIOx_Def GPIO_TypeDef*#define GPIOMode_Def GPIOMode_TypeDef

typedef struct{ GPIOx_Def gpio; uint32_t msk; uint32_t init_value; } bsp_output_pin_def;

#define _GPIO_PIN_OUT(id, gpiox, pinx, init) [id].gpio = gpiox, [id].msk = (1 《《 pinx), [id].init_value = init#define GPIO_PIN_OUT(id, gpiox, pinx, init) _GPIO_PIN_OUT(id, gpiox, pinx, init)

#define _bsp_pin_output_set(gpiox, pin) (gpiox)-》BSRR = pin#define bsp_pin_output_set(gpiox, pin) _bsp_pin_output_set(gpiox, pin)

#define _bsp_pin_output_clr(gpiox, pin) (gpiox)-》BRR = pin#define bsp_pin_output_clr(gpiox, pin) _bsp_pin_output_clr(gpiox, pin)

typedef enum{ PIN_OUTPUT_LED_G, PIN_OUTPUT_LED_R, PIN_OUTPUT_LED_B, PIN_OUTPUT_MAX}bsp_pin_output_id_def;

static const bsp_output_pin_def bsp_output_pin [PIN_OUTPUT_MAX] = { GPIO_PIN_OUT(PIN_OUTPUT_LED_G, GPIOA, 0, 0), GPIO_PIN_OUT(PIN_OUTPUT_LED_R, GPIOF, 15, 0), GPIO_PIN_OUT(PIN_OUTPUT_LED_B, GPIOD, 10, 0),};

void bsp_pin_init_output(GPIOx_Def gpiox, uint32_t msk, uint32_t init){ uint32_t temp;

assert_param((msk & 0xffff0000) == 0 && gpiox != 0);

temp = ((uint32_t) gpiox - (uint32_t) GPIOA) / ( (uint32_t) GPIOB - (uint32_t) GPIOA);

/* enable the led clock */ RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA 《《 temp, ENABLE);

GPIO_InitTypeDef GPIO_InitStruct;

GPIO_InitStruct.GPIO_Mode = (GPIOMode_Def)GPIO_Mode_Out_PP; GPIO_InitStruct.GPIO_Pin = msk; GPIO_InitStruct.GPIO_Speed = GPIO_Speed_2MHz;

GPIO_Init((GPIO_TypeDef*)gpiox, &GPIO_InitStruct);

if(init == 0) { bsp_pin_output_clr(gpiox, msk); } else { bsp_pin_output_set(gpiox, msk); }}

void bsp_output_init(){ bsp_output_pin_def *info;

info = (bsp_output_pin_def *)&bsp_output_pin; for(int i = 0; i 《 sizeof(bsp_output_pin)/sizeof(bsp_output_pin[0]); i++) { bsp_pin_init_output(info-》gpio, info-》msk, info-》init_value); info++; }}

void bsp_output(bsp_pin_output_id_def id, uint32_t value){ assert_param(id 《 PIN_OUTPUT_MAX);

if(value == 0) { bsp_pin_output_clr(bsp_output_pin[id].gpio, bsp_output_pin[id].msk); } else { bsp_pin_output_set(bsp_output_pin[id].gpio, bsp_output_pin[id].msk); }}

int main(void){ USRAT_Init(9600);//必須,進入調試模式后點擊全速運行

bsp_output_init();

while(1) { bsp_output(PIN_OUTPUT_LED_G, 1); bsp_output(PIN_OUTPUT_LED_B, 0); bsp_output(PIN_OUTPUT_LED_R, 1); } }

這個框架有啥好處呢?

1、自動完成 GPIO 的時鐘初始化工作,也就是說你只需要修改引腳即可,不必關心時鐘配置,但對于特殊引腳(比如PB3),還是得另外配置才行。

2、應用和底層具體 IO 分離,這樣一旦修改了 IO,應用代碼不需要進行任何修改。

3、增加或刪減 IO 變得很簡單,增加 IO時,首先加入對應枚舉,然后就可以添加對應的 IO 了。刪除 IO時,只要屏蔽對應枚舉值和引腳即可。

4、參數檢查功能, IO 刪除時,因為屏蔽了對應的枚舉,所以編譯時可以幫你發現問題,而增加 IO 時,它可以幫你在運行時檢查該 IO是否進行配置了,可以防止因為失誤導致的問題。

a82570d2-e10c-11eb-9e57-12bb97331649.png

5、更改庫時可以很方便,只需要修改對應的宏即可,目前可以順利在 GD32 和 STM32 庫進行快速更換。

6、對于輸入 IO 而言,可以方便的修改有效和無效狀態,防止硬件修改有效電平。對于輸出 IO 而言,可以設定初始 IO 電平狀態。

7、代碼簡單高效,盡可能的復用代碼,增加一個 IO 只需要很少的空間。

8、缺點就是,只對同種配置的 IO 可以這樣用。

編輯:jq

聲明:本文內容及配圖由入駐作者撰寫或者入駐合作網站授權轉載。文章觀點僅代表作者本人,不代表電子發燒友網立場。文章及其配圖僅供工程師學習之用,如有內容侵權或者其他違規問題,請聯系本站處理。 舉報投訴
  • 嵌入式系統
    +關注

    關注

    41

    文章

    3610

    瀏覽量

    129604

原文標題:簡單實用IO輸入輸出框架

文章出處:【微信號:zhuyandz,微信公眾號:FPGA之家】歡迎添加關注!文章轉載請注明出處。

收藏 人收藏

    評論

    相關推薦

    西門子PLC輸入輸出接線全攻略

    的物理量,如溫度、壓力、流量等。本文重點講解數字量的輸入輸出接線。 、數字量輸入接線方式? ? PLC的輸入端主要用于對外圍的
    的頭像 發表于 01-09 16:02 ?328次閱讀
    西門子PLC<b class='flag-5'>輸入輸出</b>接線全攻略

    io口和串口的區別 單片機有多少io

    等。而串口,即串行通信接口(Serial Communication Interface),是種數據通信方式,通過條數據線按照順序傳送數據。IO口和串口在功能和用途上存在顯著區別: 通信方式 :
    的頭像 發表于 10-06 10:06 ?1862次閱讀

    誤差放大器的輸入輸出關系

    誤差放大器(Error Amplifier)在電子測量和控制系統中扮演著至關重要的角色,其輸入輸出關系對于理解和設計這些系統至關重要。以下是對誤差放大器輸入輸出關系的詳細解析,包括其工作原理、輸入輸出特性、影響因素以及實際應用等
    的頭像 發表于 09-11 15:32 ?1351次閱讀

    隔離變壓器輸入輸出可以隨便接嗎

    隔離變壓器的輸入輸出接線并非可以隨便接,而是需要遵循定的原則、步驟和注意事項,以確保其正常、安全、高效地運行。 、接線原則 電壓匹配 :在接線之前,必須確保輸入電源和
    的頭像 發表于 09-06 11:07 ?989次閱讀

    互阻放大電路對輸入輸出電阻的要求

    檢測的領域中非常重要。互阻放大電路的設計和性能受到輸入輸出電阻的影響,因此對這些電阻的要求非常嚴格。 輸入電阻 高輸入電阻 :互阻放大電路需
    的頭像 發表于 09-05 14:21 ?923次閱讀

    寄存器的輸入輸出方式

    寄存器的輸入輸出方式是數字電路設計中至關重要的部分,它決定了數據如何在寄存器中進出以及處理的效率。下面將詳細探討寄存器的幾種主要輸入輸出方式,包括并行輸入輸出、串行輸入輸出以及雙向
    的頭像 發表于 09-05 14:09 ?1516次閱讀

    PLC運動控制中的輸入輸出設備

    在PLC(可編程邏輯控制器)運動控制系統中,輸入輸出設備扮演著至關重要的角色。這些設備不僅負責將外部信號傳遞給PLC,還負責將PLC的處理結果輸出到外部執行機構,從而實現對機械設備運動的精確控制。以下是對PLC運動控制中輸入輸出
    的頭像 發表于 09-03 10:52 ?1017次閱讀

    用OPA656搭了簡單的跟隨器,但是輸入輸出之間有漂移,為什么?

    我用OPA656搭了簡單的跟隨器,但是輸入輸出之間有漂移,差不多250mV
    發表于 09-03 07:26

    引入負反饋對輸入輸出電阻的影響

    度等。 1. 引言 在電子電路設計中,電阻是基本的參數,它影響著電路的電流和電壓。輸入電阻和輸出電阻分別描述了電路對輸入信號和
    的頭像 發表于 07-30 09:43 ?2173次閱讀

    PLC輸入輸出信號異常的原因分析

    在工業自動化領域中,PLC(可編程邏輯控制器)作為控制系統的核心部件,其性能的穩定性和可靠性對于整個生產線的正常運行具有至關重要的影響。然而,在實際應用中,PLC的輸入輸出信號異常問題時有發生,這不
    的頭像 發表于 06-12 11:25 ?2350次閱讀

    為什么可以將GPIO引腳同時配置為輸入輸出模式呢?

    系列高低電平。 那么對于GPIO6而言,在發送起始信號的時候,是輸出模式,接收信號的時候是輸入模式,也就是說需要將引腳同時配置為
    發表于 06-05 07:37

    自定義位寬輸入輸出截位模塊的靈活配置方案

    可配置任意輸入輸出位寬截位模塊
    的頭像 發表于 04-25 11:36 ?416次閱讀

    PLC的輸入輸出接口是否需要進行隔離保護?

    PLC(可編程邏輯控制器)的輸入輸出接口是否需要進行隔離保護,取決于具體的應用場景和需求。
    的頭像 發表于 02-23 09:09 ?2186次閱讀

    輸入輸出復用電路的定義 復用器的輸出由什么控制

    輸入輸出復用電路是種特殊的電路設計,它允許單個物理端口在不同的時間或條件下執行輸入輸出操作。這種復用電路在多個領域都有應用,特別是在需要高效利用硬件資源和提高系統性能的場景中。
    的頭像 發表于 02-18 14:11 ?964次閱讀

    鎖相環的輸入輸出相位致嗎?

    鎖相環是保證相位致,還是相位差致?鎖相環的輸入輸出相位致嗎? 鎖相環(PLL)是種回路控制系統,用于保持
    的頭像 發表于 01-31 15:45 ?1245次閱讀
    主站蜘蛛池模板: 天堂在线网| 中文字幕色婷婷在线精品中| 情趣店上班h系列小说| 奇米影视婷婷| 99九九成人免费视频精品| 久久综合九色综合98一99久久99久| 四虎影院.com| 国产精品久久久久久吹潮| 91视频免费网站| www操com| 国产高清毛片| 狠狠天天| 国产老头和美女在线观看| 特黄视频| 天天插天天色| 五月花亚洲| 在线免费看一级片| www.青草视频| 好男人社区在线观看www| 麻豆国产三级在线观看| 免费网站日本| 欧美黄色片在线观看| 欧美在线观看www| 日韩有色| 日本xxxx色视频在线观看免费| 色停停| 色婷婷资源网| 色妞综合网| 激情五月婷婷综合网| 久久久免费| 久久久久四虎国产精品| bt磁力在线搜索| 日日夜夜精品| 狠狠操天天操夜夜操| 91拍拍在线观看| 亚洲伊人tv综合网色| 香蕉久久夜色精品国产2020| 午夜私人影院| 老色视频| 天天艹| 在线观看视频一区二区|