GPIO的意思是通用輸入輸出端口,可通過軟件配置成輸入或者輸出端。即可以通過GPIO口輸出高低電平或者通過GPIO口讀入引腳狀態是高電平還是低電平。大部分引腳除了當GPIO使用外,還可以復用為外設功能引腳。如UART外設與其他硬件進行數據交互。
CW32L083的每組GPIO都有20個寄存器,除了基礎的配置寄存器、數據寄存器、位置位/清零寄存器、位清零寄存器、鎖定寄存器、復用功能寄存器外,還配置了位翻轉寄存器,中斷數字濾波寄存器等,讓操作更加快捷。同時提供完善的固件庫函數,方便工程師快速開發測試,增強可移植性。
GPIO端口可配置成8種工作模式
4種輸入模式
1.浮空輸入
2.輸入上拉
3.輸入下拉
4.模擬輸入
4種輸出模式
1.開漏輸出
2.推挽式輸出
3.開漏復用功能
4.推挽式復用功能
GPIO功能框圖
初始化GPIO可使用void GPIO_Init(GPIO_TypeDef *GPIOx, GPIO_InitTypeDef *GPIO_Init)函數,此函數在cw32l083_gpio.c中有詳細的配置,其中的第一個參數GPIO_TypeDef是一個結構體類型,在cw32l083.h中有詳細定義,包含著每組GPIO的20個寄存器。
typedefstruct{寫法DIR_f;//輸入輸出方向寄存器OPENDRAIN_f;//輸出模式寄存器PDR_f;//下拉電阻寄存器PUR_f;//上拉電阻寄存器AFRH_f;//復用功能寄存器高段AFRL_f;//復用功能寄存器低段ANALOG_f;//模擬數字配置寄存器RISEIE_f;//上升沿中斷使能寄存器FALLIE_f;//下降沿中斷使能寄存器HIGHIE_f;//高電平中斷使能寄存器LOWIE_f;//低電平中斷使能寄存器ISR_f;//中斷標志寄存器ICR_f;//中斷標志清除寄存器LCKR_f;//配置鎖定寄存器FILTER_f;//中斷數字濾波器配置寄存器IDR_f;//輸入數據寄存器ODR_f;//輸出數據寄存器BRR_f;//位清零寄存器BSRR_f;//位置位清零寄存器TOG_f;//位翻轉寄存器}GPIO_TypeDef;
第二個參數GPIO_InitTypeDef也是一個結構體,在cw32l083_gpio.h中可查看其定義。
typedefstruct{uint32_tPins;uint32_tMode;uint32_tIT;}GPIO_InitTypeDef;
下面舉一個簡單的例子配置一個IO口翻轉,可實現閃燈實驗。
int32_t main(void)
{
GPIO_InitTypeDef GPIO_InitStruct = {0};
RCC_HSI_Enable(RCC_HSIOSC_DIV6);
__RCC_GPIOC_CLK_ENABLE(); //打開GPIOC的時鐘
GPIO_InitStruct.IT = GPIO_IT_NONE;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Pins = GPIO_PIN_2|GPIO_PIN_3;
GPIO_Init(CW_GPIOC, GPIO_InitStruct);
while (1)
{
GPIO_TogglePin(CW_GPIOC,GPIO_PIN_2|GPIO_PIN_3);
Delay(0xFFFF); //延遲函數
}
}
void Delay(__IO uint16_t nCount)
{
/* Decrement nCount value */
while (nCount != 0)
{
nCount--;
}
}
例程中使用PC02和PC03引腳進行IO口翻轉實驗,官方CW32L083VCT6的評估板上這兩個引腳外接LED燈,可以看到LED周期閃爍的效果。
其中CW_GPIOC,GPIO_PIN_0以及GPIO_MODE_OUTPUT_PP都是定義在頭文件中的宏定義,如下面第一行為CW_GPIOC端口地址映射。
#define CW_GPIOC ((GPIO_TypeDef*) GPIOC_BASE)
#define GPIOC_BASE 0x48000800UL
#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 */
#define GPIO_MODE_ANALOG (0X00)
#define GPIO_MODE_INPUT (0x10)
#define GPIO_MODE_INPUT_PULLUP (0x11)
#define GPIO_MODE_INPUT_PULLDOWN (0x12)
#define GPIO_MODE_OUTPUT_PP (0x20)
#define GPIO_MODE_OUTPUT_OD (0x21)
上面的例子是使用庫函數配置的,也可以用寄存器操作,具體步驟如下。
//開啟HSI并6分頻,Sysclk=HCLK=PCLK=8MHz
CW_SYSCTRL->HSI=(5<
CW_SYSCTRL->CR1|=SYSCTRL_BYPASS|SYSCTRL_CR1_HSIEN_Msk; //Enable HSI
while ((CW_SYSCTRL->HSI SYSCTRL_HSI_STABLE_Msk) != SYSCTRL_HSI_STABLE_Msk) //Wait stable
{
;
}
//開啟GPIOC的時鐘
REGBITS_SET(CW_SYSCTRL->AHBEN, RCC_AHB_PERIPH_GPIOC);
//配置PC02和PC03為數字功能推挽輸出
CW_GPIOC->ANALOG_f.PIN2 = 0; //將PC02設置為數字功能
CW_GPIOC->DIR_f.PIN2 = 0; //將PC02設置成輸出模式
CW_GPIOC->OPENDRAIN_f.PIN2 = 0; //將PC02設置成推挽模式
CW_GPIOC->ANALOG_f.PIN3 = 0; //將PC03設置為數字功能
CW_GPIOC->DIR_f.PIN3 = 0; //將PC03設置為輸出模式
CW_GPIOC->OPENDRAIN_f.PIN3 = 0; //將PC03設置為推挽模式
while (1)
{
CW_GPIOC->TOG=bv2; //PC02翻轉
Delay(0xFFFF);
CW_GPIOC->TOG=bv3; //PC03翻轉
Delay(0xFFFF);
}
下面以CW32L083為例通過配置GPIO引腳來驅動SPI2外設,查閱CW32L083的用戶手冊可以得知, SPI2可以通過PA00,PA01,PA02,PA03復用實現,這個就是上文提到的GPIO口的復用功能。
PA00_AFx_SPI2MISO() //將PA00復用成SPI2的MISO線
PA01_AFx_SPI2MOSI() //將PA01復用成SPI2的MOSI線
PA02_AFx_SPI2SCK() //將PA02復用成SPI2的時鐘線
PA03_AFx_SPI2CS() //將PA03復用成SPI2的片選線,如需操作片選線,有特定函數
GPIO_InitTypeDef GPIO_InitStructure = {0};
GPIO_InitStructure.Pins =GPIO_PIN_1|GPIO_PIN_2 |GPIO_PIN_3;
GPIO_InitStructure.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStructure.IT= GPIO_IT_NONE;
GPIO_Init(CW_GPIOA, GPIO_InitStructure);
GPIO_InitStructure.Pins =GPIO_PIN_0;
GPIO_InitStructure.Mode = GPIO_MODE_INPUT;
GPIO_Init(CW_GPIOA, GPIO_InitStructure);
另外我們的GPIO支持外部中斷,具體的配置如下,如果有不清楚的小伙伴可以查看下節CW32中斷控制器,會有詳細講解。
GPIO_InitTypeDef GPIO_InitStruct = {0};
__RCC_GPIOA_CLK_ENABLE();//開啟GPIOA的時鐘
GPIO_InitStruct.IT = GPIO_IT_RISING | GPIO_IT_FALLING; //上升沿或者下降沿觸發
GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
GPIO_InitStruct.Pins =GPIO_PIN_1;
GPIO_Init(CW_GPIOA, GPIO_InitStruct);
//清除PA01中斷標志并使能NVIC
GPIOA_INTFLAG_CLR(bv1);
NVIC_EnableIRQ(GPIOA_IRQn);
上面的例程即可實現外部輸入中斷,PA01在接收到上升沿或者下降沿的信號的時候會進入到中斷函數中去執行相關的程序,具體的例程可以參考官方CW32L083的gpio_int_filter例子。
下面介紹的是CW32L083的GPIO所相關的函數及其功能。
1.void GPIO_SWD2GPIO(void);
將PA13/PA14 SWD設置成GPIO
2.void GPIO_GPIO2SWD(void);
將PA13/PA14設置成SWD
3.void GPIO_LockPin(GPIO_TypeDef *GPIOx, uint16_t GPIO_Pins);
鎖定指定引腳配置項,可同時設置多個引腳
4.void GPIO_DeInit(GPIO_TypeDef *GPIOx, uint32_t GPIO_Pins);
GPIO去初始化,可同時設置多個引腳或單個引腳
5.void GPIO_Init(GPIO_TypeDef *GPIOx, GPIO_InitTypeDef *GPIO_Init);
GPIO 初始化,可同時設置多個引腳或單個引腳
6.void GPIO_ConfigFilter(GPIO_TypeDef *GPIOx, uint16_t GPIO_Pins, uint32_t FltClk);
配置端口濾波
7.void GPIO_WritePin(GPIO_TypeDef *GPIOx, uint16_t GPIO_Pins, GPIO_PinState PinState);
設置指定引腳電平,可同時設置多個引腳
8.void GPIO_Write(GPIO_TypeDef* GPIOx, uint16_t Value);
設置指定引腳端口的輸出值
9.void GPIO_TogglePin(GPIO_TypeDef *GPIOx, uint16_t GPIO_Pins);
翻轉指定引腳電平,可同時設置多個引腳
10.GPIO_PinState GPIO_ReadPin(GPIO_TypeDef *GPIOx, uint16_t GPIO_Pin);
獲取一個引腳的電平
以上是CW32通用輸入輸出端口的介紹。
來源:武漢芯源半導體
審核編輯:湯梓紅
-
寄存器
+關注
關注
31文章
5363瀏覽量
121162 -
端口
+關注
關注
4文章
990瀏覽量
32208 -
GPIO
+關注
關注
16文章
1216瀏覽量
52378
發布評論請先 登錄
相關推薦
評論