#include "ULTRA_AIC.h" static volatile unsigned int ui_Tic; // 58us 1cm. static volatile unsigned int ui_dist; // static volatile unsigned int ui_state; // 현재 초음파 거리를 측정중인지 아닌지. // 측정중이면 1, 측정중이 아니면 0 unsigned char *ULTRA_RUN() { static unsigned char uc_dist[] = "---cm"; TRG_PULSE_Toggle(); ui_Tic = 0; // 미리 0cm 로 초기화. ui_dist = 0; // 계속동작중인 ui_Tic 에다가 값을 넣어서. 실제거리를 제려고.
while( 0 == ((AT91C_BASE_PIOA->PIO_PDSR) & ( 1<<Echo_PIN )) ); // 상승엣지의 상태를 발견함. // LOW level 0 , HIGH level 1 // 타이머 클럭 활성화(TC_CCR, CLKEN) AT91C_BASE_TC0->TC_CCR = AT91C_TC_CLKEN; // 클럭이 켜짐. Timer/Count 를 켜줌. // 1. 끝 : 타이머 클럭 비활성화 ------------------
// 타이머 시작(TC_CCR, SWTRG) AT91C_BASE_TC0->TC_CCR = AT91C_TC_SWTRG;
// 인터럽트를 켜줌. AT91C_BASE_PIOA->PIO_IER = 1<<Echo_PIN; // PIO의 15번 핀을 켜줌. 셋팅을 끝내고 열어줌! AT91C_BASE_AIC->AIC_IECR = 1<<AT91C_ID_PIOA; // 장치번호를 켜줘야함!
ui_state = 1; // 측정중 숫자넣어놓기.
while( 1 == ui_state ); // 전역변수에 0 이 드러가면 나옴.
U_Timer_Init(); // 타이머 꺼줌. ECHO_INIT(); // Echo 꺼줌.
uc_dist[0]= '0' + ((ui_dist%1000)/100); // ui_dist의 실제거리를 넣어둠. uc_dist[1]= '0' + ((ui_dist%100)/10); uc_dist[2]= '0' + ((ui_dist%10)); return uc_dist; }
void ULTRA_INIT() { ECHO_INIT(); TRG_init(); U_Timer_Init();
} void ECHO_INIT() { AT91C_BASE_PMC->PMC_PCER = 1<<AT91C_ID_PIOA; // P203, PMC_PCER 를 통해서 PIOA 활성화. AT91C_BASE_PIOA->PIO_ODR = 1<<Echo_PIN; // P252, PIO_ODR 를 통해서 15번 핀 출력 비활성화. AT91C_BASE_PIOA->PIO_PER = 1<<Echo_PIN; // P250, PIO_PER 를 통해서 핀자체를 활성화. AT91C_BASE_PIOA->PIO_IDR = 1<<Echo_PIN; // P250, PIO_IDR 를 통해서 15번 핀의 Interrupt 를 비활성화. AT91C_BASE_AIC->AIC_IDCR = 1<<AT91C_ID_PIOA; // P175, AIC_IDCR 를 통해 AIC 비활성화.
// 타이머 카운터 0 인터럽트 핸들러 등록(AIC_SVR[TC0], AIC_Handler) AT91C_BASE_AIC->AIC_SVR[AT91C_ID_PIOA] = (volatile unsigned int )ULTRA_Handler;
// 타이머 카운터 0 인터럽트 모드 설정(AIC_SMR[TC0], AIC_SRCTYPE_INT_HIGH_LEVEL, PRIOR_LOWEST) AT91C_BASE_AIC->AIC_SMR[AT91C_ID_PIOA] = ((AT91C_AIC_PRIOR_LOWEST) | (AT91C_AIC_SRCTYPE_EXT_NEGATIVE_EDGE)); // Source type 은 외부인터럽트-Negative 로 맞춰줌.
AT91C_BASE_AIC->AIC_ICCR = 1<<AT91C_ID_PIOA; // P181, PIOA 장치에 값을 초기화. 엣지 디텍터 AT91C_BASE_PIOA->PIO_IFER= 1<<Echo_PIN; // P253, Glitch Input Filter Enable Register // PIN에 스위치를 통한 처음과 끝부분의 잡음 제거. AT91C_BASE_AIC->AIC_ISCR = 1<<AT91C_ID_PIOA; // Glitch Input Filter 를 설정하고 다시 켜줌. 엣지 디텍터. //AT91C_BASE_PIOA->PIO_IER = 1<<Echo_PIN; // PIO의 15번 핀을 켜줌. 셋팅을 끝내고 열어줌! //AT91C_BASE_AIC->AIC_IECR = 1<<AT91C_ID_PIOA; // 장치번호를 켜줘야함! return; }
void ULTRA_Handler() { // Timer/count 와는 다르게 인터럽트는 32개가 다 반응하므로 PIO로 외부인터럽트신호를 확인해줘야한다. AT91C_BASE_PIOA->PIO_ISR; // 미리 만들어 둔다.
ui_dist = ui_Tic; // 하강인터럽트 걸리는 순간까지도 ui_Tic 은 계속 돌고있다. // 그래서 ui_dist 에다가 인터럽트 걸리는 순간에 실제거리를 저장해놓는다. ui_state = 0; // 0 으로 만들어둔다. 다음 타이머를 받기위해.
AT91C_BASE_AIC->AIC_EOICR = 0; return; }
void U_Timer_Init() { // 타이머 카운터 0 사용을 위한 PMC 활성화 AT91C_BASE_PMC->PMC_PCER = 1<<AT91C_ID_TC0; // 1.시작 : 타이머 클럭 비활성화 ------------------ // 타이머 클럭 비활성화(TC_CCR 설정) AT91C_BASE_TC0->TC_CCR = AT91C_TC_CLKDIS; // 클럭이 꺼짐
// 2. 시작 : 타이머 인터럽트 비활성화 ------------- // 타이머 인터럽트 비활성화(TC_IDR 설정) // 인터럽트 상태 정보 초기화(TC_SR 읽기) 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); AT91C_BASE_TC0->TC_SR;
// 분주비 128, 비교 방식 레지스터 설정(TC_CMR, DIV5_CLOCK, CPCTRG) // MCKR divided by 8 => 58us(TC_RC 설정:353) AT91C_BASE_TC0->TC_CMR = (AT91C_TC_CLKS_TIMER_DIV2_CLOCK) | (AT91C_TC_CPCTRG); AT91C_BASE_TC0->TC_RC = 353;
// 타이머 카운터 0 인터럽트 비활성화(AIC_IDCR, TC0) AT91C_BASE_AIC->AIC_IDCR = 1<<AT91C_ID_TC0;
// 3. 시작 : 타이머 카운터 0 인터럽트 비활성화 ------
// 타이머 카운터 0 인터럽트 핸들러 등록(AIC_SVR[TC0], Timer_Handler) AT91C_BASE_AIC->AIC_SVR[AT91C_ID_TC0] = (volatile unsigned int )U_Timer_Handler;
// 타이머 카운터 0 인터럽트 모드 설정(AIC_SMR[TC0], AIC_SRCTYPE_INT_HIGH_LEVEL, PRIOR_LOWEST) AT91C_BASE_AIC->AIC_SMR[AT91C_ID_TC0] = ((AT91C_AIC_PRIOR_LOWEST) | (AT91C_AIC_SRCTYPE_POSITIVE_EDGE));
// 타이머 카운터 0 인터럽트 클리어(AIC_ICCR, TC0) AT91C_BASE_AIC->AIC_ICCR = 1<<AT91C_ID_TC0;
// TC_RC 값 비교 타이머 인터럽트 활성화(TC_IER, CPCS) AT91C_BASE_TC0->TC_IER = AT91C_TC_CPCS; // 2. 끝 : 타이머 인터럽트 비활성화 ---------------
// 타이머 카운터 0 인터럽트 활성화(AIC_IECR, TC0) AT91C_BASE_AIC->AIC_IECR = 1<<AT91C_ID_TC0;
// 3. 끝 : 타이머 카운터 0 인터럽트 비활성화 -------
/*// 타이머 클럭 활성화(TC_CCR, CLKEN) AT91C_BASE_TC0->TC_CCR = AT91C_TC_CLKEN; // 클럭이 켜짐. // 1. 끝 : 타이머 클럭 비활성화 ------------------
// 타이머 시작(TC_CCR, SWTRG) AT91C_BASE_TC0->TC_CCR = AT91C_TC_SWTRG;*/ }
void U_Timer_Handler() { AT91C_BASE_TC0->TC_SR; // TC0_SR 에 가서 CPCS비트에 1이 들어가있는 상태면 인터럽트가 비활성화됨. // 그래서 1이 들어가있으면 안됨. TC0_SR 에 접근(읽으면) 0 으로 만듬 ++ui_Tic; // 여기선 데이터 단위 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; //AT91C_BASE_PIOA->PIO_PPUDR=1<<TRG_PIN; //트러거핀 풀업저항을 오픈시켜 사용금지 return; }
void TRG_PULSE_Toggle() { volatile unsigned int ui_Cnt;
AT91C_BASE_PIOA->PIO_SODR = 1<<TRG_PIN; for(ui_Cnt=0;ui_Cnt < 100;++ui_Cnt); // 48 cycle 이상 지연. 0.00001s 4000 cycle 이상 지연. AT91C_BASE_PIOA->PIO_CODR = 1<<TRG_PIN;
return; }
|