天天看點

STM32CubeMX-GPIO的八種工作模式

STM32IO口的八種工作模式:

1)、GPIO_Mode_IN_FLOATING:浮空輸入

2)、GPIO_Mode_AIN:模拟輸入

3)、GPIO_Mode_IPD:下拉輸入

4)、GPIO_Mode_IPU:上拉輸入

5)、GPIO_Mode_Out_OD:開漏輸出

6)、GPIO_Mode_Out_PP:推挽輸出

7)、GPIO_Mode_AF_OD:複用開漏輸出

8)、GPIO_Mode_AF_PP:複用推挽輸出

STM32CubeMX-GPIO的八種工作模式

在晶片手冊上有每個IO口支援的功能,我們想要知道一個IO都有啥功能時,就晶片手冊而言可能手頭沒有或者懶得去翻。這時STM32CubeMX的便利性就突出來了!下圖比如我們想知道PF6這個IO口支援哪些功能,隻需要在這個引腳上單擊左鍵,軟體就會将該IO目前所支援的功能彈出!

STM32CubeMX-GPIO的八種工作模式
STM32CubeMX-GPIO的八種工作模式

上圖為M4的IO口基本結構

1、GPIO輸入

STM32的輸入相對于輸出來說要簡單,從字面意思能很容易了解。

IO配置為浮空輸入,IO輸入的電平會直接到施密特觸發器(百度對于施密特觸發器的解釋)IO口浮空狀态時IO處于高阻态,電平狀态完全由外部輸入電平決定。

IO配置為上拉輸入或者下拉輸入,

STM32CubeMX-GPIO的八種工作模式

上拉輸入IO口會把這個上拉電路(1)接入,在外部無電平輸入時,IO口狀态為高。

下拉輸入IO口會把這個下拉電路(2)接入,在外部無電平輸入時,IO口狀态為低。,

IO配置為模拟輸入,

STM32CubeMX-GPIO的八種工作模式

為模拟輸入時,IO口輸入的不在是數字量而是模拟量,IO口會關閉施密特觸發器,将模拟量送到片上的外設AD去采集,

這四種輸入模式我們在什麼情況下使用的:

數字電路有三種狀态:高電平、低電平、高組态,當不希望出現高阻态時,可以通過上拉電阻或者下拉電阻的方式将不确定的信号通過一個電阻鉗位在高電平或者低電平。

簡單的說當外圍裝置自己沒有驅動能力時上拉和下拉電阻必不可少,就按鍵來說按鍵自己本身無法輸出高低電平這時就需要上拉或者下拉電阻,

STM32CubeMX-GPIO的八種工作模式

原子的探索者開發闆字上有四個按鍵,根據原理圖可以看出需要檢測這四個按鍵狀态,WK_UP需要設定為下拉,其他三個為上拉。理論上來說當外圍裝置具有驅動能力時,不需要上拉或者下拉浮空就可以。但還是要具體問題具體分析。比如我在原子的論壇裡看到一位老哥講的,在按鍵和IIC上他從來不用IO的電阻,自己外接電阻。因為他覺得晶片内部內建的電阻,阻值都比較大(幾十K),提供的“拉力”不強且難說穩定。那這時他的IO口肯定設定的是浮空狀态。(原子論壇裡關于這幾種方式的讨論)模拟輸入這個簡單的來說就是我們用ADC功能檢測電壓這樣的模拟量時使用的,會通過模拟通道将模拟量直接送給AD采集。

在STM32CubeMX中

要使用浮空輸入或者上拉\下拉時左鍵單擊,在彈出的菜單中選擇GPIO_Input,然後在左側的GPIO選項中單擊該IO口,在GPIO Pull-up/Pull-down中選擇浮空還是下拉或者上拉。Pull-up為上拉輸入模式、Pull-down為下拉輸入模式、No Pull-up and No Pull-down 為浮空輸入。如下圖

STM32CubeMX-GPIO的八種工作模式

要是使用模拟輸入時單擊左鍵在彈出的菜單中選擇GPIO_Analog,如下圖

STM32CubeMX-GPIO的八種工作模式

1、GPIO輸出

大體的來看有兩種模式:開漏輸出和推完輸出。

STM32CubeMX-GPIO的八種工作模式

上圖有兩個MOS

當設定為開漏輸出時P-MOS是始終截止的,當輸出控制輸出0時,N-MOS被導通,這樣就會将IO口電平拉低,這時IO的輸出狀态就是低;當輸出控制輸出為1時,N-MOS截止,這時候IO的輸出狀态需要上拉或者下拉電阻來實作,比如開漏輸出模式需要輸出高電平,那就需要上拉電阻。

當設定為推完輸出時,當輸出控制輸出為0時P-MOS截止,N-MOS導通IO電平被拉低,也就是輸出0;當輸出控制輸出為1時,P-MOS導通,N-MOS截止IO口電平被拉高,也就是輸出1。

複用開漏輸出和開漏輸出原理一樣,差別在于輸出控制源不同,前者是通過外設後者是通過CPU寫寄存器。

複用推挽輸出和推挽輸出原理一樣,差別在于輸出控制源不同,前者是通過外設後者是通過CPU寫寄存器。

推挽和開漏的使用:

推挽輸出:可以輸出高,低電平,連接配接數字器件;

開漏輸出:輸出端相當于三極管的集電極. 要得到高電平狀态需要上拉電阻才行. 适合于做電流型的驅動,其吸收電流的能力相對強(一般20ma以内).

那種80c51單片機的IO口就是開漏輸出,是以在使用51單片機時需要加上拉電阻,

(其他博友對于推挽電路和開漏電路的講解)具體的選用大家可以在網上詳細的查一下兩種電路的優缺點,在結合自己實際電路來選擇

在STM32CubeMX中

需要用到開漏輸出或者推挽輸出,左鍵單擊,在彈出的菜單中選擇GPIO_Output,然後在左側的GPIO選項中單擊該IO口,在GPIO mode選項中選擇模式,Output Push Pull為推挽輸出,Out Open Drain為開漏輸出。

STM32CubeMX-GPIO的八種工作模式

在當IO口設定為輸出時,主要的設定參數有四個,

STM32CubeMX-GPIO的八種工作模式

第一個IO輸出的初始狀态,Low表示輸出0,High表示輸出1.

第二個IO的輸出模式上面闡述過。

第三個IO是否上拉或下拉上面闡述過。

第四個IO的輸出速度,就M4而言有4中最大速度:2MHz、25MHz、50MHz、100MHz。

在選擇中有Low、Medium、High、Very High

void MX_GPIO_Init(void)
{
  /*Configure GPIO pin Output Level */
  HAL_GPIO_WritePin(GPIOF, LED1_Pin|LED2_Pin, GPIO_PIN_RESET);
  /*Configure GPIO pins : PFPin PFPin */
  GPIO_InitStruct.Pin = LED1_Pin|LED2_Pin;
  GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
  GPIO_InitStruct.Pull = GPIO_NOPULL;
  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
  HAL_GPIO_Init(GPIOF, &GPIO_InitStruct);
}
/** @defgroup GPIO_speed_define  GPIO speed define
  * @brief GPIO Output Maximum frequency
  * @{
  */
#define  GPIO_SPEED_FREQ_LOW         0x00000000U  /*!< IO works at 2 MHz, please refer to the product datasheet */
#define  GPIO_SPEED_FREQ_MEDIUM      0x00000001U  /*!< range 12,5 MHz to 50 MHz, please refer to the product datasheet */
#define  GPIO_SPEED_FREQ_HIGH        0x00000002U  /*!< range 25 MHz to 100 MHz, please refer to the product datasheet  */
#define  GPIO_SPEED_FREQ_VERY_HIGH   0x00000003U  /*!< range 50 MHz to 200 MHz, please refer to the product datasheet  */
           

通過追溯,可以看到在代碼裡做了宏定義,

STM32CubeMX-GPIO的八種工作模式

我們對A0、F9、F10三個引腳做了如下配置

STM32CubeMX-GPIO的八種工作模式

生成的IO配置如下

GPIO_InitTypeDef GPIO_InitStruct = {0};

  /* GPIO Ports Clock Enable */
  __HAL_RCC_GPIOF_CLK_ENABLE();
  __HAL_RCC_GPIOH_CLK_ENABLE();
  __HAL_RCC_GPIOA_CLK_ENABLE();

  /*Configure GPIO pin Output Level */
  HAL_GPIO_WritePin(GPIOF, LED1_Pin|LED2_Pin, GPIO_PIN_SET);

  /*Configure GPIO pin : PtPin */
  GPIO_InitStruct.Pin = LED1_Pin;
  GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_OD;
  GPIO_InitStruct.Pull = GPIO_NOPULL;
  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
  HAL_GPIO_Init(LED1_GPIO_Port, &GPIO_InitStruct);

  /*Configure GPIO pin : PtPin */
  GPIO_InitStruct.Pin = LED2_Pin;
  GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
  GPIO_InitStruct.Pull = GPIO_NOPULL;
  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
  HAL_GPIO_Init(LED2_GPIO_Port, &GPIO_InitStruct);

  /*Configure GPIO pin : PtPin */
  GPIO_InitStruct.Pin = WK_UP_Pin;
  GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
  GPIO_InitStruct.Pull = GPIO_PULLDOWN;
  HAL_GPIO_Init(WK_UP_GPIO_Port, &GPIO_InitStruct);
           
while (1)
  {
    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
		if(HAL_GPIO_ReadPin(WK_UP_GPIO_Port,WK_UP_Pin))//讀取Io目前狀态,如果為1進入
		{
			HAL_Delay(100);//延時消抖
			if(HAL_GPIO_ReadPin(WK_UP_GPIO_Port,WK_UP_Pin))//再次讀取IO目前狀态如果為1進入
			{
		
				HAL_GPIO_WritePin(LED1_GPIO_Port,LED1_Pin,0);//IO口輸出0
				HAL_GPIO_WritePin(LED2_GPIO_Port,LED2_Pin,0);	//IO輸出0		
			}
		}
		while(HAL_GPIO_ReadPin(WK_UP_GPIO_Port,WK_UP_Pin));//等待按鍵松開
  }
           

我們通過按按鍵來點亮LED,這裡的按鍵防抖和按鍵松開檢測的處理方式很不好,占用資源尤其while,用不好容易卡死在這裡,這裡隻是簡單用用,後期我們會用狀态機來做。基于STM32按鍵的防抖和松開處理:狀态機

繼續閱讀