특징
- 80 Standard I/Os (5V tolerant, 20 mA drive)
- 18 MHz Toggling
- Configurable Output Speed up to 50 MHz
- Up to 16 Analog Inputs
- Alternate Functions pins (like USARTx, TIMx, I2Cx, SPIx, CAN, USB…)
- All I/Os can be set-up as external interrupt (up to 16 lines at time)
- One I/O can be used as Wake-Up from STANDBY (PA.00)
- One I/O can be set-up as Tamper Pin (PC.13)
- All Standard I/Os are shared in 5 ports (GPIOA..GPIOE)
- Atomic Bit Set and Bit Reset using BSRR and BRR registers
- Locking mechanism to avoid spurious write in the IO registers
GPIO관련 registers
CRL - Port Control Register low
CRH - Port Control Register High
IDR - Input Data Register
ODR Output Data Register
BSRR Bit Set Reset Register
BRR Bit Reset Register
LCKR Lock Register
EVCR Event Control Register
MAPR Remap Debug and AF Register
EXTICR EXTI Line 0 to Line 15 Configuration Register
GPIO Configuration
고속을 요하지 않는 포트 설정은 간단히 GPIO_DeInit()함수에 원하는 설정값 구조체를 입력하면 되므로 쉽게 설정가능한다.
GPIO클럭 APB2를 eable하고 원하는 포트와 클럭속도, 입출력 모드를 설정하면 GPIO Configuration이 된다.
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_Init(LED1_PORT, &GPIO_InitStructure)
void GPIO_DeInit(GPIO_TypeDef* GPIOx) { switch (*(u32*)&GPIOx) { case GPIOA_BASE: RCC_APB2PeriphResetCmd(RCC_APB2Periph_GPIOA, ENABLE); RCC_APB2PeriphResetCmd(RCC_APB2Periph_GPIOA, DISABLE); break; case GPIOB_BASE: RCC_APB2PeriphResetCmd(RCC_APB2Periph_GPIOB, ENABLE); RCC_APB2PeriphResetCmd(RCC_APB2Periph_GPIOB, DISABLE); break; case GPIOC_BASE: RCC_APB2PeriphResetCmd(RCC_APB2Periph_GPIOC, ENABLE); RCC_APB2PeriphResetCmd(RCC_APB2Periph_GPIOC, DISABLE); break; case GPIOD_BASE: RCC_APB2PeriphResetCmd(RCC_APB2Periph_GPIOD, ENABLE); RCC_APB2PeriphResetCmd(RCC_APB2Periph_GPIOD, DISABLE); break; case GPIOE_BASE: RCC_APB2PeriphResetCmd(RCC_APB2Periph_GPIOE, ENABLE); RCC_APB2PeriphResetCmd(RCC_APB2Periph_GPIOE, DISABLE); break; default: break; } } |
IO포트가 출력으로 설정되면 Output Buffer가 사용가능해 진다.
따라서 포트를 0 또는 1로 출력하기 위해 BSRR(Bit Set Reset Register), BRR(Bit Reset Register) 레지스터에 값을 출력하면 된다.
//GPIO핀을 high로 출력
GPIOx->BSRR = GPIO_Pin
//GPIO핀을 low로 출력
GPIOx->BRR = GPIO_Pin
#define cbi(Port, Bit) Port->BRR = Bit
ODR(Output Data Register)는 쓰고 읽을 수 있으므로 비트토글에 있어 유용하게 사용할 수 있다.
GPIOx->ODR ^= GPIO_Pin
보드상의 LED를 제어하기 위해 아래와 같이 설정하였다.
#define LED1_BIT GPIO_Pin_8
#define LED1_PORT GPIOB
#define Led1Off() LED1_PORT->BRR |= LED1_BIT
#define Led1On() LED1_PORT-> |= LED1_BIT
#define Led1Toggle() LED1_PORT->ODR ^= LED1_BIT
JATG핀을 GPIO로 사용하기 위해 처리해야 할 사항
* STM32에서 JTAG핀은 RCC_APB2Periph_AFIO 클럭을 설정해야 정상동작 한다.
//Enable GPIOA, GPIOB and AFIO clocks
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOB | RCC_APB2Periph_AFIO, ENABLE);
//Disable the Serial Wire Jtag Debug Port SWJ-DP
GPIO_PinRemapConfig(GPIO_Remap_SWJ_Disable, ENABLE);
//Configure PA.13 (JTMS/SWDAT), PA.14 (JTCK/SWCLK) and PA.15 (JTDI) as output push-pull
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13 | GPIO_Pin_14 | GPIO_Pin_15;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_Init(GPIOA, &GPIO_InitStructure);
//Configure PB.03 (JTDO) and PB.04 (JTRST) as output push-pull
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3 | GPIO_Pin_4;
GPIO_Init(GPIOB, &GPIO_InitStructure);
SWD 를 이용하고 나머지 JTAG핀을 GPIO로 사용하고 싶다면 GPIO_PinRemapConfig()함수에서 GPIO_Remap_SWJ_JTAGDisable 를 설정하면 된다.
#define GPIO_Remap_SWJ_NoJTRST ((u32)0x00300100) /* Full SWJ Enabled (JTAG-DP + SW-DP) but without JTRST */
#define GPIO_Remap_SWJ_JTAGDisable ((u32)0x00300200) /* JTAG-DP Disabled and SW-DP Enabled */
#define GPIO_Remap_SWJ_Disable ((u32)0x00300400) /* Full SWJ Disabled (JTAG-DP + SW-DP) */
고속으로 GPIO를 제어 하기 위해 ST에서 제공하는 함수로는 한계가 있다.
직접 레지스터를 제어 해야 한다.
특히 GPIO 입출력 방향을 자주 바꾸어야 할 경우 아무래도 제공함수는 설정하는것이 너무 많다.
일단 PORTB 하위를 Data포트로 사용하기 때문에 아래와 같이 정의해서 사용하면 편리하다.
#define GPIOB_DIR_IN() GPIOB->CRL = 0x88888888;
#define GPIOB_DIR_OUT() GPIOB->CRL = 0x33333333;