目錄
常用的就是這幾個:
1 初始化端口
5 讀取端口的輸出數據
7,8 給端口寫1,0
14 選擇中斷線
——————————————————————————————————————
位帶操作可以參考這篇文章
https://blog.csdn.net/oshan2012/article/details/95938302
———————————————————————————————————————
1.GPIO設置函數(端口號,對端口的設置)
/**
* @brief Initializes the GPIOx peripheral according to the specified
* parameters in the GPIO_InitStruct.
* @param GPIOx: where x can be (A..G) to select the GPIO peripheral.
* @param GPIO_InitStruct: pointer to a GPIO_InitTypeDef structure that
* contains the configuration information for the specified GPIO peripheral.
* @retval None
*/
假設使用a口
void GPIO_Init(GPIO_TypeDef* GPIOx, GPIO_InitTypeDef* GPIO_InitStruct)
{
uint32_t currentmode = 0x00, currentpin = 0x00, pinpos = 0x00, pos = 0x00;
uint32_t tmpreg = 0x00, pinmask = 0x00;
/* Check the parameters */
assert_param(IS_GPIO_ALL_PERIPH(GPIOx));
assert_param(IS_GPIO_MODE(GPIO_InitStruct->GPIO_Mode));
assert_param(IS_GPIO_PIN(GPIO_InitStruct->GPIO_Pin)); //斷言機制,就是判斷給進來的參數是不是符合要求的參數。防止使用者亂給參數
/*---------------------------- GPIO Mode Configuration -----------------------*/
currentmode = ((uint32_t)GPIO_InitStruct->GPIO_Mode) & ((uint32_t)0x0F);
//這個大有玄機
/*
typedef enum
{ GPIO_Mode_AIN = 0x0,
GPIO_Mode_IN_FLOATING = 0x04,//0100
GPIO_Mode_IPD = 0x28, //1000
GPIO_Mode_IPU = 0x48,
GPIO_Mode_Out_OD = 0x14,//0100
GPIO_Mode_Out_PP = 0x10,
GPIO_Mode_AF_OD = 0x1C,//1100
GPIO_Mode_AF_PP = 0x18
}GPIOMode_TypeDef;
這便是GPIOmode裏邊的東西。我們可以發現,他所有的參數最低兩位都是0.這裏記住,後邊要考
而且高4位的最低位,也就是左邊的數字是0x1*開頭的都是輸出模式,比如0x14。開頭不是0x1的就是輸入模式。4輸入4輸出。
所以上邊那句0x0f與他的低位,就是把判斷輸入還是輸出剔除了。就留下低四位,用來判斷她是哪種類型的。
*/
if ((((uint32_t)GPIO_InitStruct->GPIO_Mode) & ((uint32_t)0x10)) != 0x00)//這句話判斷的是她是否是輸出模式。因爲輸出模式是0x1*。
{
/* Check the parameters */
assert_param(IS_GPIO_SPEED(GPIO_InitStruct->GPIO_Speed));
/* Output mode */
currentmode |= (uint32_t)GPIO_InitStruct->GPIO_Speed;
/*
typedef enum
{
GPIO_Speed_10MHz = 1,
GPIO_Speed_2MHz,
GPIO_Speed_50MHz
}GPIOSpeed_TypeDef;
分別是1,2,3.枚舉類型。也就是0001,0010,0011
上面說到,GPIOmode的最低兩位都是0,所以
currentmode 或上這三個 ,不會影響
*/
}
/*---------------------------- GPIO CRL Configuration ------------------------*/
/* Configure the eight low port pins */
if (((uint32_t)GPIO_InitStruct->GPIO_Pin & ((uint32_t)0x00FF)) != 0x00)
//低8位
{
tmpreg = GPIOx->CRL;
/*這些就是每個引腳的定義。GPIOA叫端口port,pin0叫引腳。每個端口16個引腳
#define GPIO_Pin_0 ((uint16_t)0x0001) /*!< Pin 0 selected */
#define GPIO_Pin_1 ((uint16_t)0x0002) /*!< Pin 1 selected */
#define GPIO_Pin_2 ((uint16_t)0x0004) /*!< Pin 2 selected */
#define GPIO_Pin_3 ((uint16_t)0x0008) /*!< Pin 3 selected */
#define GPIO_Pin_4 ((uint16_t)0x0010) /*!< Pin 4 selected */
#define GPIO_Pin_5 ((uint16_t)0x0020) /*!< Pin 5 selected */
#define GPIO_Pin_6 ((uint16_t)0x0040) /*!< Pin 6 selected */
#define GPIO_Pin_7 ((uint16_t)0x0080) /*!< Pin 7 selected */
#define GPIO_Pin_8 ((uint16_t)0x0100) /*!< Pin 8 selected */
#define GPIO_Pin_9 ((uint16_t)0x0200) /*!< Pin 9 selected */
#define GPIO_Pin_10 ((uint16_t)0x0400) /*!< Pin 10 selected */
#define GPIO_Pin_11 ((uint16_t)0x0800) /*!< Pin 11 selected */
#define GPIO_Pin_12 ((uint16_t)0x1000) /*!< Pin 12 selected */
#define GPIO_Pin_13 ((uint16_t)0x2000) /*!< Pin 13 selected */
#define GPIO_Pin_14 ((uint16_t)0x4000) /*!< Pin 14 selected */
#define GPIO_Pin_15 ((uint16_t)0x8000) /*!< Pin 15 selected */
#define GPIO_Pin_All ((uint16_t)0xFFFF) /*!< All pins selected */
*/
for (pinpos = 0x00; pinpos < 0x08; pinpos++)//8個引腳
{
pos = ((uint32_t)0x01) << pinpos;//選擇對應的引腳 第2次0x01 ,0001 左移1位,0010
/* Get the port pins position */
//pinpos = 0x01 ; pos = 0x02; currentpin = 0010
currentpin = (GPIO_InitStruct->GPIO_Pin) & pos;//再次確認
if (currentpin == pos)
{
pos = pinpos << 2;//0100,4
/* Clear the corresponding low control register bits */
pinmask = ((uint32_t)0x0F) << pos;//11110000
tmpreg &= ~pinmask; //GPIOx->CRL;//00001111
/* Write the mode configuration in the corresponding bits */
tmpreg |= (currentmode << pos);//0010<<4=0010 0000
/* Reset the corresponding ODR bit */
if (GPIO_InitStruct->GPIO_Mode == GPIO_Mode_IPD)
{
GPIOx->BRR = (((uint32_t)0x01) << pinpos);
}
else
{
/* Set the corresponding ODR bit */
if (GPIO_InitStruct->GPIO_Mode == GPIO_Mode_IPU)
{
GPIOx->BSRR = (((uint32_t)0x01) << pinpos);
}
}
}
}
GPIOx->CRL = tmpreg;
}
/*---------------------------- GPIO CRH Configuration ------------------------*/
/* Configure the eight high port pins */
if (GPIO_InitStruct->GPIO_Pin > 0x00FF)
{
tmpreg = GPIOx->CRH;
for (pinpos = 0x00; pinpos < 0x08; pinpos++)
{
pos = (((uint32_t)0x01) << (pinpos + 0x08));
/* Get the port pins position */
currentpin = ((GPIO_InitStruct->GPIO_Pin) & pos);
if (currentpin == pos)
{
pos = pinpos << 2;
/* Clear the corresponding high control register bits */
pinmask = ((uint32_t)0x0F) << pos;
tmpreg &= ~pinmask;
/* Write the mode configuration in the corresponding bits */
tmpreg |= (currentmode << pos);
/* Reset the corresponding ODR bit */
if (GPIO_InitStruct->GPIO_Mode == GPIO_Mode_IPD)
{
GPIOx->BRR = (((uint32_t)0x01) << (pinpos + 0x08));
}
/* Set the corresponding ODR bit */
if (GPIO_InitStruct->GPIO_Mode == GPIO_Mode_IPU)
{
GPIOx->BSRR = (((uint32_t)0x01) << (pinpos + 0x08));
}
}
}
GPIOx->CRH = tmpreg;
}
}
都註釋在裏邊了。
2.GPIO初始化結構體函數()
把對端口的設置結構體初始化。比如GPIO_Pin_All,就是全置一,讓人一看就知道,這是初始化完的。
/**
* @brief Fills each GPIO_InitStruct member with its default value.
* @param GPIO_InitStruct : pointer to a GPIO_InitTypeDef structure which will
* be initialized.
* @retval None
*/
void GPIO_StructInit(GPIO_InitTypeDef* GPIO_InitStruct)
{
/* Reset GPIO init structure parameters values */
GPIO_InitStruct->GPIO_Pin = GPIO_Pin_All;
GPIO_InitStruct->GPIO_Speed = GPIO_Speed_2MHz;
GPIO_InitStruct->GPIO_Mode = GPIO_Mode_IN_FLOATING;
}
——————————————————————————————————
3.讀取某個端口的某個引腳的輸入值(端口,引腳)
/**
* @brief Reads the specified input port pin.
* @param GPIOx: where x can be (A..G) to select the GPIO peripheral.
* @param GPIO_Pin: specifies the port bit to read.
* This parameter can be GPIO_Pin_x where x can be (0..15).
* @retval The input port pin value.
*/
uint8_t GPIO_ReadInputDataBit(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin)
{
uint8_t bitstatus = 0x00;
/* Check the parameters */
assert_param(IS_GPIO_ALL_PERIPH(GPIOx));
assert_param(IS_GET_GPIO_PIN(GPIO_Pin));
if ((GPIOx->IDR & GPIO_Pin) != (uint32_t)Bit_RESET)
//爲什麼這樣判斷呢?因爲gpio_pin的定義是0x0001,0x0002,0x0004,0x0008這種樣子定義的
//所以idr與對應的引腳後,要判斷1在哪一位很複雜,不如直接判斷是不是不等於0,只要不等於0,那就說明
//這一位肯定是1.非常巧妙
{
bitstatus = (uint8_t)Bit_SET;
}
else
{
bitstatus = (uint8_t)Bit_RESET;
}
return bitstatus;
}
—————————————————————————
4.讀取某個端口的所有引腳輸入數據
對應的IDR寄存器是隻讀的。
/**
* @brief Reads the specified GPIO input data port.
* @param GPIOx: where x can be (A..G) to select the GPIO peripheral.
* @retval GPIO input data port value.
*/
uint16_t GPIO_ReadInputData(GPIO_TypeDef* GPIOx)
{
/* Check the parameters */
assert_param(IS_GPIO_ALL_PERIPH(GPIOx));
return ((uint16_t)GPIOx->IDR);
}
——————————————————
5.讀取某個端口的某個引腳的輸出數據
ODR寄存器是可讀可寫的。所以讀取方法和上邊一樣
/**
* @brief Reads the specified output data port bit.
* @param GPIOx: where x can be (A..G) to select the GPIO peripheral.
* @param GPIO_Pin: specifies the port bit to read.
* This parameter can be GPIO_Pin_x where x can be (0..15).
* @retval The output port pin value.
*/
uint8_t GPIO_ReadOutputDataBit(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin)
{
uint8_t bitstatus = 0x00;
/* Check the parameters */
assert_param(IS_GPIO_ALL_PERIPH(GPIOx));
assert_param(IS_GET_GPIO_PIN(GPIO_Pin));
if ((GPIOx->ODR & GPIO_Pin) != (uint32_t)Bit_RESET)
{
bitstatus = (uint8_t)Bit_SET;
}
else
{
bitstatus = (uint8_t)Bit_RESET;
}
return bitstatus;
}
————————————————————————————
6.讀取某個端口的所有引腳輸出數據
和上邊輸入是一樣的
/**
* @brief Reads the specified GPIO output data port.
* @param GPIOx: where x can be (A..G) to select the GPIO peripheral.
* @retval GPIO output data port value.
*/
uint16_t GPIO_ReadOutputData(GPIO_TypeDef* GPIOx)
{
/* Check the parameters */
assert_param(IS_GPIO_ALL_PERIPH(GPIOx));
return ((uint16_t)GPIOx->ODR);
}
——————————————————————————————
7.給某個端口的某個引腳寫1
/**
* @brief Sets the selected data port bits.
* @param GPIOx: where x can be (A..G) to select the GPIO peripheral.
* @param GPIO_Pin: specifies the port bits to be written.
* This parameter can be any combination of GPIO_Pin_x where x can be (0..15).
* @retval None
*/
void GPIO_SetBits(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin)
{
/* Check the parameters */
assert_param(IS_GPIO_ALL_PERIPH(GPIOx));
assert_param(IS_GPIO_PIN(GPIO_Pin));
GPIOx->BSRR = GPIO_Pin;
}
——————————————————————————
8.給某個端口的某個引腳寫0
BSRR可1可0
BRR只能置0
/**
* @brief Clears the selected data port bits.
* @param GPIOx: where x can be (A..G) to select the GPIO peripheral.
* @param GPIO_Pin: specifies the port bits to be written.
* This parameter can be any combination of GPIO_Pin_x where x can be (0..15).
* @retval None
*/
void GPIO_ResetBits(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin)
{
/* Check the parameters */
assert_param(IS_GPIO_ALL_PERIPH(GPIOx));
assert_param(IS_GPIO_PIN(GPIO_Pin));
GPIOx->BRR = GPIO_Pin;
}
——————————————————————
9.既可以給某個引腳寫1,又可以寫0
評語:脫褲子放屁——多此一舉
/**
* @brief Sets or clears the selected data port bit.
* @param GPIOx: where x can be (A..G) to select the GPIO peripheral.
* @param GPIO_Pin: specifies the port bit to be written.
* This parameter can be one of GPIO_Pin_x where x can be (0..15).
* @param BitVal: specifies the value to be written to the selected bit.
* This parameter can be one of the BitAction enum values:
* @arg Bit_RESET: to clear the port pin
* @arg Bit_SET: to set the port pin
* @retval None
*/
void GPIO_WriteBit(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin, BitAction BitVal)
{
/* Check the parameters */
assert_param(IS_GPIO_ALL_PERIPH(GPIOx));
assert_param(IS_GET_GPIO_PIN(GPIO_Pin));
assert_param(IS_GPIO_BIT_ACTION(BitVal));
if (BitVal != Bit_RESET)
{
GPIOx->BSRR = GPIO_Pin;
}
else
{
GPIOx->BRR = GPIO_Pin;
}
}
————————————————————————
10.直接給整個端口寫
/**
* @brief Writes data to the specified GPIO data port.
* @param GPIOx: where x can be (A..G) to select the GPIO peripheral.
* @param PortVal: specifies the value to be written to the port output data register.
* @retval None
*/
void GPIO_Write(GPIO_TypeDef* GPIOx, uint16_t PortVal)
{
/* Check the parameters */
assert_param(IS_GPIO_ALL_PERIPH(GPIOx));
GPIOx->ODR = PortVal;
}
——————————————————————————————————————————————
11.鎖定端口的配置
每個位對應CRH或CRL中的4個位。因爲CRL、H中每4個位配置一個引腳
/**
* @brief Locks GPIO Pins configuration registers.
* @param GPIOx: where x can be (A..G) to select the GPIO peripheral.
* @param GPIO_Pin: specifies the port bit to be written.
* This parameter can be any combination of GPIO_Pin_x where x can be (0..15).
* @retval None
*/
void GPIO_PinLockConfig(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin)
{
uint32_t tmp = 0x00010000;
/* Check the parameters */
assert_param(IS_GPIO_ALL_PERIPH(GPIOx));
assert_param(IS_GPIO_PIN(GPIO_Pin));
tmp |= GPIO_Pin;
/* Set LCKK bit */
GPIOx->LCKR = tmp;
/* Reset LCKK bit */
GPIOx->LCKR = GPIO_Pin;
/* Set LCKK bit */
GPIOx->LCKR = tmp;
/* Read LCKK bit*/
tmp = GPIOx->LCKR;
/* Read LCKK bit*/
tmp = GPIOx->LCKR;
}
很簡單要鎖哪個就用哪個pin
但是16位置一,或上pin口,得到一個變量
不停操作這個變量和pin口來達到圖中鎖定配置需要的時序
——————————————————————————
12.選擇用作事件輸出的GPIO引腳
/**
* @brief Selects the GPIO pin used as Event output.
* @param GPIO_PortSource: selects the GPIO port to be used as source
* for Event output.
* This parameter can be GPIO_PortSourceGPIOx where x can be (A..E).
* @param GPIO_PinSource: specifies the pin for the Event output.
* This parameter can be GPIO_PinSourcex where x can be (0..15).
* @retval None
*/
void GPIO_EventOutputConfig(uint8_t GPIO_PortSource, uint8_t GPIO_PinSource)
{
uint32_t tmpreg = 0x00;
/* Check the parameters */
assert_param(IS_GPIO_EVENTOUT_PORT_SOURCE(GPIO_PortSource));
assert_param(IS_GPIO_PIN_SOURCE(GPIO_PinSource));
tmpreg = AFIO->EVCR;
/* Clear the PORT[6:4] and PIN[3:0] bits */
tmpreg &= EVCR_PORTPINCONFIG_MASK;
tmpreg |= (uint32_t)GPIO_PortSource << 0x04;
tmpreg |= GPIO_PinSource;
AFIO->EVCR = tmpreg;
}
就是這個寄存器
————————————————————————————————
13.啓用或禁用事件輸出
/**
* @brief Enables or disables the Event Output.
* @param NewState: new state of the Event output.
* This parameter can be: ENABLE or DISABLE.
* @retval None
*/
void GPIO_EventOutputCmd(FunctionalState NewState)
{
/* Check the parameters */
assert_param(IS_FUNCTIONAL_STATE(NewState));
*(__IO uint32_t *) EVCR_EVOE_BB = (uint32_t)NewState;
}
位帶操作,控制這1位
置一後事件就會指導設置好的pin口上
——————————————————————————————
14.選擇用作外部中斷線的GPIO引腳
/**
* @brief Selects the GPIO pin used as EXTI Line.
* @param GPIO_PortSource: selects the GPIO port to be used as source for EXTI lines.
* This parameter can be GPIO_PortSourceGPIOx where x can be (A..G).
* @param GPIO_PinSource: specifies the EXTI line to be configured.
* This parameter can be GPIO_PinSourcex where x can be (0..15).
* @retval None
*/
void GPIO_EXTILineConfig(uint8_t GPIO_PortSource, uint8_t GPIO_PinSource)
{
uint32_t tmp = 0x00;
/* Check the parameters */
assert_param(IS_GPIO_EXTI_PORT_SOURCE(GPIO_PortSource));
assert_param(IS_GPIO_PIN_SOURCE(GPIO_PinSource));
tmp = ((uint32_t)0x0F) << (0x04 * (GPIO_PinSource & (uint8_t)0x03));
AFIO->EXTICR[GPIO_PinSource >> 0x02] &= ~tmp;
AFIO->EXTICR[GPIO_PinSource >> 0x02] |= (((uint32_t)GPIO_PortSource) << (0x04 * (GPIO_PinSource & (uint8_t)0x03)));
}