ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 20140717 (ARM Ultrasonic 초음파 모듈)
    부산IT학원/스마트컨트롤러 2014. 7. 17. 16:10

    104일차











    -------------------------------

    ARM Ultrasonic (초음파 모듈)

    -------------------------------




    ------- 어제 소스에 이어 계속 거리를 측정하는 소스를 작성한다.


    --- 원리는



    트리거 신호를 발사하면

    초음파 모듈에서 버스트 신호를 발사하고

    Echo로 H를 내보내다가

    버스트 신호가 들어오면

    Echo가 L로 들온다.


    이 때 걸린 시간을 계산하면 물체와의 거리가 된다.












    ------- 소스



    --- usonic.c




    #include "usonic.h"


    static volatile unsigned int uiCm;
    static volatile unsigned int uiDist;

    void Ultra_Init(void)
    {
      Trg_Init();
      Echo_Init();
      Timer1_Init();
    }


    void Timer1_Init(void)
    {
    // PIOA에 전원공급
      *AT91C_PMC_PCER = (1<<AT91C_ID_TC1);

    // Clock disable
      *AT91C_TC1_CCR = AT91C_TC_CLKDIS;

    // TC1 인터럽트 비활성화
      *AT91C_AIC_IDCR = (1<<AT91C_ID_TC1);

    // TC1 인터럽트 비활성화
      *AT91C_TC1_IDR =  AT91C_TC_COVFS | AT91C_TC_LOVRS | AT91C_TC_CPAS
              | AT91C_TC_CPBS | AT91C_TC_CPCS | AT91C_TC_LDRAS
              | AT91C_TC_LDRBS | AT91C_TC_ETRGS;

    // Status Reg를 한번 읽어야 한다.
    // ATmel 사에서 해야한다고 함.
      *AT91C_TC1_SR;

    // TC1 Clock Select 128 , RC Compare Trigger Enable
      *AT91C_TC1_CMR = AT91C_TC_CLKS_TIMER_DIV2_CLOCK
                | AT91C_TC_CPCTRG;

    // 분주비 128일 때 375마다 1ms.
      *AT91C_TC1_RC = 353;

    // 인터럽트시 실행할 함수
      AT91C_AIC_SVR[AT91C_ID_TC1] = (volatile unsigned int)Ultra_Handler;

    // 인터럽트 걸리는 조건 및 우선순위
      AT91C_AIC_SMR[AT91C_ID_TC1] = AT91C_AIC_SRCTYPE_HIGH_LEVEL
                      | AT91C_AIC_PRIOR_LOWEST;

    // 인터럽트 Edge detecter 끄기
      *AT91C_AIC_ICCR = (1<<AT91C_ID_TC1);

    // TC1 인터럽트 RC compare 활성화
      *AT91C_TC1_IER = AT91C_TC_CPCS;

    // TC1 인터럽트 활성화
      *AT91C_AIC_IECR = (1<<AT91C_ID_TC1);

    // Clock enable
      *AT91C_TC1_CCR = AT91C_TC_CLKEN | AT91C_TC_SWTRG;
      
    // Clock start
    //  *AT91C_TC1_CCR = AT91C_TC_SWTRG;

    }


    void Ultra_Handler(void)
    {
      ++uiCm;
      
    // Status Reg를 한번 읽어야 다음 인터럽트가 걸린다.
    // ATmel 사에서 해야한다고 함.
      *AT91C_TC1_SR;
    }


    void Echo_Init(void)
    {
    // PIOA에 전원공급
      *AT91C_PMC_PCER = (1<<AT91C_ID_PIOA);

    // PIN_ECHO 출력 비활성화
      *AT91C_PIOA_ODR = PIN_ECHO;

    // PIN_ECHO 핀 활성화
      *AT91C_PIOA_PER = PIN_ECHO;

    // PIN_ECHO 인터럽트 비활성화
      *AT91C_PIOA_IDR = PIN_ECHO;

    // pull up 저항 OFF
      *AT91C_PIOA_PPUDR = PIN_ECHO;

    // 인터럽트시 실행할 함수
      AT91C_AIC_SVR[AT91C_ID_PIOA] = (volatile unsigned int)Echo_Handler;

    // 인터럽트 걸리는 조건 및 우선순위
      AT91C_AIC_SMR[AT91C_ID_PIOA] = AT91C_AIC_SRCTYPE_POSITIVE_EDGE
                      | AT91C_AIC_PRIOR_LOWEST;

    // 인터럽트 Edge detecter 끄기
      *AT91C_AIC_ICCR = (1<<AT91C_ID_PIOA);

    // PIOA 인터럽트 Edge detecter 켜기
      *AT91C_AIC_ISCR = (1<<AT91C_ID_PIOA);

    }


    void Trg_Init(void)
    {
      *AT91C_PMC_PCER = (1<<AT91C_ID_PIOA);
      *AT91C_PIOA_PER = PIN_TRG;
      *AT91C_PIOA_OER = PIN_TRG;
    }


    void Echo_Handler(void)
    {
      static unsigned int uiState;
      static volatile unsigned int uiMode = MODE_POSITIVE;

    // ISR은 한 번 읽으면 바로 다 지워짐
    // 따라서 따로 저장해 두고 사용.
      uiState = *AT91C_PIOA_ISR;

    // 해당 인터럽트가 오면
      if(PIN_ECHO == (uiState & PIN_ECHO))
      {
    // 상승 edge
        if(MODE_POSITIVE == uiMode)
        {
          uiCm = 0;

    // 인터럽트 걸리는 조건 및 우선순위
          AT91C_AIC_SMR[AT91C_ID_PIOA] =
          AT91C_AIC_SRCTYPE_EXT_NEGATIVE_EDGE
          | AT91C_AIC_PRIOR_LOWEST;

          uiMode = MODE_NEGATIVE;
        }
     // 하강 edge
        else
        {
    // PIN_ECHO 인터럽트 비활성화
          *AT91C_PIOA_IDR = PIN_ECHO;

          uiDist = uiCm;

          uiMode = MODE_POSITIVE;
        }
      }

    // 처리중 인터럽트 발생시 초기화.  
      uiState = *AT91C_PIOA_ISR;

    // Atmel 사에서 무슨 의미인지 모르지만
    // 인터럽트가 끝날 때 마지막에 꼭 넣으라 함.
      *AT91C_AIC_EOICR = 0;
    }


    void Ultra_Trigger(void)
    {
      volatile unsigned int uiCnt;

    // PIN_ECHO 인터럽트 활성화
      *AT91C_PIOA_IER = PIN_ECHO;

    // PIOA 인터럽트 활성화
      *AT91C_AIC_IECR = (1<<AT91C_ID_PIOA);

    // 시작 펄스 신호
      *AT91C_PIOA_CODR = PIN_TRG;
      DELAY(1000);
      *AT91C_PIOA_SODR = PIN_TRG;
      DELAY(5000);
      *AT91C_PIOA_CODR = PIN_TRG;
    }


    unsigned int Ultra_Act(void)
    {
      uiDist = 0;
      
      Ultra_Init();
      Ultra_Trigger();

      while(0 == uiDist);
      
      return uiDist;
    }






    --- usonic.h



    #ifndef _USONIC_H_
    #define _USONIC_H_


    #include "project.h"


    #define PIN_TRG    AT91C_PIO_PA15
    #define PIN_ECHO  AT91C_PIO_PA14

    #define MODE_POSITIVE  1
    #define MODE_NEGATIVE  0



    void Ultra_Init(void);
    void Timer1_Init(void);
    void Ultra_Handler(void);
    void Echo_Init(void);
    void Trg_Init(void);
    void Echo_Handler(void);
    void Ultra_Trigger(void);
    unsigned int Ultra_Act(void);



    #endif  //_USONIC_H_







    --- main.c


    #include "project.h"
    #include "lcd.h"
    #include "dbgu.h"
    #include "irq.h"
    #include "tc.h"
    #include "usonic.h"


    int main(void)
    {
      volatile unsigned int uiCnt;
      unsigned int uiDist;

      Lcd_Init();
    //  DBGU_Init();
    //  IRQ_Init();
    //  IRQ_LED_Init();
    //  TC0_Init();
      
      Lcd_Str((const unsigned char *)"Ultrasonic");


      while (1)
      {
        uiDist = Ultra_Act();
        Lcd_Inst(INST_SET_DDRAM | 0x40);
        Lcd_Num(uiDist);
        DELAY(1000000);
      }

      while(1);
      return 0;
    }











Designed by Tistory.