본문 바로가기
코스웨어/13년 스마트컨트롤러

초음파센서를 이용한 거리측정_진종영

by 알 수 없는 사용자 2013. 5. 23.
728x90
반응형

___________ARM_______________________________________________________________

 

ULTRA.H

#ifndef _ULTRA_H_
#define _ULTRA_H_
#include <AT91SAM7S256.h>


#define ECHO_PIN 15 // PIO 중 외부 인터럽트용으로 사용할 핀번호
#define TRG_PIN 14 // PIO 중 트리거 펄스 출력용으로 사용할 핀번호


void ULTRA_Init();
void ULTRA_Handler(void);
void ECHO_Init();
void UTimer_Handler(void);
void UTIMER_Init(void);
void TRG_Init();
void TRG_Pulse();
unsigned char * ULTRA_Run();


#endif //_ULTRA_H_

 

ULTRA.C

AIC(외부)인터럽트를 이용

#include "ULTRA.h"

static volatile unsigned int uiTick;// 타이머 카운터가 cm마다 카운트 증가 시키는 변수

static volatile unsigned int uiDist;

//에코 펄스가 L가 될때(에코펄스가 끝날때)의 uiTick값을 저장하여 거리값을 알수있도록 하는 변수

 

static volatile unsigned int uiState;

// 초음파 거리를 측정중인지 아닌지 상태 표시하는 변수(에코펄스 상태), 측정중이면 1 아니면 0

 

 

// 초음파센서로부터 에코펄스를 받으면 TC0와 AIC(외부인터럽트)를 이용하여 거리 측정함.

unsigned char * ULTRA_Run()

{

static unsigned char ucDist[] = "---cm";

//미리 배열을 만들어 cm를 넣어놓고 3자리숫자를 채울수 있는 크기를 확보해놓음

uiState = 1;
uiTick = 0;
uiDist = 0;

TRG_Pulse(); //트리거 펄스를 초음파센서로 인가

while ( 0 == ((AT91C_BASE_PIOA->PIO_PDSR) & (1<<ECHO_PIN)) );

//에코핀에 상승에지를 발견하기 위함, PIO_PDSR로 핀의 레벨을 알수 있음.

AT91C_BASE_TC0->TC_CCR = AT91C_TC_CLKEN; //TC0 Clock Enable
AT91C_BASE_TC0->TC_CCR = AT91C_TC_SWTRG;

// software trigger가 1로 셋되면 카운터 리셋, 클럭 스타트 됨.


AT91C_BASE_PIOA->PIO_IER = (1<<ECHO_PIN); //PIO 15번핀 Interrupt Enable
AT91C_BASE_AIC->AIC_IECR = (1<<AT91C_ID_PIOA); //PIOA장치 Interrupt Enable

uiState = 1; // 에코펄스가 끝나기도 전에 15핀에 하강에지가 감지되어 uiState가 0으로

// 바뀐값을 다시잡아줌, 임시해결책이므로 수정필요...


while( 1 == uiState );//에코펄스가 H값인 동안에는 대기하도록 함.

UTIMER_Init(); //다시 초기화 하면서 TC0 비활성 됨.
ECHO_Init(); //다시 초기화 하면서 AIC 인터럽트(외부 인터럽트) 비활성 됨.

//uiDist의 세자리수 값을 각자리의 아스키코드값으로 나누어 배열에 저장
ucDist[0] = '0'+((uiDist%1000)/100);
ucDist[1] = '0'+((uiDist%100)/10);
ucDist[2] = '0'+(uiDist%10);

return (ucDist); //배열주소 반환

}


void ULTRA_Init()
{
      TRG_Init();
      UTIMER_Init();
      ECHO_Init();

      return;
}


void ECHO_Init()
{

       AT91C_BASE_PMC->PMC_PCER = (1<<AT91C_ID_PIOA); //PIOA 장치 Clock Enable
       AT91C_BASE_PIOA->PIO_ODR = (1<<ECHO_PIN); //PIO 15번핀 출력 비활성
       AT91C_BASE_PIOA->PIO_PER = (1<<ECHO_PIN); //PIO 15번핀활성
       AT91C_BASE_PIOA->PIO_IDR = (1<<ECHO_PIN); //PIO 15번핀 인터럽트 비활성
       AT91C_BASE_AIC->AIC_IDCR = (1<<AT91C_ID_PIOA); //PIOA 인터럽트 비활성

       //AT91C_BASE_PIOA->PIO_PPUDR = (1<<ECHO_PIN); // 풀업 비활성

       AT91C_BASE_AIC->AIC_SVR[AT91C_ID_PIOA] = (unsigned int)ULTRA_Handler;
       //AIC_SVRx의 대응하는 장치번호에 함수의 주소를 넣어줌, 핸들러 등록

       AT91C_BASE_AIC->AIC_SMR[AT91C_ID_PIOA] = AT91C_AIC_PRIOR_LOWEST |

       AT91C_AIC_SRCTYPE_EXT_NEGATIVE_EDGE;//PRIOR : 0, Negative edge triggered

       AT91C_BASE_AIC->AIC_ICCR = (1<<AT91C_ID_PIOA);

// PIOA , 에지 디텍터 clear

AT91C_BASE_PIOA->PIO_IFER = (1<<ECHO_PIN);

// PIO 15핀 glitch filter on


AT91C_BASE_AIC->AIC_ISCR = (1<<AT91C_ID_PIOA);

// PIOA , 에지 디텍터 set


return;

}




void ULTRA_Handler(void) // AIC(외부) 인터럽트 걸리면 호출되는 함수
{
       AT91C_BASE_PIOA->PIO_ISR;

       //PIO_ISR는 입출력라인에 한번이라도 변화가 감지되면 해당 핀에 1로 셋됨.
       //PIO_ISR을 읽으면 다시 0으로 clear됨.

       uiDist = uiTick; //하강에지가 감지 되었을때 uiTick값을 저장함.

       uiState = 0; //ULTRA_Num에게 에코펄스가 H가 됐다는 것을 알려줌

       AT91C_BASE_AIC->AIC_EOICR = 0; //인터럽트가 끝났음을 알려줌.
       // 인터럽트의 끝을 알리기 위해 AIC_EOICR에 값을 쓰기함.
       //보통 0을 쓴다.

      return;
}



void UTIMER_Init(void)
{
        AT91C_BASE_PMC->PMC_PCER = (1<<AT91C_ID_TC0);

        //at91sam7s의 TC0 장치번호(12)를 넣어 PMC(clk) enalble 시킴

        AT91C_BASE_TC0->TC_CCR = AT91C_TC_CLKDIS; // 타이머 클럭 비활성화(TC0_CCR 설정)

        AT91C_BASE_TC0->TC_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 ); // 타이머 인터럽트 비활성화(TC_IDR 설정)

         AT91C_BASE_TC0->TC_SR; // 인터럽트 상태 정보 초기화(TC_SR 읽기)

         AT91C_BASE_TC0->TC_CMR = (AT91C_TC_CLKS_TIMER_DIV2_CLOCK

                                                                 | AT91C_TC_CPCTRG );
                                                             // 분주비 8, 비교 방식 레지스터 설정

         AT91C_BASE_TC0->TC_RC = 353;
    // MCK divided by 8 => 58.8333us(TC_RC 설정 : 353)
      


        AT91C_BASE_AIC->AIC_IDCR = (1<<AT91C_ID_TC0);
         //AIC_IDCR 레지스터의 대응하는 장치번호(TC0 = 12)에 1 set하면 비활성 됨.
         // 타이머 카운터 0 인터럽트 비활성화(AIC_IDCR, TC0)

        AT91C_BASE_AIC->AIC_SVR[AT91C_ID_TC0] = (unsigned int)UTimer_Handler;
        // AIC_SVRx의 대응하는 장치번호에 즉, AIC_SVR12에 함수의 주소를 넣어줌.
        // 타이머 카운터 0 인터럽트 핸들러 등록(AIC_SVR[ID_TC0], Timer_Handler)


        AT91C_BASE_AIC->AIC_SMR[AT91C_ID_TC0] = AT91C_AIC_PRIOR_LOWEST

                                                                                          | AT91C_AIC_SRCTYPE_POSITIVE_EDGE;
                                                                                          //PRIOR : 0, positive edge triggered

        AT91C_BASE_AIC->AIC_ICCR = (1<<AT91C_ID_TC0);// TC0 인터럽트 클리어
        

        AT91C_BASE_TC0->TC_IER = AT91C_TC_CPCS;

        // TC0를 RC Compare Interrupt 방식으로 활성화

        AT91C_BASE_AIC->AIC_IECR = (1<<AT91C_ID_TC0);// TC0 인터럽트 활성화

 

         return;
}


void UTimer_Handler(void)
{
        AT91C_BASE_TC0->TC_SR;

        // RC Compare가 끝나면 TC0_SR의 CPCS에 1이 셋된다.
        //TC Status Register 를 읽으면(접근하면) 0이 됨.
        //다음 인터럽트가 발생할수 있도록해줌...

       ++uiTick; // TC0 인터럽트가 한번 발생할때마다 1씩증가, 단위 : cm

       return;
}

 


void TRG_Init()
{
       AT91C_BASE_PIOA->PIO_OER = (1<<TRG_PIN);
       AT91C_BASE_PIOA->PIO_PER = (1<<TRG_PIN);
       AT91C_BASE_PIOA->PIO_CODR = (1<<TRG_PIN);// 트리거 펄스, 처음에 L 값으로 시작

      return;
}


void TRG_Pulse()
{
       volatile unsigned int uiCnt;

       AT91C_BASE_PIOA->PIO_SODR = (1<<TRG_PIN);// 트리거 펄스 H

       for(uiCnt = 0; uiCnt < 1000; ++uiCnt);

    //최소 10us 펄스를 만들기 위한 지연, 480cycle (0.00001)이상지연

       AT91C_BASE_PIOA->PIO_CODR = (1<<TRG_PIN); // 트리거 펄스 L

       return;
}

 

 

반복문을 이용한 폴링방식

#include "ULTRA.h"

static volatile unsigned int uiTick;// 타이머 카운터가 cm마다 카운트 증가 시키는 변수
static volatile unsigned int uiDist;

//에코 펄스가 L가 될때(에코펄스가 끝날때)의 uiTick값을 저장하여 거리값을 알수있도록 하는 변수

 

 

// 에코펄스의 상승, 하강 에지를 반복문을 이용한 폴링방식으로 확인

unsigned char * ULTRA_Run()

{

static unsigned char ucDist[] = "---cm";

//미리 배열을 만들어 cm를 넣어놓고 3자리숫자를 채울수 있는 크기를 확보해놓음

uiTick = 0;
uiDist = 0;

TRG_Pulse(); //트리거 펄스를 초음파센서로 인가

while ( 0 == ((AT91C_BASE_PIOA->PIO_PDSR) & (1<<ECHO_PIN)) );

//에코핀의 상승엣지를 감지하기 위함, PIO_PDSR로 핀의 레벨을 알수 있음.

AT91C_BASE_TC0->TC_CCR = AT91C_TC_CLKEN; //TC0 Clock Enable
AT91C_BASE_TC0->TC_CCR = AT91C_TC_SWTRG;

// software trigger가 1로 셋되면 카운터 리셋, 클럭 스타트 됨.

while ( 0 != ((AT91C_BASE_PIOA->PIO_PDSR) & (1<<ECHO_PIN)) );

//에코핀의 하강엣지를 감지하기 위함, PIO_PDSR의 레벨 변화를 확인

     

      uiDist = uiTick; // 에코펄스(ECHO_PIN)가 Low로 떨어질때 uiTick값을 저장


      UTIMER_Init(); //다시 초기화 하면서 TC0 비활성 됨. 
      ECHO_Init(); //다시 초기화 하면서 AIC 인터럽트(외부 인터럽트) 비활성 됨.

//uiDist의 세자리수 값을 각자리의 아스키코드값으로 나누어 배열에 저장
ucDist[0] = '0'+((uiDist%1000)/100);
ucDist[1] = '0'+((uiDist%100)/10);
ucDist[2] = '0'+(uiDist%10);

return (ucDist); //배열주소 반환

}


/* 다른 함수들은 외부인터럽트를 이용하는 방식과 똑같이 해도 상관없지만

불필요한 내용들은 없앤다면 ULTRA_Handler() 함수와 관련된 내용은 삭제해도 됨. */

 

 

 

 

 

main.c

#include "project.h"
#include "LCD.h"
#include "ADC.h"
#include "DBGU.h"
#include "LED.h"
#include "Relay.h"
#include "TIMER.h"
#include "AIC.h"
#include "ULTRA.h"


 

int main()

{

volatile unsigned int uiCnt;

LCD_Init();
ADC_Init();
DBGU_init();
LED_Init();
RELAY_Init();
ULTRA_Init();

/*
while(1)
{
       for(uiCnt = 0; uiCnt < 500000; ++uiCnt);
       LCD_Cmd_write(0x80);
       LCD_String(ULTRA_Run());
}

*/

while(1)
{
       DBGU_String("1.LED Toggle\r\n");
       DBGU_String("2.LCD TEST\r\n");
       DBGU_String("3.RELAY Toggle\r\n");
       DBGU_String("4.ULTRA Sonic\r\n");

 

switch( Recv_char( ))

{


case '1':
       LED_Toggle();
       break;

case '2':
       LCD_String("TEST");
       break;

case '3':
       RELAY_Toggle();
       break;

case '4':
       LCD_String(ULTRA_Run());
       DBGU_String(ULTRA_Run());
       break;

default :
;

}

}
return 0;

 

}

실습파일

 

ULTRA.zip

_____________________________________________________________________________________

728x90

'코스웨어 > 13년 스마트컨트롤러' 카테고리의 다른 글

초음파센서 소스-변준식  (0) 2013.05.24
초음파센서 소스 - 김경순  (0) 2013.05.24
센서사용 팁  (2) 2013.05.23
초음파센서소스-송시혁  (0) 2013.05.23
초음파센서 - 전영기  (0) 2013.05.23
한성원_초음파센서.  (0) 2013.05.23
조유진 초음파센서  (0) 2013.05.23
초음파 센서 소스-문영식  (0) 2013.05.23