본문 바로가기

Lecture/ARM

stm32f407 I/O 제어 (2). Initializes the GPIOx peripheral

STM32F4 DISCOVERY BOARD 를 이용한 I/O 제어 


지난시간에는 첫번째 줄  클럭 enable 에 대해서 작성을 했었다. 

  /* GPIOD Periph clock enable */

  RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOD, ENABLE);



오늘은 그럼 포트의 출력설정에 대해서 알아보도록 하자

(이게 얼마나 길어질지는 나도 모르겠네...ㅠㅠ


  /* Configure PD12, PD13, PD14 and PD15 in output pushpull mode */

  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10 | GPIO_Pin_13| GPIO_Pin_14| GPIO_Pin_15;

  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;

  GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;

  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;

  GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;

  GPIO_Init(GPIOD, &GPIO_InitStructure);


GPIO_InitStructure란 변수는 main 함수에 아래와 같이 선언되어 있다. 

GPIO_InitTypeDef  GPIO_InitStructure;


그럼 우리는 아래의 함수를 캐보도록 하자 

GPIO_InitTypeDef


함수가 아니라 구조체로군...  이 구조체(struct)는 stm32f4xx.gpio.h에 있다.




그러면 각각 GPIO_Pin, GPIO_Mode, GPIO_Speed, GPIO_OType, GPIO_PuPd 에 대해 알아보도록 하자!!


GPIO Configuration Mode 에는 

GPIO Input, Output, Alternate function,Analog의 mode 가 있다.


GPIO Output type은 

PP(push-pull), OD(open-drain) 이 있다.


GPIO Output Maximum frequency

는 2M, 25M, 50M 100MHz가 있으며 이건 솔찍히 무슨 내용인지 잘 모르겠다. 

데이타시트를 보니 최대 속도를 소프트웨어적으로 제한시켜준다는거 같은데 그러면 어떻게 동작되는지 그거에 대해서는 모르겠다.


GPIO Configuration PullUp PullDown

GP(general-purpose), PU(pull-up), PD(pull-down) 모드가 있다.  

여기서 GP는 아마도 NOPULL로 선언된듯 싶다.


여기서 함수들의 기능은 위의 코드와 데이터 시트를 보면 적관적으로 이해되리라 생각된다. 

아날로그 입력과 아날로그 출력, 입출력, Alternate function(타이머, I2C 등의 확장기능의 핀맵핑이라고 보면 된다), 이 있고

push pull 반전, open-drain,  pull-up, pull-down 등은 그래프를 보고 직관적으로 이해하면 될 듯 싶다.


이제 각각의 구조체와 함수들을 살펴보도록 하자.


GPIO_Pin 같은 경우 stm32f4xx_gpio.h 파일에 

#define GPIO_Pin_0                 ((uint16_t)0x0001)  /* Pin 0 selected */

에서부터 15번핀까지 그리고 


#define GPIO_Pin_All               ((uint16_t)0xFFFF)  /* All pins selected */

모든핀 선택 해서 핀정보에 대해 정의되어 있다. 

그럼 GPIO_Pin 에서 설정할때는 각각의 핀을 비트연산을 통해 계산한다고 생각하면 된다. 


따라서 위이 예제에서도 소스코드를 보면 

  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10 | GPIO_Pin_13| GPIO_Pin_14| GPIO_Pin_15;

와 같아 비트연산을 통해 값을 설정한 것을 확인할 수 있다. 


나머지 부분들은 enum을 통해 선언되었으므로 구조체 초기화에 대해서는 이해했을것이다. 


그러면 그 다음으로 나온 함수가 GPIO_Init()함수이다. 


void GPIO_Init(GPIO_TypeDef* GPIOx, GPIO_InitTypeDef* GPIO_InitStruct);

위의 함수는 stm32f4xx_gpio.h에 선언되어 있고 stm32f4xx_gpio.c 에 정의되어 있다. 


코드를 분석해보면 for 문으로 0~15번 핀까지 반복한다.

여기서 GPIO_InitStructure.GPIO)Pin 에서 설정된 핀들의 경우 레지스터 값을 설정하게 된다.

일단 mode를 설정하고 output mode 일 경우 output type, speed, pupd의 값들을 세팅하게 된다.


세팅 과정은 각각의 output type, speed, pupd의 레지스터를 지우고 다시쓰는 방식을 취하고 있다.


한번에 연산해서 레지스터에 집어넣는게 빠르지 않을까란 생각이 들긴 한다. 


CMSIS 에 의해 직접 억세스 하지 않고 간접적으로 접근하는 방식을 선택한 것일까? 

하여튼 직접 억세스하여 레지스터를 기록하는거보다는 많은 클럭을 잡아먹을것이라 예상된다. 


하지만 M4의 성능이라면 그 몇클럭이 의미가 있을가 싶다. 그리고 이것의 경우 계속사용하는게 아니라 초기화이기 때문에 포트의 상태를 변화시키지 않는 한 초기화 시킬때 한번이라면 

신경쓰지 않아도 될듯 하다.



아래의 내용도 진행을 시키려 했는데.......

SetBits, ResetBits 를 살펴보던중 이 명령어들은 bit banding 이랑 관련이 되어있다는걸 알게 되었다.

이건...대박아이디어인데?....


비트밴딩이란게 이런거구나.......


수정 : 공부해본 결과 bit banding이랑은 다르다. 마치 RS 플립플롭처럼 레지스터를 set reset 해주는 역할을 한다. 

이것만으로도 편한걸?



그런 의미로 SetBits랑 ResetBits는 다음블로깅으로 넘기도록 하겠다.....  ㅋㅋㅋㅋ!!!


Cortex-M4....대박이야!!!!




  while (1)

  {

    /* PD12 to be toggled */

    GPIO_SetBits(GPIOD, GPIO_Pin_12);

    GPIO_ResetBits(GPIOD, GPIO_Pin_1|GPIO_Pin_13|GPIO_Pin_14|GPIO_Pin_15);


  }