20140717 (ARM Ultrasonic 초음파 모듈)

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;
}











설정

트랙백

댓글