#include typedef enum { portINPUT, portOUTPUT, portOUTPUTOD, portALTOUT, portALTOD, portANALOG } eIOPortMode; int InitIOPort(GPIO_TypeDef* baseGPIO, uint32_t portNum, eIOPortMode mode) { uint32_t bitPortEn = 0; uint32_t bitPortRst = 0; uint32_t portTypeVal = 0x0100; // value bigger than 4-bits combination if (baseGPIO == GPIOA) { bitPortEn = RCC_APB2ENR_IOPAEN; bitPortRst = RCC_APB2RSTR_IOPARST; } if (baseGPIO == GPIOB) { bitPortEn = RCC_APB2ENR_IOPBEN; bitPortRst = RCC_APB2RSTR_IOPBRST; } if (baseGPIO == GPIOC) { bitPortEn = RCC_APB2ENR_IOPCEN; bitPortRst = RCC_APB2RSTR_IOPCRST; } if (baseGPIO == GPIOD) { bitPortEn = RCC_APB2ENR_IOPDEN; bitPortRst = RCC_APB2RSTR_IOPDRST; } if (baseGPIO == GPIOE) { bitPortEn = RCC_APB2ENR_IOPEEN; bitPortRst = RCC_APB2RSTR_IOPERST; } if ((bitPortEn == 0) || (bitPortRst == 0) // not selected known GPIO || (portNum > 15)) // or number of pin to large return 0; // return with error if (!(RCC->APB2ENR & bitPortEn)) // not enabled ? enable required { RCC->APB2ENR |= bitPortEn; RCC->APB2RSTR |= bitPortRst; RCC->APB2RSTR &= ~bitPortRst; } switch (mode) { case portINPUT: portTypeVal = 0x08; break; // 10 00 - Input with pull-up / pull-down, Input mode (reset state) case portOUTPUT: portTypeVal = 0x03; break; // 00 11 - General purpose output push-pull, Output mode, max speed 50 MHz case portOUTPUTOD: portTypeVal = 0x07; break; // 01 11 - General purpose output Open-drain, Output mode, max speed 50 MHz case portALTOUT: portTypeVal = 0x0B; break; // 10 11 - Alternate function output Push-pull, Output mode, max speed 50 MHz case portALTOD: portTypeVal = 0x0F; break; // 11 11 - Alternate function output Push-pull, Output mode, max speed 50 MHz case portANALOG: portTypeVal = 0x00; break; // 00 00 - Analog mode, Input mode (reset state) } if (portTypeVal >= 0x100) // none as result of "case" block return 0; // eturn with error if (portNum < 8) // lower 8 pins are in CRL { baseGPIO->CRL &= ~(0x0f << (portNum * 4)); baseGPIO->CRL |= portTypeVal << (portNum * 4); } else // higher 8 in CRH { portNum -= 8; // CRH foe IO 8-15 baseGPIO->CRH &= ~(0x0f << (portNum * 4)); baseGPIO->CRH |= portTypeVal << (portNum * 4); } return 1; } void WriteGPIO(GPIO_TypeDef* baseGPIO, uint32_t portNum, bool val) { if (val) baseGPIO->ODR |= 1 << portNum; else baseGPIO->ODR &= ~(1 << portNum); } bool ReadGPIO(GPIO_TypeDef* baseGPIO, uint32_t portNum) { return (baseGPIO->IDR & (1 << portNum)) != 0; } void ToggleGPIO(GPIO_TypeDef* baseGPIO, uint32_t portNum) { baseGPIO->ODR ^= 1 << portNum; }