==================================Outline====================================
초음파 센서 동작
----------------------------------------------------------------------------
초음파 센서를 작동시키기 위한 코드를 계속 작성해보자.

타이밍도를 보면 펄스를 10us 동안 high로 유지하면 ultrasonic이 8 cycle 동안 발생한다. 이 후에 echo 펄스가 방출되어 돌아오기 직전까지 high가 유지된다.
echo펄스가 high를 유지한 동안의 클럭을 측정해주면 거리가 나오게 되는 것이다.
펄스 측정을 위해 ARM의 핀을 활성화 해주고 초음파 센서와 연결하는 작업을 해주어야 한다.
//장치를 사용하기 위한 작업을 인터페이싱이라고 한다.
mode 1을 사용해 줄 것이기 때문에 핀을 4개만 사용한다.

시연 동영상 - https://www.youtube.com/watch?v=bPN0R7o3wXY
코드는 아래와 같다.
/*** ultra.c ***/
#include <project.h>
static volatile unsigned int uiCM; static volatile unsigned int uiState = INIT_OFF;
static void UTimer_Init(void); static void Ultra_ISR(void); static void U_Trigger_Init(); static void U_Echo_Init(); static void U_Trigger();
static void UTimer_Init(void) { // 타이머 카운터 0 사용을 위한 PMC 활성화(AT91C_ID_TC0) // p33 : // p204 : //p20 : 주소 *AT91C_PMC_PCER = 1 << AT91C_ID_TC0; // 1.시작 : 타이머 클럭 비활성화 ------------------ // 타이머 클럭 비활성화(TC_CCR 설정) - 설정 중에 작동하는 것을 막기 위해 *AT91C_TC0_CCR = AT91C_TC_CLKDIS;
// 2. 시작 : 타이머 인터럽트 비활성화 ------------- // 타이머 인터럽트 비활성화(TC_IDR 설정) *AT91C_TC0_IDR = 0xFF; // p479 // 인터럽트 상태 정보 초기화(TC_SR 읽기) *AT91C_TC0_SR; // 언급만 하면 읽은 효과 => 읽으면 0 이 됨 //p476
// 분주비 128, 비교 방식 레지스터 설정(TC_CMR, DIV4_CLOCK, AT91C_TC_CPCTRG) // MCKR divided by 4096 => 12, 0.25us(TC_RC 설정) *AT91C_TC0_CMR = AT91C_TC_CLKS_TIMER_DIV4_CLOCK | AT91C_TC_CPCTRG; // register c와 비교
// 타이머 카운터 0 인터럽트 비활성화(AIC_IDCR, AT91C_ID_TC0) *AT91C_AIC_IDCR = 1 << AT91C_ID_TC0; // p33 // 3. 시작 : 타이머 카운터 0 인터럽트 비활성화 ------ // 타이머 카운터 0 인터럽트 핸들러 등록(AIC_SVR[AT91C_ID_TC0], timer_handler) // 타이머 카운터 0 인터럽트 모드 설정(AIC_SMR[AT91C_ID_TC0], AT91C_AIC_SRCTYPE_INT_HIGH_LEVEL, AT91C_AIC_PRIOR_LOWEST) // 타이머 카운터 0 인터럽트 클리어(AIC_ICCR, AT91C_ID_TC0) AT91C_AIC_SVR[AT91C_ID_TC0] = (unsigned int)Ultra_ISR; // p175 AT91C_AIC_SMR[AT91C_ID_TC0] = AT91C_AIC_SRCTYPE_INT_HIGH_LEVEL | AT91C_AIC_PRIOR_LOWEST; *AT91C_AIC_ICCR = 1 << AT91C_ID_TC0; // TC_RC 값 비교 타이머 인터럽트 활성화(TC_IER, AT91C_TC_CPCS) *AT91C_TC0_IER = AT91C_TC_CPCS; // MCKR divided by 128 => 375, 0.001sec(TC_RC 설정) *AT91C_TC0_RC = 22; // 2. 끝 : 타이머 인터럽트 비활성화 ---------------
// 타이머 카운터 0 인터럽트 활성화(AIC_IECR, AT91C_ID_TC0) *AT91C_AIC_IECR = 1 << AT91C_ID_TC0;
// 3. 끝 : 타이머 카운터 0 인터럽트 비활성화 -------
// 타이머 클럭 활성화(TC_CCR, AT91C_TC_CLKEN) *AT91C_TC0_CCR = AT91C_TC_CLKEN; // 1. 끝 : 타이머 클럭 비활성화 ------------------
// 타이머 시작(TC_CCR, AT91C_TC_SWTRG) // *AT91C_TC0_CCR = AT91C_TC_SWTRG;
return; }
static void Ultra_ISR(void) //소리가 1cm움직이면 { // 인터럽트 상태 정보 초기화(TC_SR 읽기) *AT91C_TC0_SR; // 언급만 하면 읽은 효과 => 읽으면 0 이 됨 //p476 ++uiCM; //uiCM 값이 초음파로부터 물체가 떨어진 거리(cm) return; }
static void U_Trigger_Init() { *AT91C_PMC_PCER =1<< AT91C_ID_PIOA; //Peripheral Clock Supply PIOA *AT91C_PIOA_PER = UTRI_PIN; //PIO Enable Register *AT91C_PIOA_PPUDR = UTRI_PIN; //Pull-up Disable Register *AT91C_PIOA_OER = UTRI_PIN; //Output Enable Register *AT91C_PIOA_CODR = UTRI_PIN; //Clear Output Data Register }
static void U_Echo_Init() { *AT91C_PMC_PCER = 1<<AT91C_ID_PIOA; //Peripheral Clock Supply PIOA *AT91C_PIOA_PER = ECHO_PIN; //PIO Enable Register - enabling pin means enabling input function *AT91C_PIOA_PPUDR = ECHO_PIN; //Pull-up Disable Register }
static void U_Trigger() { volatile unsigned int uiCnt; *AT91C_PIOA_CODR = UTRI_PIN; //Clear Output Data Register
/*** PULSE FOR TRIGGER ***/ for(uiCnt = 0; uiCnt <1000 ; ++uiCnt); *AT91C_PIOA_SODR = UTRI_PIN; //SET Output Data Register
for(uiCnt = 0; uiCnt <1000 ; ++uiCnt); *AT91C_PIOA_CODR = UTRI_PIN; //Clear Output Data Register ///////////////////////////////// }
void Ultra_Init() { UTimer_Init(); U_Trigger_Init(); U_Echo_Init(); uiState = INIT_ON; }
unsigned int Ultra_Run() { if(uiState == INIT_OFF) { LCD_Inst(LCD_INST_CLR); LCD_Inst(LCD_INST_HOME); LCD_Print("Error"); return 0; }
uiCM = 0; //distance 0 *AT91C_TC0_CCR = AT91C_TC_CLKEN; //Timer enable U_Trigger(); while( 0 == ((*AT91C_PIOA_PDSR) & (ECHO_PIN)) ); //holding when echo is low *AT91C_TC0_CCR = AT91C_TC_SWTRG; //Timer init.
while( 0 != ((*AT91C_PIOA_PDSR) & (ECHO_PIN)) ); //holding when echo is not low *AT91C_TC0_CCR = AT91C_TC_CLKDIS; //Timer disable
return uiCM; }
/*** main.c ***/
#include <project.h> #include <stdlib.h> #include <string.h>
volatile unsigned int uiCnt;
#define Delay(x) for(uiCnt = 0; uiCnt < x; ++uiCnt)
void Init(void) { LCD_Init(); Ultra_Init(); return; }
int main(void) { int iCnt; char cADist[] ="000cm" ; unsigned int uiCM; Init(); LCD_Inst(0x0C); while(1) { uiCM = Ultra_Run(); if(uiCM == 0) { LCD_Inst(LCD_INST_CLR); LCD_Inst(LCD_INST_HOME); LCD_Print("Error"); continue; } cADist[0] = uiCM/100 + '0'; cADist[1] = (uiCM%100)/10 + '0'; cADist[2] = uiCM%10 + '0'; LCD_Inst(LCD_INST_HOME); LCD_Print(cADist); for(iCnt=0; iCnt < 5; ++iCnt) { Delay(100000); }
} return 0; } |