STM32——GPIO
/* GPIO_InitTypeDef結(jié)構(gòu)體 */
typedef?enum { ??GPIO_Speed_10MHz?=?1,??//枚舉常量,值為?1,代表輸出速率最高為?10MHz ??GPIO_Speed_2MHz,???????//對(duì)不賦值的枚舉變量,自動(dòng)加?1,此常量值為?2 ??GPIO_Speed_50MHz???????//常量值為?3 }?GPIOSpeed_TypeDef; typedef?enum { ??GPIO_Mode_AIN?=?0x0,?//模擬輸入模式 ??GPIO_Mode_IN_FLOATING?=?0x04,?//浮空輸入模式 ??GPIO_Mode_IPD?=?0x28,?//下拉輸入模式 ??GPIO_Mode_IPU?=?0x48,?//上拉輸入模式 ??GPIO_Mode_Out_OD?=?0x14,?//開(kāi)漏輸出模式 ??GPIO_Mode_Out_PP?=?0x10,?//通用推挽輸出模式 ??GPIO_Mode_AF_OD?=?0x1C,??//復(fù)用功能開(kāi)漏輸出 ??GPIO_Mode_AF_PP?=?0x18???//復(fù)用功能推挽輸出 }?GPIOMode_TypeDef; typedef?struct { ??uint16_t?GPIO_Pin;??????????????/*?指定要配置的引腳?*/ ??GPIOSpeed_TypeDef?GPIO_Speed;???/*?指定GPIO引腳輸出的最高頻率?*/ ??GPIOMode_TypeDef?GPIO_Mode;?????/*?指定GPIO引腳工作狀態(tài)?*/ }?GPIO_InitTypeDef;
/*?初始化GPIO?--?GPIO_Init()?*/ 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; ??/*?斷言,用于檢查輸入的參數(shù)是否正確?*/ ??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?的模式配置?-----------------------*/ ??/*把輸入?yún)?shù)?GPIO_Mode?的低四位暫存在?currentmode*/ ??currentmode?=?((uint32_t)GPIO_InitStruct?- ?????????????????>?GPIO_Mode)?&?((uint32_t)0x0F); ??/*判斷是否為輸出模式,輸出模式,可輸入?yún)?shù)中輸出模式的?bit4?位都是?1*/ ??if?((((uint32_t)GPIO_InitStruct?- ????????>?GPIO_Mode)?&?((uint32_t)0x10))?!=?0x00) ??{ ????/*?檢查輸入?yún)?shù)?*/ ????assert_param(IS_GPIO_SPEED(GPIO_InitStruct->GPIO_Speed)); ????/*?輸出模式,所以要配置?GPIO?的速率:00(輸入模式)?01(10MHz)?10(2MHz)?11?*/ ????currentmode?|=?(uint32_t)GPIO_InitStruct->GPIO_Speed; ??} ??/*----------------------------配置?GPIO?的?CRL?寄存器?----------------------- ??-*/ ??/*?判斷要配置的是否為?pin0?~~?pin7?*/ ??if?(((uint32_t)GPIO_InitStruct?- ???????>?GPIO_Pin?&?((uint32_t)0x00FF))?!=?0x00) ??{ ????/*備份原?CRL?寄存器的值*/ ????tmpreg?=?GPIOx->CRL; ????/*循環(huán),一個(gè)循環(huán)設(shè)置一個(gè)寄存器位*/ ????for?(pinpos?=?0x00;?pinpos?<?0x08;?pinpos++) ????{ ??????/*pos?的值為?1?左移?pinpos?位*/ ??????pos?=?((uint32_t)0x01)?<<?pinpos; ??????/*?令?pos?與輸入?yún)?shù)?GPIO_PIN?作位與運(yùn)算,為下面的判斷作準(zhǔn)備?*/ ??????currentpin?=?(GPIO_InitStruct->GPIO_Pin)?&?pos; ??????/*判斷,若?currentpin=pos,說(shuō)明?GPIO_PIN?參數(shù)中含的第?pos?個(gè)引腳需要配置*/ ??????if?(currentpin?==?pos) ??????{ ????????/*pos?的值左移兩位(乘以?4),因?yàn)榧拇嫫髦?4?個(gè)寄存器位配置一個(gè)引腳*/ ????????pos?=?pinpos?<<?2; ????????/*以下兩個(gè)句子,把控制這個(gè)引腳的?4?個(gè)寄存器位清零,其它寄存器位不變*/ ????????pinmask?=?((uint32_t)0x0F)?<<?pos; ????????tmpreg?&=?~pinmask; ????????/*?向寄存器寫(xiě)入將要配置的引腳的模式?*/ ????????tmpreg?|=?(currentmode?<<?pos); ????????/*?復(fù)位?GPIO?引腳的輸入輸出默認(rèn)值*/ ????????/*判斷是否為下拉輸入模式*/ ????????if?(GPIO_InitStruct->GPIO_Mode?==?GPIO_Mode_IPD) ????????{ ??????????/*下拉輸入模式,引腳默認(rèn)置?0,對(duì)?BRR?寄存器寫(xiě)?1?可對(duì)引腳置?0*/ ??????????GPIOx->BRR?=?(((uint32_t)0x01)?<<?pinpos); ????????} ????????else ????????{ ??????????/*判斷是否為上拉輸入模式*/ ??????????if?(GPIO_InitStruct->GPIO_Mode?==?GPIO_Mode_IPU) ??????????{ ????????????/*上拉輸入模式,引腳默認(rèn)值為?1,對(duì)?BSRR?寄存器寫(xiě)?1?可對(duì)引腳置?1*/ ????????????GPIOx->BSRR?=?(((uint32_t)0x01)?<<?pinpos); ??????????} ????????} ??????} ????} ????/*把前面處理后的暫存值寫(xiě)入到?CRL?寄存器之中*/ ????GPIOx->CRL?=?tmpreg; ??} ??/*----------------------------?以下部分是對(duì)?CRH?寄存器配置的?----------------- ??--------當(dāng)要配置的引腳為?pin8?~~?pin15?的時(shí)候,配置?CRH?寄存器,?----- ??-------------?-----這過(guò)程和配置?CRL?寄存器類(lèi)似------------------------------ ??------ ??-------讀者可自行分析,看看自己是否了解了上述過(guò)程--^_^-----------*/ ??/*?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; ??} }