成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

簡(jiǎn)單實(shí)用IO輸入輸出框架

存儲(chǔ) 存儲(chǔ)設(shè)備
在一個(gè)嵌入式系統(tǒng)中,可能存在許多輸入或輸出的IO口,輸入有霍爾傳感器、紅外對(duì)管等,輸出有LED、電源控制開關(guān)等。

 [[397946]]

本文轉(zhuǎn)載自微信公眾號(hào)「魚鷹談單片機(jī)」,作者魚鷹談單片機(jī)。轉(zhuǎn)載本文請(qǐng)聯(lián)系魚鷹談單片機(jī)公眾號(hào)。

在一個(gè)嵌入式系統(tǒng)中,可能存在許多輸入或輸出的IO口,輸入有霍爾傳感器、紅外對(duì)管等,輸出有LED、電源控制開關(guān)等。

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

因?yàn)橐坏┯心骋粋€(gè) IO 配置錯(cuò)誤,或者原來的配置沒有修改正確(比如一個(gè) IO 在原來的硬件適配中是輸入,之后的硬件需要修改成輸出),那么你很難查出來這是什么問題,因?yàn)檫@個(gè)時(shí)候不僅硬件修改了,軟件也修改了,你需要先定位到底是軟件問題還是硬件問題,所以一個(gè)好用的 IO 的配置框架就顯得很有必要了。

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

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

2、公司原本的代碼就是使用標(biāo)準(zhǔn)庫,只是因?yàn)镮O 的變化,你就需要把整個(gè)庫換掉嗎?時(shí)間上允許嗎?你確定修改后不會(huì)出現(xiàn)大問題?

3、國(guó)產(chǎn)化的芯片可沒有所謂的標(biāo)準(zhǔn)庫和HAL庫供你選擇,每一家都有各自的庫,如果你的產(chǎn)品臨時(shí)換方案怎么辦?

4、HAL 效率問題。

今天魚鷹介紹一個(gè)簡(jiǎn)單實(shí)用的框架,可用于快速增加或修改IO配置,甚至修改底層庫。

假設(shè)有3個(gè) LED 作為輸出、3 個(gè)霍爾傳感器作為輸入:

輸入配置代碼:

  1. #define GPIOx_Def           GPIO_TypeDef* 
  2. #define GPIOMode_Def        GPIOMode_TypeDef 
  3.  
  4. typedef struct 
  5.     GPIOx_Def       gpio;  
  6.     uint16_t        msk; 
  7.     GPIOMode_Def    pull_up_down;      
  8. } bsp_input_pin_def;  
  9.  
  10. #define  _GPIO_PIN_INPUT(id, pull, gpiox, pinx)   [id].gpio = (GPIOx_Def)gpiox, [id].msk = (1 << pinx), [id].pull_up_down = (GPIOMode_Def)pull 
  11. #define  GPIO_PIN_INPUT(id, pull, gpiox, pinx)    _GPIO_PIN_INPUT(id, pull, gpiox, pinx) 
  12.  
  13. #define bsp_pin_get_port(gpiox)             ((uint16_t)((GPIO_TypeDef *)gpiox)->IDR) 
  14. #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) 
  15.  
  16.  
  17. #define BSP_GPIO_PUPD_NONE                                          GPIO_Mode_IN_FLOATING 
  18. #define BSP_GPIO_PUPD_PULLUP                                        GPIO_Mode_IPU 
  19. #define BSP_GPIO_PUPD_PULLDOWN                                      GPIO_Mode_IPD 
  20.  
  21.  
  22. typedef enum 
  23.     PIN_INPUT_HALL_0 = 0,  // 輸入 IO 定義 
  24.     PIN_INPUT_HALL_1,    
  25.     PIN_INPUT_HALL_2,                     
  26.     PIN_INPUT_MAX 
  27. }bsp_pin_input_id_def; 
  28.  
  29. static const bsp_input_pin_def  bsp_input_pin [PIN_INPUT_MAX] =  
  30.     GPIO_PIN_INPUT(PIN_INPUT_HALL_0,          BSP_GPIO_PUPD_NONE, GPIOA, 0), 
  31.     GPIO_PIN_INPUT(PIN_INPUT_HALL_1,          BSP_GPIO_PUPD_NONE, GPIOB, 8),     
  32.     GPIO_PIN_INPUT(PIN_INPUT_HALL_2,          BSP_GPIO_PUPD_NONE, GPIOE, 9),    
  33. }; 
  34.  
  35. // 單個(gè) IO 初始化函數(shù)   
  36. void bsp_pin_init_input(GPIOx_Def gpiox, uint32_t msk, GPIOMode_TypeDef pull_up_down) 
  37.     uint32_t temp
  38.  
  39.     assert_param((msk & 0xffff0000) == 0 && gpiox != 0); 
  40.  
  41.     temp = ((uint32_t) gpiox - (uint32_t) GPIOA) / ( (uint32_t) GPIOB - (uint32_t) GPIOA); 
  42.  
  43.     /* enable the led clock */ 
  44.     RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA << temp, ENABLE); 
  45.  
  46.     GPIO_InitTypeDef GPIO_InitStruct; 
  47.  
  48.     GPIO_InitStruct.GPIO_Mode  = (GPIOMode_Def)pull_up_down; 
  49.     GPIO_InitStruct.GPIO_Pin   = msk; 
  50.     GPIO_InitStruct.GPIO_Speed = GPIO_Speed_2MHz; 
  51.  
  52.     GPIO_Init((GPIO_TypeDef*)gpiox, &GPIO_InitStruct); 
  53.  
  54. // 所有 IO 初始化 
  55. void gpio_input_init() 
  56. {     
  57.     bsp_input_pin_def  *info; 
  58.  
  59.     info = (bsp_input_pin_def *)&bsp_input_pin; 
  60.  
  61.     for(int i = 0; i < sizeof(bsp_input_pin)/sizeof(bsp_input_pin[0]); i++) 
  62.     { 
  63.         bsp_pin_init_input(info->gpio, info->msk, info->pull_up_down); 
  64.         info++; 
  65.     }    
  66.  
  67.  
  68. // 最多支持 32 個(gè) IO 輸入 
  69. uint32_t bsp_input_all(void) 
  70.     uint32_t temp = 0; 
  71.  
  72.     bsp_pin_get_value(temp, PIN_INPUT_HALL_0); 
  73.     bsp_pin_get_value(temp, PIN_INPUT_HALL_1); 
  74.     bsp_pin_get_value(temp, PIN_INPUT_HALL_2); 
  75.  
  76.     return temp
  77.  
  78.  
  79. // 讀取單個(gè) IO 狀態(tài) 
  80. uint32_t bsp_input_level(bsp_pin_input_id_def id) 
  81.     return (bsp_pin_get_port(bsp_input_pin[id].gpio) & bsp_input_pin[id].msk) ? 1 : 0; 
  82.  
  83. typedef enum 
  84.     HW_HAL_LEVEL_ACTIVE = 0, // 可直接修改為 0 或 1,另一個(gè)枚舉值自動(dòng)修改為相反值 
  85.     HW_HAL_LEVEL_NO_ACTIVE = !HW_HAL_LEVEL_ACTIVE, 
  86. }hw_input_hal_status_def; 
  87.  
  88. typedef struct   
  89.     hw_input_hal_status_def hal_level0;  
  90.     uint8_t                 hal_level1; 
  91.     uint8_t                 hal_level2; 
  92. }bsp_input_status_def; 
  93.  
  94.  
  95. bsp_input_status_def bsp_input_status; 
  96.  
  97. int main(void) 
  98. {   
  99.     USRAT_Init(9600);//必須,進(jìn)入調(diào)試模式后點(diǎn)擊全速運(yùn)行 
  100.  
  101.     gpio_input_init(); 
  102.  
  103.     while(1) 
  104.     { 
  105.         uint32_t temp = bsp_input_all(); 
  106.  
  107.         bsp_input_status.hal_level0 = (hw_input_hal_status_def)((temp >> PIN_INPUT_HALL_0) & 1); 
  108.         bsp_input_status.hal_level1 = ((temp >> PIN_INPUT_HALL_1) & 1); 
  109.         bsp_input_status.hal_level2 = ((temp >> PIN_INPUT_HALL_2) & 1); 
  110.     }                       

調(diào)試的時(shí)候,我們可以很方便的查看每個(gè) IO 的狀態(tài)是怎樣的,而不用管 0 或 1 到底代表什么意思:

輸出配置代碼:

  1. #define GPIOx_Def           GPIO_TypeDef* 
  2. #define GPIOMode_Def        GPIOMode_TypeDef 
  3.  
  4. typedef struct 
  5.     GPIOx_Def  gpio;  
  6.     uint32_t   msk;  
  7.     uint32_t   init_value;  
  8. } bsp_output_pin_def;  
  9.  
  10. #define  _GPIO_PIN_OUT(id, gpiox, pinx, init)                        [id].gpio = gpiox, [id].msk = (1 << pinx), [id].init_value = init 
  11. #define  GPIO_PIN_OUT(id, gpiox, pinx, init)                         _GPIO_PIN_OUT(id, gpiox, pinx, init) 
  12.  
  13. #define _bsp_pin_output_set(gpiox, pin)                              (gpiox)->BSRR = pin 
  14. #define bsp_pin_output_set(gpiox, pin)                               _bsp_pin_output_set(gpiox, pin) 
  15.  
  16. #define _bsp_pin_output_clr(gpiox, pin)                              (gpiox)->BRR = pin 
  17. #define bsp_pin_output_clr(gpiox, pin)                               _bsp_pin_output_clr(gpiox, pin) 
  18.  
  19. typedef enum 
  20.     PIN_OUTPUT_LED_G, 
  21.     PIN_OUTPUT_LED_R,   
  22.     PIN_OUTPUT_LED_B, 
  23.     PIN_OUTPUT_MAX 
  24. }bsp_pin_output_id_def; 
  25.  
  26. static const bsp_output_pin_def  bsp_output_pin [PIN_OUTPUT_MAX] =  
  27.     GPIO_PIN_OUT(PIN_OUTPUT_LED_G,          GPIOA,  0, 0), 
  28.     GPIO_PIN_OUT(PIN_OUTPUT_LED_R,          GPIOF, 15, 0), 
  29.     GPIO_PIN_OUT(PIN_OUTPUT_LED_B,          GPIOD, 10, 0), 
  30. }; 
  31.  
  32.  
  33. void bsp_pin_init_output(GPIOx_Def gpiox, uint32_t msk, uint32_t init) 
  34.     uint32_t temp
  35.  
  36.     assert_param((msk & 0xffff0000) == 0 && gpiox != 0); 
  37.  
  38.     temp = ((uint32_t) gpiox - (uint32_t) GPIOA) / ( (uint32_t) GPIOB - (uint32_t) GPIOA); 
  39.  
  40.     /* enable the led clock */ 
  41.     RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA << temp, ENABLE); 
  42.  
  43.     GPIO_InitTypeDef GPIO_InitStruct; 
  44.  
  45.     GPIO_InitStruct.GPIO_Mode  = (GPIOMode_Def)GPIO_Mode_Out_PP; 
  46.     GPIO_InitStruct.GPIO_Pin   = msk; 
  47.     GPIO_InitStruct.GPIO_Speed = GPIO_Speed_2MHz; 
  48.  
  49.     GPIO_Init((GPIO_TypeDef*)gpiox, &GPIO_InitStruct); 
  50.  
  51.     if(init == 0) 
  52.     { 
  53.         bsp_pin_output_clr(gpiox, msk); 
  54.     } 
  55.     else 
  56.     { 
  57.         bsp_pin_output_set(gpiox, msk); 
  58.     } 
  59.  
  60. void bsp_output_init() 
  61.     bsp_output_pin_def  *info; 
  62.  
  63.     info = (bsp_output_pin_def *)&bsp_output_pin; 
  64.     for(int i = 0; i < sizeof(bsp_output_pin)/sizeof(bsp_output_pin[0]); i++) 
  65.     { 
  66.         bsp_pin_init_output(info->gpio, info->msk, info->init_value); 
  67.         info++; 
  68.     } 
  69.  
  70. void bsp_output(bsp_pin_output_id_def id, uint32_t value) 
  71.     assert_param(id < PIN_OUTPUT_MAX); 
  72.  
  73.     if(value == 0) 
  74.     { 
  75.         bsp_pin_output_clr(bsp_output_pin[id].gpio, bsp_output_pin[id].msk); 
  76.     } 
  77.     else 
  78.     { 
  79.         bsp_pin_output_set(bsp_output_pin[id].gpio, bsp_output_pin[id].msk); 
  80.     } 
  81.  
  82. int main(void) 
  83. {   
  84.     USRAT_Init(9600);//必須,進(jìn)入調(diào)試模式后點(diǎn)擊全速運(yùn)行 
  85.  
  86.     bsp_output_init(); 
  87.  
  88.     while(1) 
  89.     { 
  90.         bsp_output(PIN_OUTPUT_LED_G, 1); 
  91.         bsp_output(PIN_OUTPUT_LED_B, 0); 
  92.         bsp_output(PIN_OUTPUT_LED_R, 1); 
  93.     }                       

這個(gè)框架有啥好處呢?

1、自動(dòng)完成 GPIO 的時(shí)鐘初始化工作,也就是說你只需要修改引腳即可,不必關(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)問題,而增加 IO 時(shí),它可以幫你在運(yùn)行時(shí)檢查該 IO是否進(jìn)行配置了,可以防止因?yàn)槭д`導(dǎo)致的問題。

5、更改庫時(shí)可以很方便,只需要修改對(duì)應(yīng)的宏即可,目前可以順利在 GD32 和 STM32 庫進(jìn)行快速更換。

6、對(duì)于輸入 IO 而言,可以方便的修改有效和無效狀態(tài),防止硬件修改有效電平。對(duì)于輸出 IO 而言,可以設(shè)定初始 IO 電平狀態(tài)。

7、代碼簡(jiǎn)單高效,盡可能的復(fù)用代碼,增加一個(gè) IO 只需要很少的空間。

8、缺點(diǎn)就是,只對(duì)同種配置的 IO 可以這樣用。

 

責(zé)任編輯:武曉燕 來源: 魚鷹談單片機(jī)
相關(guān)推薦

2011-11-28 09:25:36

Java輸入輸出

2009-12-23 10:57:20

nohup命令

2009-12-17 11:36:55

Ruby輸入輸出

2014-09-04 11:39:43

Linux

2011-07-11 11:05:09

Windows控制臺(tái)

2010-02-06 14:28:38

C++標(biāo)準(zhǔn)輸入輸出

2020-09-04 11:02:47

Java技巧參數(shù)

2021-06-24 10:24:57

Linux輸入輸出設(shè)備Interface

2024-09-09 06:00:00

Python輸入編程

2021-12-01 11:40:14

Python 輸入輸出

2010-02-03 15:35:00

C++輸入輸出漢字

2009-01-18 11:14:06

軟設(shè)計(jì)算機(jī)系統(tǒng)知識(shí)I

2013-12-12 17:21:46

Lua出入輸出

2009-07-30 11:43:32

2023-10-30 08:53:36

Python輸入輸出

2009-12-15 17:48:20

Ruby輸入輸出

2021-04-12 15:34:33

C語言printfscanf

2009-11-12 14:55:16

ADO.NET實(shí)體框架

2021-03-31 12:41:24

C語言編程語言

2021-04-04 08:00:39

C++編程語言軟件開發(fā)
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)

主站蜘蛛池模板: 国产精品女人久久久 | 欧美视频一区二区三区 | 亚洲a级| 国产成人综合av | 久久极品 | 正在播放国产精品 | 久久国内精品 | 中文字幕国产精品 | 亚洲一区二区久久 | 古装三级在线播放 | 雨宫琴音一区二区在线 | h片在线播放 | 日本精a在线观看 | 国产精品久久久久无码av | 国产一区二区三区四区在线观看 | 国产不卡视频 | 亚洲精品一区中文字幕乱码 | 国产精品视频一区二区三区四区国 | 一级特黄视频 | 久久国产精品免费一区二区三区 | 一区二区久久电影 | 亚洲精品一二三区 | 97影院2| 久久精品久久久久久 | 99re热精品视频 | 亚洲福利在线视频 | 大伊人久久 | 欧美在线视频二区 | 久久99视频免费观看 | 久久精品中文字幕 | 国产精品精品视频一区二区三区 | 一区二区国产精品 | 亚洲综合大片69999 | 色吊丝2288sds中文字幕 | 精品二三区 | 91 久久| 老司机深夜福利网站 | 免费观看成人性生生活片 | 插插宗合网 | 日韩成人久久 | 亚洲精品成人 |