Busan IT/Assembly2015. 9. 22. 17:42

==================================Outline====================================

 기본 명령어

- 증감 명령어 inc, dec

- 부호 변경 neg

- 곱셈 mul, imul

----------------------------------------------------------------------------

증감 명령어 inc, dec


 

최상위 비트는 부호 비트로 보기 때문에 맨 아래의 연산에서 SF1이 된다.


부호 변경 neg


 

neg2의 보수를 취해주는 연산이다.

 

곱셈 mul, imul


곱셉의 연산은 multiplication의 약자인 ‘mul'이다.

 


 

‘mul’ 명령어를 사용하면 accumulatoreax가 사용되게 된다.

 

곱하기를 하게 되면 곱셈을 사용한 연산레지스터의 두 배의 용량이 필요하기 때문에 (e)dx를 빌려오게 된다.

 

 

 

1byte 곱셈이기 때문에 AL에 있는 값과 곱하기가 된다. 때문에 dx레지스터를 빌려오지 않고 AH를 사용하여 2byte를 확보하게 된다.

 



 

2번을 작성하여 결과 값을 windbg로 확인해보자.


 

imul은 곱셈 때 양수만 취급한다. mul은 형식이 한가지이지만 imul은 세가지이다.

 

 

1. imul source

mul과 동일하다.

 

2. imul register, source

Opcode2byte임을 알 수 있다.

 

 

3. register, source, immediate

소스와 상수가 곱해진 값이 레지스터에 입력된다.

imul은 양수만 취급하기 때문에 싸인플래그(SF)가 변하지 않는다.

 

imul은 확장 레지스터가 없기 때문에 레지스터를 넘어가는 값은 버려진다.

 

mul보다 add가 클럭 사이클이 적게 소모되기 때문에 곱하는 수가 낮을 경우 add연산을 사용하는 것이 효율적이다.

 

pdf/127쳐보기

숙제 pdf p/130 exercise 4.3 2

반응형
Posted by newind2000
Busan IT/Assembly2015. 9. 21. 17:33

==================================Outline====================================

mov 명령어

----------------------------------------------------------------------------

mov 명령어

 

mov 명령어에 대하여 공부해보자.

 

 

mov 명령어의 문법은 mov destination, source이다.

 

 

메모리에 있는 변수끼리의 mov 명령어는 실행 불가능하다.

 

ex) mov Count, Number //illegal for two memory operands

 

CPU 레지스터를 거쳐서 데이터가 이동해야 한다.

 

 

 

Opcodecpu가 이해할 수 있는 언어이기 때문에 exe파일 자체를 assembly language로 고칠 수 있다.

 

AL100을 넣는 assembly를 작성해보자.

 

mov AL, 64h //assembly language

B0 64 //기계어

 

 

C8, 10, 16진수만 사용 가능하지만 assembly2진수도 가능하다.

 

 

어셈블러를 기계어로 변환시켜보자.

 

mov CH, 10

 

-> B5 0A

 

mov EDX, 64

 

-> BA 40 00 00 00 //little endian

direct는 메모리에 직접 집어넣기 때문에 메모리 주소가 필요하다.

변수가 아닌 주소를 사용하기 때문에 주소 값 4byte가 필요하다. 값을 이동시키기 위해서는 원본과 복사본이 필요한데 두 개의 크기는 같아야 한다. 때문에 원본과 복사본의 용량이 각 각 4byte로써 8byte. opcode1byte를 사용한다.

 

immediate(상수) 값은 cpu에 있다.

 

register indirect

 

mov EDX, 64 //EDX64를 넣는다.

 

mov [EDX], 64 //EDX가 가리키는 주소에 64를 넣는다. 포인터와 같은 기능

 

 

아래 표에서 C72개이기 때문에 이를 구별하기 위한 1byte가 필요하다.

AL, AX, EAX에 데이터를 복사하는 기계어는 따로 분리되어 있다. accumulate는 가장 많이 사용하는 명령어이기 때문이다.

 

mov AL, 100 //A0

mov BL, 100 //8A

mov CL, 100 //8A

mov BH, 100 //8A

 

 

//segment register들은 사용하지 않는다.

//굳이 op코드를 외울 필요 없이 표를 보는 방법을 습득해야 한다.

 

 

xchg eax, ebx ; eaxebx값을 바꾼다.

레지스터에 데이터 값은 빅엔디안, 메모리의 값은 리틀 엔디안으로 저장되어 있다.

 

 

AL, AH는 따로 지원하지 않고 EAX부터 따로 opcode가 나뉜다.

 

movxchg를 사용할 때의 클럭 수의 차이를 살펴보자.

 

mov AL, AH ;1 clock

mov AH, BH ;1 clock

mov BH, AL ;1 clock

 

xchg AH, BH ;3 clock

 

 

어셈블리어 코드는 작성자가 용량과 효율을 고려하여 코드를 작성하여야 한다.

 

컴파일러는 assembly 언어를 기계어로 바꿀 때 용량과 효율을 고려하여 컴파일 한다.

컴파일러보다 assembly 언어를 최적화 시킬 수 없다면 assembly어는 손대지 않는 것이 낫다.

 

 

 

 

 

 

 

정수의 덧셈/뺄셈 명령어

 

 

 

덧셈 : add dest., source

뺄셈 : sub dest., source

 

결과는 dest.에 저장된다.

 

 

 

연산을 하는 명령어는 다른 레지스터에 영향을 미친다.


EFL(Extended Flag) 은 비트들의 플래그만 모아 놓은 레지스터이다.

 

//책에 틀린 내용이 존재함으로 위의 연산을 일일이 확인해 보아야 한다.

Windbg를 사용하여 EFL의 값을 확인할 수 있다.

표에 나와 있는 내용을

 

00 00 02 06

 

 

-> 0(SF)0(ZF)10 0110(CF)

 

 

계산 결과가 부호비트를 넘었을 때도 overflow가 발생한다.


 

 

반응형
Posted by newind2000
Busan IT/ARM Controller2015. 9. 18. 09:53

==================================Outline====================================

ADC 전압측정

----------------------------------------------------------------------------

 

ADC 전압측정

 

 

ADC를 동작시키기 위한 코드를 계속 작성해보자.






 

- 전역변수로 ADC 초기화 플래그를 설정해 주어 ADC초기화 함수의 끝에서 해당 플래그를 1로 변환 시킨다.

 

- ADC를 동작 시키는 함수에서 ADC 초기화 함수가 1일 때만 작동하도록 처리해준다.

 

- ADC를 동작시키는 함수에서 ADC기능을 동작시킨다(ADC_CR, ADC_START)

 

- ADC가 데이터를 변환시키는 동안 프로그램을 잡아준다.(ADC_SR, ADC_DRDY)

 

- 변환 값을 ADC동작함수의 반환 값으로 해준다, 이 때 유효한 데이터만 추출하기 위해

 

마스크를 사용한다.(ADC_LCDR, ADC_LDATA)

 

- 메인함수에서 ADC동작 함수로부터 받은 값을 버프에 넣어 출력한다.


그리하여 코드는 아래와 같으니...


/*** ADC.c ***/


#include <project.h>

unsigned int uiInitFlag;

void ADC_Init()
{
  *AT91C_PMC_PCER = 1 << AT91C_ID_ADC;  //CLK supply to ADC
  *AT91C_ADC_CR = AT91C_ADC_SWRST;    //resets the ADC simulating a hardware reset
  *AT91C_ADC_CHER = AT91C_ADC_CH4;    //enables ADC channel 4
  //*AT91C_ADC_MR = AT91C_ADC_PRESCAL & (AT91C_ADC_LOWRES_10_BIT);  
  //*AT91C_ADC_MR = 0x05 << 8 &  (~(0 << 4));
  ///////////////// as far 9/16 //////////////////
  //*AT91C_ADC_CR = AT91C_ADC_START;    //ADC start

  *AT91C_ADC_MR = AT91C_ADC_LOWRES_10_BIT | (0x05 << 8);
  
  uiInitFlag = 1;  
  
}
int ADC_Run()
{
  if(uiInitFlag == 0)
  {
    return -1;
  }
  *AT91C_ADC_CR = AT91C_ADC_START;    //ADC start
  while(0 ==  (*AT91C_ADC_SR &  AT91C_ADC_DRDY) );  //hold while converting
  return (int)(*AT91C_ADC_LCDR & AT91C_ADC_LDATA);    //returning ADC value
}
 

/*** 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();
  ADC_Init();
    
  return;
}

int main(void)
{  
  unsigned char ucVal[] = "000"//ADC value containing variable
  int iVal;
  int iCnt;
  
  Init();
  
  while(1)
  {
    iVal = ADC_Run();
    if(-1 == iVal)
    {
      LCD_Print("Error");
      while(1);
    }
    /*
    ucVal[0] = iVal / 1000 + '0';
    ucVal[1] = (iVal % 1000) / 100 + '0';
    ucVal[2] = (iVal % 100) / 10 + '0';
    ucVal[3] = iVal %10 + '0';*/

    iVal = (iVal * 33)/1024;   
    
    ucVal[0= iVal/10 + '0';
    ucVal[1= '.';
    ucVal[2= iVal%10 + '0';
    

    LCD_Inst(LCD_INST_HOME);
    LCD_Print(ucVal);
    for(iCnt = 0; iCnt <10; ++iCnt)
      Delay(100000);

  }
  
  

  return 0;



반응형
Posted by newind2000
Busan IT/ARM Controller2015. 9. 17. 08:26

==================================Outline====================================

Analogue to Digital Converter

----------------------------------------------------------------------------

 

Analogue to Digital Converter

 

왼쪽 Timer Counter Channels로 제어하는 것은 외부신호로 ADC 작동을 알리는 것이다.

ADC의 번역 값을 인터럽트를 사용하여 전송할 수도 있다.

 


아몰랑

ADC에서도 클럭이 공급되어야 한다. 클럭은 연산과 시간을 위한 기준이 된다.

ADC에서는 연산(덧셈)을 사용 한다. 공급되는 전압을 수치로 표현하기 위해서 주어진 비트의 최대 값을 표준전압의 최대 값과 동일하게 설정하게주고 비율에 따라 전압 값을 레지스터의 숫자 값으로 변환해준다.

 

예를 들어 16bit레지스터에 최대 3.3v 전압이 허용되고 입력된 전압이 1.5v라 하면,

3.3v/65535 * X = 1.5v에서 XADC의 변환 값이 되는 것이다.

 

입력 받은 전압을 수치로 변환하여 ADC레지스터에 저장하는데 숫자를 저장하는 단위마다 16bit(2byte)가 필요하다.

 

연속된 아날로그 값을 불연속적인 디지털로 바꾸게 되면 불연속구간의 존재 때문에 아날로그 원본과의 차이를 가지게 된다. 끊어져 있는 디지털 값들의 간격을 줄이게 되면 원본과의 차이는 줄어들지만 용량이 늘어난다는 단점이 있다.

 

3분짜리 음악을 저장하기 위해서는 30MB의 용량이 필요하다.

 

화소는 화면을 표시하는 점 개수를 말한다. 일반적으로 1024*768이다.

RGBREG, GREEN. BLUE로 색을 표시하는 기법을 말한다. 한 색깔 1byte(256)단계로 색을 표현한다. 때문에 사진 한 장이 차지하는 용량은 2MB가 된다.

 

영상은 초당 24프레임이라 가정하고 2시간 영화의 경우 379GB가 필요하다.

 

 

엄청난 용량이기 때문에 압축을 필요로 한다.







 

ADC4번을 쓰기로 하고 회로를 만들어주자.

 

 

코딩을 해보자

 

-ADC 클럭 공급(PMC_PCER, ID_ADC)

-ADC 하드웨어 리셋(ADC_CR, ADC_SWRST)

-ADC 4번 채널 활성화(ADC_CHER, ADC_CH4)

-ADC 분해능 10bit / 샘플링 4mb


#include <project.h>

void ADC_Init()
{
  *AT91C_PMC_PCER = 1 << AT91C_ID_ADC;  //CLK supply to ADC
  *AT91C_ADC_CR = AT91C_ADC_SWRST;    //resets the ADC simulating a hardware reset
  *AT91C_ADC_CHER = AT91C_ADC_CH4    //enables ADC channel 4
  *AT91C_ADC_MR = AT91C_ADC_PRESCAL & (~AT91C_ADC_LOWRES_10_BIT)
  ///////////////// as far 9/16 //////////////////
  
  
}

반응형

'Busan IT > ARM Controller' 카테고리의 다른 글

ARM Core3 M3 프로그래밍 환경 설정  (0) 2015.10.05
ADC 전압측정  (0) 2015.09.18
PWM(Pulse Width Modulation)  (0) 2015.09.14
PWM(Pulse Width Modulation Controller)  (0) 2015.09.11
초음파 센서 동작  (0) 2015.09.10
Posted by newind2000
Busan IT/ARM Controller2015. 9. 14. 17:30

#include <project.h>

void PWM2_Init()
{
  *AT91C_PMC_PCER = 1<<(AT91C_ID_PWMC);  //clock into PWM
  *AT91C_PIOA_PPUDR = (AT91C_PA25_PWM2);//pull-up register disable
  *AT91C_PIOA_PDR = (AT91C_PA25_PWM2);  //PIOA pin disable
  *AT91C_PIOA_BSR = (AT91C_PA25_PWM2);  //Prepheral B 25(PWM2) enable
  *AT91C_PWMC_MR = (30 << DIVA) |(0x03<< PREA) 
    | (30 << DIVB) |(0x03<< PREB);  //200,000hz
  *AT91C_PWMC_CH2_CMR = AT91C_PWMC_CPRE_MCKA & (~AT91C_PWMC_CALG)
  & (~AT91C_PWMC_CPOL) & (~AT91C_PWMC_CPD);  //channel mode register
  *AT91C_PWMC_CH2_CPRDR = MAXDUTY;    //Channel Period Register
  *AT91C_PWMC_CH2_CDTYR = DEF_DUTY;      //Channel Duty Cycle Register  
  *AT91C_PWMC_ENA = AT91C_PWMC_CHID2;  //PWMC Enable Register  
}
//타이밍도 486
//파형의 왼쪽을 늘이고 줄이는 레지스터 CDTY
//파형의 오른쪽을 조절하는 레지스터 CPRD
void Set_Duty(int iDuty)  //duty rate 조절 
{
  if(iDuty > MAXDUTY)
    iDuty = MAXDUTY;
  else if0 > iDuty)
    iDuty = 0;
  //파형 중간에 듀티비를 수정할 수 없음으로 update register를 사용한다.
  *AT91C_PWMC_CH2_CUPDR = iDuty;//Channel Update Register
  

}


동영상 - https://www.youtube.com/watch?v=a9irzMGpZFc&feature=youtu.be


반응형

'Busan IT > ARM Controller' 카테고리의 다른 글

ADC 전압측정  (0) 2015.09.18
Analogue to Digital Converter  (0) 2015.09.17
PWM(Pulse Width Modulation Controller)  (0) 2015.09.11
초음파 센서 동작  (0) 2015.09.10
초음파 센서  (0) 2015.09.09
Posted by newind2000
Busan IT/센서 제어2015. 9. 14. 13:51

초음파 센서를 사용하여 센서 앞 10cm 거리에 물체가 있을 경우 빨간불이 켜지도록 코딩해 보자.



20150914.zip


동영상 - https://www.youtube.com/watch?v=V0EqM1Y9PMs

반응형

'Busan IT > 센서 제어' 카테고리의 다른 글

적외선 센서 코딩  (0) 2015.09.24
서머 커플러, 적외선 센서  (0) 2015.09.24
온도계 섭씨 화씨 변경, 초음파의 특성  (0) 2015.09.10
C#을 활용한 NTC 온도 센서  (0) 2015.09.04
NTC 온도계 저항값 변환  (0) 2015.09.04
Posted by newind2000
Busan IT/ARM Controller2015. 9. 11. 17:36

==================================Outline====================================

PWM(Pulse Width Modulation Controller)

----------------------------------------------------------------------------

 

PWM(Pulse Width Modulation Controller)

 

 

비교기를 활용하여 펄스의 폭을 조절하는 것이 pwm이다.

 


 

PWM_SR(PWM status register) - PWMon/off 상태를 담고 있는 레지스터이다.

PWM_ENA(PWM Enable) - PWM을 작동시키는 레지스터

PWM_DIS(PWM Disable) - PWM을 작동을 멈추는 레지스터

PWM_CPRD - PWM의 삼각형 모양을 제어한다.

PWM_CLTY - 펄스의 넓이를 제어한다.

 

즉 펄스의 넓이는 PWM_CPRDPWM_CLTY를 사용하여 조절해야 한다.

 

피라미드형의 파형은 펄스의 넓이를 중간으로부터 양쪽으로 늘여줄 수 있고, 톱니형의 경우에는 우측 끝을 기준으로 좌측으로 넓이를 늘여줄 수 있다.

 

파형의 한 주기마다 인터럽트가 발생함으로 타이머/카운터의 성질을 가지고 있음을 알 수 있다.

 

 

Peripheral B를 선택하여 25번 핀에 있는 PWM2를 선택하자.

 

 /*** pwm.c ***/

 #include <project.h>


void PWM2_Init()
{
  *AT91C_PMC_PCER = 1<<(AT91C_ID_PWMC);  //clock into PWM
  *AT91C_PIOA_PPUDR = 1<<(AT91C_ID_PWMC);//pull-up register disable
  *AT91C_PIOA_PDR = 1<<(AT91C_ID_PWMC);  //PIOA pin disable
  *AT91C_PIOA_BSR = 1<<(AT91C_ID_PWMC);  //Prepheral B 25(PWM2) enable
  *AT91C_PWMC_MR = (30 << DIVA) |(0x03<< PREA) 
    | (30 << DIVB) |(0x03<< PREB);  //200,000hz
  *AT91C_PWMC_CH2_CMR = AT91C_PWMC_CPRE_MCKA & (~AT91C_PWMC_CALG)
  & (~AT91C_PWMC_CPOL) & (~AT91C_PWMC_CPD)  //channel mode register
  
}


반응형

'Busan IT > ARM Controller' 카테고리의 다른 글

Analogue to Digital Converter  (0) 2015.09.17
PWM(Pulse Width Modulation)  (0) 2015.09.14
초음파 센서 동작  (0) 2015.09.10
초음파 센서  (0) 2015.09.09
ARM 타이머/카운터 소스, 초음파 센서 거리측정식  (0) 2015.09.09
Posted by newind2000
Busan IT/ARM Controller2015. 9. 10. 17:14

==================================Outline====================================

초음파 센서 동작

----------------------------------------------------------------------------

 

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

 

 

타이밍도를 보면 펄스를 10us 동안 high로 유지하면 ultrasonic8 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;
}







반응형

'Busan IT > ARM Controller' 카테고리의 다른 글

PWM(Pulse Width Modulation)  (0) 2015.09.14
PWM(Pulse Width Modulation Controller)  (0) 2015.09.11
초음파 센서  (0) 2015.09.09
ARM 타이머/카운터 소스, 초음파 센서 거리측정식  (0) 2015.09.09
Timer/Counter  (0) 2015.09.07
Posted by newind2000
Busan IT/센서 제어2015. 9. 10. 13:48

==================================Outline====================================

온도계 섭씨 화씨 변경

음파의 특성

----------------------------------------------------------------------------


온도계 섭씨 화씨 변경

외부인터럽트를 활용하여 버튼을 누를때마다 표시형식이 섭씨와 화씨를 오고가게 만들어보자.


인터럽트를 사용할 핀에 스위치를 연결해 주고 코드만 간단히 수정해주면 된다.

/*** 코드 ***/

void FND_Display(unsigned char ucTD, unsigned char ucUD, unsigned char ucDP)
{

  PORTA = cFND[ucDP];  
  PORTC = 0x06 ;
  _delay_ms(2);

  PORTA = cFND[ucUD] | cFND[10];  
  PORTC = 0x05;
  _delay_ms(2);

  PORTA = cFND[ucTD];  
  PORTC = 0x03;
  _delay_ms(2);

}

void F_Convert(int temp)
{
  temp = temp * 1.8 + 320;


  FND_Display(temp/100, (temp%100)/10, temp%10);
  
}

void __vector_5(void)
{
  iFlag ^= 0x01;
  if(iFlag == C)
    PORTJ = 0X02;
  else
    PORTJ = 0X01;
}

/*** 동영상 ***/


https://www.youtube.com/watch?v=3hx9BH189ec


음파의 특성


인간이 들을 수 있는 주파수(가청 주파수)의 영역은 20 - 20kHz이다. 20Hz의 주파수를 저주 파 20,000Hz 이상의 주파수를 초음파라고 부른다.

 



 

파동은 직진성과 회절성을 가진다. 회절성은 파동이 휘어지는 성질이다.

 

낮은 주파수 대역을 만드는 기계를 우퍼라고 한다.

 

주파수와 회절성은 반비례하고 직진성과 주파수는 비례한다.

 

회절성에 따라 통신 수신의 사각지대가 줄어든다.

 

진동은 사물을 만나면 투과, 반사 혹은 흡수 된다.

 

주파수는 붉은색계열이 주파수가 낮고 파란색 계열이 주파수가 높다. 때문에 높은 주파수 계열을 사용하면 분해능이 증가한다.

 

주파수의 소리와 흡수는 사물의 밀도에 따라 달라진다. 밀도가 높으면 반사율이 높고 밀도가 낮으면 흡수율이 높다.

반응형

'Busan IT > 센서 제어' 카테고리의 다른 글

서머 커플러, 적외선 센서  (0) 2015.09.24
자동차 후진 경고 센서  (0) 2015.09.14
C#을 활용한 NTC 온도 센서  (0) 2015.09.04
NTC 온도계 저항값 변환  (0) 2015.09.04
NTC 센서를 활용한 온도계  (0) 2015.09.02
Posted by newind2000
Busan IT/ARM Controller2015. 9. 9. 17:41

==================================Outline====================================

초음파 센서

----------------------------------------------------------------------------

 

ARM에서는 인터럽트가 발생할 시 작동하는 함수의 주소를 넣어주어야 해당 함수가 실행된다. C에서 함수의 주소는 함수 자체의 이름이기 때문에 함수가 실행될 자리에 함수 이름을 넣어주면 된다.

 

실행될 함수의 주소가 적힌 테이블을 벡터 테이블이라고 한다.

 





/*** ultra.c(진행중) ***/


static volatile unsigned int uiCM;
static volatile unsigned int uiState = INIT_OFF;

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 = 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_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()
{
  U_Trigger_Init();    
  
  uiState = INIT_ON;
  
}

int Ultra_Run()
{
  if(uiState == INIT_OFF)
  {
    return;
  }  
  U_Trigger();    

  return;
}

 

 

반응형

'Busan IT > ARM Controller' 카테고리의 다른 글

PWM(Pulse Width Modulation Controller)  (0) 2015.09.11
초음파 센서 동작  (0) 2015.09.10
ARM 타이머/카운터 소스, 초음파 센서 거리측정식  (0) 2015.09.09
Timer/Counter  (0) 2015.09.07
주파수와 ARM 메모리맵  (0) 2015.08.28
Posted by newind2000