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