-
20140717 (ARM Ultrasonic 초음파 모듈)부산IT학원/스마트컨트롤러 2014. 7. 17. 16:10
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;
}'부산IT학원 > 스마트컨트롤러' 카테고리의 다른 글
20140722 (ARM ADC, Assembly 기초, Debug) (0) 2014.07.22 20140721 (ARM adc 소스 작성중, asm) (0) 2014.07.21 20140716 (ARM 초음파 모듈, Ultrasonic) (0) 2014.07.16 20140715 (ARM Timer & Counter) (0) 2014.07.15 20140714 (ARM Interrupt로 LED 켜기) (0) 2014.07.14