ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • (STM32 무작정 LED켜기 2) GPIO 포트를 이용하여 DATA 출력하기
    Cortex-M3/STM32F103 2010. 5. 13. 13:24
    [임베디드/Cortex-M3] - (STM32 무작정 LED켜기 1) AHB와 APB

    (STM32 무작정 LED켜기 1) 에서 GPIO 에 해당하는 APB2 BUS에 클럭을 공급해줬으니. 이제는 GPIO포트에 DATA를 보내주기만 하면 된다 ! 

    우선 GPIO관련 레지스터를 살펴보면
    (RM0008)'Datasheet에도 있는거같다.'



    GPIOx_CRL : Port configuration register low
    GPIOx_CRH : Port configuration register high
    GPIOx_IDR : Port input data register
    GPIOx_ODR : Port output data register
    GPIOx_BSSR : Port bit set/reset register
    GPIOx_BRR : Port bit reset register
    GPIOx_LCKR : Port configuration lock register

    여기서 잠깐 집고 넘어가야할것은. 레지스터 이름을 보면 GPIOx_CRL, GPIOx_CRH 라고 x가 붙는데 
    (RM0008) 아래그림은 GPIOx_CRL의 레지스터 설명이다.
    뒤에보면 (x=A..G) 라고 적혀있는데 x가 말하는것이 A~G까지 된다. 

    GPIOA_CRL
    GPIOB_CRL
           .
           .
    GPIOG_CRL 

    즉 모든 CRL레지스터는 이름(주소)만 틀릴뿐 같은모양이다. 

    그러므로 A포트를 제어하는것과 B포트를 제어하는것은 레지스터 번지만 틀릴뿐이지 똑같다는 것이다. (CPU입장에서..)
    (CPU입장에서) LED를 켠다는것은 GPIO PORT로 High든 Low든 출력을 내보내야 함으로. ('음.. 말이 어렵네..')
    GPIOx_CRL,  GPIOx_CRH,  
    GPIOx_ODR
    이 3가지 레지스터를 봐야한다.


    GPIOx_CRL,  GPIOx_CRH
    Port Configuration Register Low
    Port Configuration Register High

    0~3 Bit의 CNF0, MODE0 이 두가지가 계속 반복된다 
    MODEx (x=0...15) 즉 외부로 나와있는 Port의 갯수를 말하는것이다.
    (PORTA는 PA0, PA1, ... PA15까지 있으므로 각 해당하는 Bit를 설정할수 있는것이다) 

    GPIOx_CRL (Low)는  0~7 Bit까지 설정할수있고
    GPIOx_CRH (High)는 8~15 Bit까지 설정할수있다.

    아래그램(RM0008)을보면 CNF와 MODE를 설정하는데있어서의 설명이 나와있다.
    Reset Value가 0x4444 4444이므로 
    이런식으로 Bit가 초기화 되어있을것이다.

    MODEx 에는 0b00 이므로 InputMode이고
    CNFx에는 0b01이므로 Input모드에서 0b01은 Floating Input이므로 
    Reset되었을때 포트의 초기값은 Input모드로 설정이 되어있다.

    우리는 LED를 켜기위해(출력) Output Mode로 설정해야 한다.
    MODEx = 0b01;
    로 셋팅해서 OutputMode로 만들어준다 (Max Speed는 Output으로 나오는 신호의 주기를 나타낸단다.. )
    단순히 LED 켜는 기능에서는 어느속도로 해도 상관이 없으므로 max speed 10MHz로 설정한다.

    다음은 CNF의 설정이다.
    Output Mode에서의 CNF설정은 
    General Purpose로 사용할것이냐, Alternate Function으로 사용할것이냐 두가지로 나뉘는데 
    우리는 General Purpose로 사용할 것이다. 
    ('아직 Alternate Function이 정확하게 어떤놈인지 모르겠다.. 저모드로 설정하면 GPIO로 I2C같은 통신도 구현할수도 있다고 하는데.. 나중에 써볼일이 있겠지뭐..')

    그럼 걸러진게 General Purpose Output에서 Push-Pull이냐, Open-Drain이냐를 선택해야 하는데..

    (Datasheet) Basic Structure of an I/O Port Bit에 보면
    Push-Pull은 내부에 (INPUT DRIVER)를 이용해서 High나 Low를 출력시키는것이고
    Open-Drain은 내부 (OUTPUT DRIVER)의 FET를 이용해서 HIGH나 LOW를 출력시키는 것이다. 
    ('두개가 틀린점이 있다지만.. 간단하게 생각하면 같은거라고 생각하고 넘어가자.. -_-; ')

    자세한것은 푸우님의 블로그.. 
    윤교수님의 기술노트 9
    ('아직 정확하게 이해가안되서 서술하기가 힘들다..ㅠㅠ')


    어쨋든 두가지경우중 아무거나 써도 지금은 문제가 없을거 같다!

    그러므로 . 

    CNFx = 0b00;  으로 사용을 하겠다.



    자 이제 PORTx를 General Purpose Output Push-Pull (Max Speed 10MHz)로 설정했으니. 
    이제는 Push-Pull을 이용해서 HIGH이든, LOW이든 출력만 시켜주면 된다. 

    (RM0008)아래그림은 
    GPIOx_ODR 레지스터에 대한 설명이다.
    레지스터 이름에서 느껴지듯이 Port의 Output Data를 설정하는 레지스터이다.
    1을 넣으면 HIGH가 출력이되고, 0을 넣으면 LOW가 출력이된다.


    1장의 LED회로에서 보면 PORT에 LOW를 출력시켯을때 LED가 켜지니. 
    GPIOx_ODR레지스터에 해당비트에 0을 쏴주면 되겠다.

    아래회로의 LED를 전부 켜기 위해서는

    간단하게.
    GPIOA_ODR = 0;
    GPIOE_ODR = 0;
    라고 적어주면 되겟다. (ODR의 Reset Value가 0x0000 0000 이므로 위 코드가 없더라도 LED는 켜질 것이다.)


    #define  RCC_APB2ENR    (*(volatile unsigned int*)0x40021018)  
    #define  GPIOA_CRH
    #define  GPIOA_CRL    (*(volatile unsigned int*)0x40010800)

    #define  GPIOE_CRH    
    #define  GPIOE_CRL    (*(volatile unsigned int*)0x40011800)

    int main()
    {

      RCC_APB2ENR |= (1<<2| (1<<6);    

      GPIOA_CRL |= (0x3333 << 16);

      GPIOE_CRL |= 0x3333;

      while(1);
    }

    위의 소스를 사용하여 LED1~8번까지 켜보았다.

    사용하는 보드는 STM32-OAK보드이다.
    http://cafe.naver.com/armcortex 

    LED는 기본 초록색 LED가 다닥다닥 붙어있어서 잘 티가나지 않아서 굴러다니는거 몇개 줒어서 바꿔 보았다.ㅎ  





    댓글

Designed by Tistory.