吴忠躺衫网络科技有限公司

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

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

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

簡(jiǎn)單實(shí)用的框架,可用于快速增加或修改IO配置

FPGA之家 ? 來(lái)源:FPGA之家 ? 作者:FPGA之家 ? 2022-05-17 09:54 ? 次閱讀

在一個(gè)嵌入式系統(tǒng)中,可能存在許多輸入或輸出的IO口,輸入有霍爾傳感器紅外對(duì)管等,輸出有LED電源控制開(kāi)關(guān)等。如果說(shuō)硬件可以一次成型,那么隨便一份代碼都可以完成IO的配置工作,但研發(fā)階段的產(chǎn)品,硬件各種修改是難免的,每一次 IO 的修改,對(duì)于底層開(kāi)發(fā)人員來(lái)說(shuō),可能都是一次挑戰(zhàn)。因?yàn)橐坏┯心骋粋€(gè) IO 配置錯(cuò)誤,或者原來(lái)的配置沒(méi)有修改正確(比如一個(gè) IO 在原來(lái)的硬件適配中是輸入,之后的硬件需要修改成輸出),那么你很難查出來(lái)這是什么問(wèn)題,因?yàn)檫@個(gè)時(shí)候不僅硬件修改了,軟件也修改了,你需要先定位到底是軟件問(wèn)題還是硬件問(wèn)題,所以一個(gè)好用的 IO 的配置框架就顯得很有必要了。

有道友會(huì)說(shuō),不如使用 CubeMx 軟件進(jìn)行開(kāi)發(fā)吧。

1、這個(gè)軟件適用于 ST 單片機(jī),以前還能用,現(xiàn)在,除非你家里有礦,不然誰(shuí)用的起STM32?基本上都國(guó)產(chǎn)化了(雖然有些單片機(jī)號(hào)稱兼容,但到底還是有些差異的)。2、公司原本的代碼就是使用標(biāo)準(zhǔn)庫(kù),只是因?yàn)?/span>IO 的變化,你就需要把整個(gè)庫(kù)換掉嗎?時(shí)間上允許嗎?你確定修改后不會(huì)出現(xiàn)大問(wèn)題?3、國(guó)產(chǎn)化的芯片可沒(méi)有所謂的標(biāo)準(zhǔn)庫(kù)和HAL庫(kù)供你選擇,每一家都有各自的庫(kù),如果你的產(chǎn)品臨時(shí)換方案怎么辦?4、HAL 效率問(wèn)題。今天魚鷹介紹一個(gè)簡(jiǎn)單實(shí)用的框架,可用于快速增加或修改IO配置,甚至修改底層庫(kù)。假設(shè)有3個(gè) LED 作為輸出、3 個(gè)霍爾傳感器作為輸入:輸入配置代碼:
#defineGPIOx_DefGPIO_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),   };
// 單個(gè) IO 初始化函數(shù)  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 個(gè) 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;}

// 讀取單個(gè) IO 狀態(tài)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,另一個(gè)枚舉值自動(dòng)修改為相反值    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);//必須,進(jìn)入調(diào)試模式后點(diǎn)擊全速運(yùn)行
    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);    }                      }
調(diào)試的時(shí)候,我們可以很方便的查看每個(gè) IO 的狀態(tài)是怎樣的,而不用管 0 或 1 到底代表什么意思:7f08e036-d57a-11ec-bce3-dac502259ad0.png輸出配置代碼:
#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);//必須,進(jìn)入調(diào)試模式后點(diǎn)擊全速運(yùn)行
    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);}}
這個(gè)框架有啥好處呢?1、自動(dòng)完成 GPIO 的時(shí)鐘初始化工作,也就是說(shuō)你只需要修改引腳即可,不必關(guān)心時(shí)鐘配置,但對(duì)于特殊引腳(比如PB3,還是得另外配置才行。2、應(yīng)用和底層具體 IO 分離,這樣一旦修改了 IO,應(yīng)用代碼不需要進(jìn)行任何修改。3、增加或刪減 IO 變得很簡(jiǎn)單,增加 IO時(shí),首先加入對(duì)應(yīng)枚舉,然后就可以添加對(duì)應(yīng)的 IO 了。刪除 IO時(shí),只要屏蔽對(duì)應(yīng)枚舉值和引腳即可。4、參數(shù)檢查功能, IO 刪除時(shí),因?yàn)槠帘瘟藢?duì)應(yīng)的枚舉,所以編譯時(shí)可以幫你發(fā)現(xiàn)問(wèn)題,而增加 IO 時(shí),它可以幫你在運(yùn)行時(shí)檢查該 IO是否進(jìn)行配置了,可以防止因?yàn)槭д`導(dǎo)致的問(wèn)題。7f58713c-d57a-11ec-bce3-dac502259ad0.png5、更改庫(kù)時(shí)可以很方便,只需要修改對(duì)應(yīng)的宏即可,目前可以順利在 GD32 STM32 庫(kù)進(jìn)行快速更換。6、對(duì)于輸入 IO 而言,可以方便的修改有效和無(wú)效狀態(tài),防止硬件修改有效電平。對(duì)于輸出 IO 而言,可以設(shè)定初始 IO 電平狀態(tài)。7、代碼簡(jiǎn)單高效,盡可能的復(fù)用代碼,增加一個(gè) IO 只需要很少的空間。8、缺點(diǎn)就是,只對(duì)同種配置的 IO 可以這樣用。

審核編輯 :李倩


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

    關(guān)注

    6043

    文章

    44622

    瀏覽量

    638529
  • 霍爾傳感器
    +關(guān)注

    關(guān)注

    27

    文章

    728

    瀏覽量

    63377

原文標(biāo)題:簡(jiǎn)單實(shí)用IO輸入輸出框架

文章出處:【微信號(hào):zhuyandz,微信公眾號(hào):FPGA之家】歡迎添加關(guān)注!文章轉(zhuǎn)載請(qǐng)注明出處。

收藏 人收藏

    評(píng)論

    相關(guān)推薦

    華納云監(jiān)視Linux磁盤IO性能命令:iotop,iostat,vmstat,atop,dstat,ioping

    。 top命令可用于查看CPU是否正在等待磁盤操作完成。“wa”度量標(biāo)準(zhǔn)顯示IO等待,CPU等待IO完成所花費(fèi)的時(shí)間(以百分比
    的頭像 發(fā)表于 10-24 14:43 ?266次閱讀

    io口和串口的區(qū)別 單片機(jī)有多少個(gè)io

    等。而串口,即串行通信接口(Serial Communication Interface),是一種數(shù)據(jù)通信方式,通過(guò)一條數(shù)據(jù)線按照順序傳送數(shù)據(jù)。IO口和串口在功能和用途上存在顯著區(qū)別: 通信方式 : IO口 :實(shí)現(xiàn)簡(jiǎn)單的輸入輸出
    的頭像 發(fā)表于 10-06 10:06 ?2057次閱讀

    【教程】比Modbus控制更簡(jiǎn)單!S7 200 SMART利用Profinet網(wǎng)關(guān)擴(kuò)展IO

    PLC自帶IO方法控制擴(kuò)展IO。一配置Profinet網(wǎng)關(guān)首先導(dǎo)入Profinet網(wǎng)關(guān)的GSD文件,用于STEP7-MicroWINSMART組態(tài)軟件
    的頭像 發(fā)表于 09-20 08:07 ?679次閱讀
    【教程】比Modbus控制更<b class='flag-5'>簡(jiǎn)單</b>!S7 200 SMART利用Profinet網(wǎng)關(guān)擴(kuò)展<b class='flag-5'>IO</b>

    單片機(jī)基本io功能調(diào)試過(guò)程

    所使用的單片機(jī)型號(hào)以及需要調(diào)試的IO口。不同型號(hào)的單片機(jī)在IO口的配置和特性上可能有所不同。 查閱單片機(jī)手冊(cè) : 查閱單片機(jī)的手冊(cè)數(shù)據(jù)手冊(cè),了解I
    的頭像 發(fā)表于 09-14 14:38 ?784次閱讀

    單片機(jī)io口怎么配置成輸出口

    單片機(jī)IO配置成輸出口的過(guò)程通常涉及對(duì)單片機(jī)內(nèi)部寄存器的操作。不同型號(hào)的單片機(jī)在寄存器配置和編程方式上可能有所不同,但基本原理是相似的。以下是一個(gè)通用的步驟,用于將單片機(jī)
    的頭像 發(fā)表于 09-14 14:33 ?973次閱讀

    Lattice MachXO3 Family默認(rèn)IO上下拉配置

    not bonded to a package pin). 也就是說(shuō),可以對(duì)unused pins進(jìn)行配置上下拉。因?yàn)樾酒想姾?b class='flag-5'>IO默認(rèn)三態(tài)下拉,我想現(xiàn)在將部分IO改為三態(tài)上拉。 2:試了很久,發(fā)現(xiàn)在Diamond軟件中,只有
    發(fā)表于 08-23 12:57

    NVIDIA推出全新深度學(xué)習(xí)框架fVDB

    在 SIGGRAPH 上推出的全新深度學(xué)習(xí)框架可用于打造自動(dòng)駕駛汽車、氣候科學(xué)和智慧城市的 AI 就緒型虛擬表示。
    的頭像 發(fā)表于 08-01 14:31 ?686次閱讀

    國(guó)產(chǎn)遠(yuǎn)程IO的在汽車生產(chǎn)裝配的應(yīng)用

    MR30系列遠(yuǎn)程IO使用簡(jiǎn)單、設(shè)計(jì)緊湊、性能卓越,適用于各種A汽車裝配場(chǎng)景。
    的頭像 發(fā)表于 07-12 15:28 ?404次閱讀
    國(guó)產(chǎn)遠(yuǎn)程<b class='flag-5'>IO</b>的在汽車生產(chǎn)裝配的應(yīng)用

    是否可以修改ESP8266的wifi信標(biāo)框架

    我想知道我是否可以修改ESP8266的 wifi 信標(biāo)框架.
    發(fā)表于 07-12 12:15

    bootstrap框架和vue框架的區(qū)別

    Bootstrap和Vue都是目前非常流行的前端開(kāi)發(fā)框架,它們各自具有獨(dú)特的優(yōu)勢(shì)和特點(diǎn)。 設(shè)計(jì)理念 Bootstrap是一個(gè)基于HTML、CSS和JavaScript的前端開(kāi)發(fā)框架,主要用于
    的頭像 發(fā)表于 07-11 09:55 ?984次閱讀

    遠(yuǎn)程IO與分布式IO的區(qū)別

    在工業(yè)自動(dòng)化和控制系統(tǒng)設(shè)計(jì)中,遠(yuǎn)程IO(Input/Output)和分布式IO是兩個(gè)重要的概念。它們各自具有獨(dú)特的特點(diǎn)和優(yōu)勢(shì),適用于不同的應(yīng)用場(chǎng)景。本文將詳細(xì)探討遠(yuǎn)程IO與分布式
    的頭像 發(fā)表于 06-15 15:57 ?2823次閱讀

    鴻蒙Ability Kit(程序框架服務(wù))【應(yīng)用啟動(dòng)框架AppStartup】

    `AppStartup`提供了一種更加簡(jiǎn)單高效的初始化組件的方式,支持異步初始化組件加速應(yīng)用的啟動(dòng)時(shí)間。使用啟動(dòng)框架應(yīng)用開(kāi)發(fā)者只需要分別為待初始化的組件實(shí)現(xiàn)`AppStartup`提供
    的頭像 發(fā)表于 06-10 18:38 ?789次閱讀

    暖通控制系統(tǒng)可用鋇錸分布式IO系統(tǒng)BL207

    可編程邏輯控制功能,可替代DDC部分功能。 BACnet/IP IO系統(tǒng)BL207提供雙網(wǎng)口支持交換機(jī)級(jí)聯(lián)功能,支持標(biāo)準(zhǔn)的BACnet/IP協(xié)議,也可用于接入BACnet/IP控制器,可適配江森、霍
    的頭像 發(fā)表于 05-24 15:35 ?399次閱讀
    暖通控制系統(tǒng)<b class='flag-5'>可用</b>鋇錸分布式<b class='flag-5'>IO</b>系統(tǒng)BL207

    STM32配置IO口的頻率時(shí),為什么只給一個(gè)IO配置

    配置IO口的頻率時(shí),為什么只給一個(gè)IO配置
    發(fā)表于 04-07 08:43

    自制測(cè)試框架(設(shè)置界面密碼1)

    (設(shè)置界面密碼為1) 目前支持的指令如下: 1.沒(méi)有任何編程基礎(chǔ)的人快速實(shí)現(xiàn)簡(jiǎn)易自動(dòng)化制作; 2.測(cè)試后可以直接把數(shù)據(jù)和結(jié)果直接寫入到MES; 3.可持續(xù)增加新的功能及模塊; 4.快速實(shí)現(xiàn)點(diǎn)
    發(fā)表于 03-02 19:33
    百家乐官网的连庄连闲| 大发888手机版下载安| 百家乐官网澳门有网站吗| 百家乐画面方法| 江山百家乐官网的玩法技巧和规则 | 百家乐官网代理荐| 大丰收娱乐城开户| 送彩金百家乐平台| 马牌百家乐官网娱乐城| 大发888娱乐城登陆| 线上百家乐网站| 百家乐官网庄闲庄庄闲| 丰禾娱乐| 真人百家乐园| 百家乐官网园36bol在线| 博e百| 百家乐视频画面| 网上百家乐娱乐场| 百家乐官网群号| 大发真钱娱乐城| 威尼斯人娱乐城会员| 百家乐视频软件下载| 百家乐官网游戏规范| 徐水县| 机器百家乐作弊| 茅台百家乐官网的玩法技巧和规则| 湘潭县| 大发888博彩官方下载| 百家乐娱乐求指点呀| 网站百家乐官网假| 百家乐官网投注规则| 百家乐赌博网址| 百家乐官网赌场代理| 清徐县| 大发888 王博| 迪士尼百家乐的玩法技巧和规则| 百家乐网上赌博| 百家乐官网打法心得| 博发| 大发888官方pt老虎机大咖炸金花网页扎金花 | 财神娱乐城信誉|