Busan IT/ARM Controller2015. 10. 5. 13:31

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

ARM Core3 M3 프로그래밍 환경 설정

- 개발환경 설정을 위한 다운로드

- STM32 Cortex-M3의 기본 설명

- 예제 프로그래밍을 통한 기능 확인

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

개발환경 설정을 위한 다운로드

우선 새로 지급 받은 CortexM3관련 자료를 자료실에서 몽땅 다운로드 받자.

(FTP 자료실(192.168.0.2)-> 수업자료 -> Digital -> CortexM3)

- 데이터 시트

- 회로도

** 데이터 시트/회로도 다운 http://www.jkelec.co.kr/img/arm/cortex-m3/rabbit_stm32_lqfp64/rabbit_stm32f10x_manual.htm

- 펌웨어 메뉴얼

** st.com에 접속하여 program manual과 reference manual 다운받기

http://www.st.com/web/catalog/mmc/FM141/SC1169/SS1031/LN1565/PF164495?s_searchtype=partnumber

- 컴파일러(Keil)

** Keil 컴파일러 다운 https://www.keil.com/demo/eval/arm.htm#DOWNLOAD

** MDK v4 Legacy Support - http://www2.keil.com/mdk5/legacy

- 프로그램 전송(um0462.zip)


STM32 Cortex-M3의 기본 설명

- STM32 Cortex-M3 에 기반한 32bit ARM 개발보드로 STM32F103VCT6 MCU를 사용하여 최대 72 MHz 속도로 동작 하고 CPU모듈과 Bottom보드가 분리되어 있다. Rabbit Bottom 보드에는 CMOS Camera, nRF24L01 RF, 터치 LCD 등의 다양한 모듈들을 연결하여 테스트 할 수 있다.


전원부는 5v를 입력 받아 3.3v로 변환하여 사용한다

- 우리가 사용하는 보드의 핀은 144핀임으로 다른 핀 설명은 무시하도록 하자.

 

- 시리얼 포트를 이용하여 프로그램을 올릴 예정임으로 'SERIAL_J1'을 주로 사용한다.

- ARM사의 컴파일러는 크게 KeilIAR이다. Keil은 프로그램 예제는 많이 없지만 회사에서 많이 쓰이는 컴파일러이다. 반면에 IAR은 예제가 많이 존재한다.

 

- 데이터 시트를 통해 내용을 살펴보자.



 

- remap기능을 활용하면 GPIO를 제외한 기능을 여러 곳에서 사용하는 것이 가능하다.

 

[Table 5. High-density STM32F103xC/D/E pin definitions] 해당 표를 많이 사용하게 될 것이다.

- 직접 메모리 액세스를 위해서는 위의 표가 필요하다.

 

- keil 컴파일로 다운 받아 위의 업데이트를 수행한다.


예제 프로그래밍을 통한 기능 확인

다운 받은 keil을 실행시킨다.

'project' -> 'open project'를 선택한다.

자료실에서 받은 예제프로그램을 실행시킨 후 하이퍼터미널로 명령어를 전송하여 각 기능을 동작시켜본다.


반응형

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

내부 LED 반전 프로그램 만들기  (0) 2015.10.08
ARM 3 Core Test, 내부 LED 동작 프로그래밍  (0) 2015.10.06
ADC 전압측정  (0) 2015.09.18
Analogue to Digital Converter  (0) 2015.09.17
PWM(Pulse Width Modulation)  (0) 2015.09.14
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/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/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
Busan IT/ARM Controller2015. 9. 9. 09:12

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

ARM 타이머/카운터 소스 

초음파 센서 거리측정식

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


ARM 타이머/카운터 소스


20150908.zip


** main.c에서 TIMER_Init을 호출하지 않아 1초마다 LED 깜빡이는 코드가 작동하지 않았다.

/*** timer.c ***/

#include "timer.h"

static volatile unsigned int uiMSec;    //milli second

// 0번 타이머 접두어: TC0 // 1번 타이머 접두어: TC1 // 2번 타이머 접두어: TC2
// 예: #define TC0_CCR    ((volatile unsigned int *)0xFFFA0000)
// 인터럽터 관련 : AT91C_BASE_AIC
// 0번 타이머 관련 : AT91C_BASE_TC0
// PMC 관련   : AT91C_BASE_PMC

void TIMER_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;  
// 인터럽트 상태 정보 초기화(TC_SR 읽기)
  *AT91C_TC0_SR;  // 초기화 :: 수행되면 레지스터가 초기화된다.

// 분주비 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;  
  

// 타이머 카운터 0 인터럽트 비활성화(AIC_IDCR, AT91C_ID_TC0)
  *AT91C_AIC_IDCR = 1 << AT91C_ID_TC0; 
  
// 3. 시작 : 타이머 카운터 0 인터럽트 비활성화 ------

// 타이머 카운터 0 인터럽트 핸들러 등록(AIC_SVR[AT91C_ID_TC0], timer_handler)
  AT91C_AIC_SVR[AT91C_ID_TC0] = (unsigned int)Timer_ISR;  

// 타이머 카운터 0 인터럽트 모드 설정(AIC_SMR[AT91C_ID_TC0], AT91C_AIC_SRCTYPE_INT_HIGH_LEVEL, AT91C_AIC_PRIOR_LOWEST)
  AT91C_AIC_SMR[AT91C_ID_TC0] = AT91C_AIC_SRCTYPE_INT_HIGH_LEVEL | AT91C_AIC_PRIOR_LOWEST;

// 타이머 카운터 0 인터럽트 클리어(AIC_ICCR, AT91C_ID_TC0)
  *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 = 375;
// 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;


}


void ms_delay(unsigned int uiMS)
{
  uiMSec = 0;
  while(uiMSec < uiMS);
}

void Timer_ISR(void)
{
// 인터럽트 상태 정보 초기화(TC_SR 읽기)
  *AT91C_TC0_SR;  // 초기화 :: 수행되면 레지스터가 초기화된다.
  ++uiMSec;

}


초음파 센서 거리측정식


초음파 센서가 1cm 앞에 있는 물체를 감지하는데를 걸리는 시간(클럭)을 측정 해보자.

소리의 속도는 340m/s 이고 이를 cm로 표현하기 위해 100을 곱하면 34,000cm/s 이다. 


비례식으로 나타내면 1초 : 34,000cm = x초 : 1cm이다.

외항과 내항을 곱하면 1cm/초 = (34,000)(x)cm/초 이므로

x = 1/34,000임으로 값은 0.00002941176470588240이다. 초음파를 측정하기 위해서 보낸 초음파를 다시 받아야 하기 때문에 곱하기 2를 해주어야 한다.

소리의 속도(m/s)소리의 속도(cm/s)1cm 이동시간 * 2

340

     34,000

0.00005882352941176470


즉 주파수가 분주비에 의해 0.00005882352941176470 가 되는 수를 찾아야 한다.


128분주의 오차가 가장 작음으로 128분주를 사용할 것이다. 128분주의 오차를 계산하면 아래 표와 같다.


반응형

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

초음파 센서 동작  (0) 2015.09.10
초음파 센서  (0) 2015.09.09
Timer/Counter  (0) 2015.09.07
주파수와 ARM 메모리맵  (0) 2015.08.28
Interrupt Code, 초음파 센서 SRF05, Timer/Counter  (0) 2015.08.19
Posted by newind2000
Busan IT/ARM Controller2015. 9. 7. 17:40

==================================Outline====================================
Timer/Counter

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

 

flash는 모델에 따라 크기가 달라지며 AT91SAM7256의 경우는 256kb 사용할 수 있다.

 

Internal Memory는 3가지 영역으로 나뉜다 :: flashSRAM 그리고 remap을 기준으로 flash()SRAM()


remap이 수행되면 cstartup.s 코드(주파수 변환)가 동작한다.

 

AT91SAM7256에서 Timer/Counter는 총 3(TC0 ~ TC2)가 있으며 카운터는 모두 16bit이다. , 0에서 65535까지 셀 수 있는 카운터이다.

 

현재 우리가 사용하는 ARM의 주파수는 48Mhz이므로 분주비와 카운터를 사용하며 원하는 단위 카운터의 시간을 만들 수 있다.



 

의사코드(psudo code)를 보고 Timer/Counter를 사용해보자.

 

//정의된 헤더파일이 없더라도 메모리맵을 보고 코딩을 할 수 있는 소양을 길러야 한다.



 // Timer.c

// 0번 타이머 접두어: TC0 // 1번 타이머 접두어: TC1 // 2번 타이머 접두어: TC2
// 예: #define TC0_CCR    ((volatile unsigned int *)0xFFFA0000)
// 인터럽터 관련 : AT91C_BASE_AIC
// 0번 타이머 관련 : AT91C_BASE_TC0
// PMC 관련   : AT91C_BASE_PMC

static unsigned int uiMsec;   //카운팅을 위한 전역 변수, 외부 접근을 막기 위해 static 선언

void Timer_Init(void)
 {
//p/33 장치번호표, p/20 memory map, T/C 주요 레지스터 p/463

// 타이머 카운터 0 사용을 위한 PMC 활성화(AT91C_ID_TC0)
   *AT91C_PMC_PCER = AT91C_ID_TC0;
// 1.시작 : 타이머 클럭 비활성화 ------------------
// 타이머 클럭 비활성화(TC_CCR 설정)
   *AT91C_TC0_CCR = AT91C_TC_CLKDIS;
   
   

// 2. 시작 : 타이머 인터럽트 비활성화 -------------

// 타이머 인터럽트 비활성화(TC_IDR 설정)
   *AT91C_TC0_IDR = 0xFF;   //타이머 인터럽트 모두 비활성화
   
// 인터럽트 상태 정보 초기화(TC_SR 읽기)
   *AT91C_TC0_SR;  //읽으면 자동으로 지워 지기 때문에 읽기만 하면 초기화 된다.  

// 분주비 128, 비교 방식 레지스터 설정(TC_CMR, DIV4_CLOCK, AT91C_TC_CPCTRG)
   *AT91C_TC0_CMR = 1<<AT91C_TC_CLKS_TIMER_DIV4_CLOCK | AT91C_TC_CPCTRG;

// MCKR divided by 128 => 2.7us(TC_RC 설정)
   

// 타이머 카운터 0 인터럽트 비활성화(AIC_IDCR, AT91C_ID_TC0)
   *AT91C_AIC_IDCR = 1<<AT91C_ID_TC0; 

// 3. 시작 : 타이머 카운터 0 인터럽트 비활성화 ------
// 타이머 카운터 0 인터럽트 핸들러 등록(AIC_SVR[AT91C_ID_TC0], timer_handler)
   AT91C_AIC_SVR[AT91C_ID_TC0] = (volatile unsigned int)Timer_ISR;
   
// 타이머 카운터 0 인터럽트 모드 설정(AIC_SMR[AT91C_ID_TC0], AT91C_AIC_SRCTYPE_INT_HIGH_LEVEL, AT91C_AIC_PRIOR_LOWEST)
   AT91C_AIC_SMR[AT91C_ID_TC0] = AT91C_AIC_SRCTYPE_INT_HIGH_LEVEL | AT91C_AIC_PRIOR_LOWEST;

// 타이머 카운터 0 인터럽트 클리어(AIC_ICCR, AT91C_ID_TC0)
   *AT91C_AIC_ICCR = 1<<AT91C_ID_TC0;    인터럽트 초기화

// TC_RC 값 비교 타이머 인터럽트 활성화(TC_IER, AT91C_TC_CPCS)
   *AT91C_TC0_IER = AT91C_TC_CPCS;
   *AT91C_TC0_RC = 375;

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

 }


void Timer_ISR(void)  //0.001초마다 호출
{
// 인터럽트 상태 정보 초기화(TC_SR 읽기)
   *AT91C_TC0_SR;

   ++uiMsec;

   
 }

void ms_Delay(unsigned int uiMs)
 {
   uiMsec = 0;
   while(uiMsec < uiMs);  
 }   
  


반응형
Posted by newind2000
Busan IT/ARM Controller2015. 8. 28. 17:35


 

회로를 작동 시키기 위해서는 명령 전달의 기준이 되는 클럭 신호가 필요하다. 시간 단위당 클럭 신호의 횟수를 주파수라고 한다.

 

PMC(Power Management Controller)는 주파수를 만들어주는 회로이다. PMC는 회로 작동을 발전기이다.

 

MCU마다 주파수는 정해져 있지만 이것을 소프트웨어적으로 변환할 수 있다. 이것이 PLL이다. 현재 사용하고 있는 소스코드에서 lowlever.c가 주파수를 변환시키는 코드를 가지고 있다.

 

USB의 클럭 신호와 회로 구성이다.

//어셈블리의 확장자: 윈도우에서는 asm, linux에서는 s

 

데이터시트에서 메모리맵은 코딩을 하는데 필수적인 요소이다. ATmegaARM의 데이터 시트는 비교적 친절하게 레지스터나






메모리맵이 설명되어 있다. Cortex 데이터시트는 형편없다.

 

 

 

firmware를 만들 때 가장 먼저 시작되는 함수는 load함수이다.

cstarup.s파일에서 ldrload를 명령으로써 프로그램을 시작하는 기준점이 된다.

pc는 어셈블리 레지스터에서 EIP역할, 즉 다음 수행할 명령어를 가리키는 포인터 역할을 한다.



반응형

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

ARM 타이머/카운터 소스, 초음파 센서 거리측정식  (0) 2015.09.09
Timer/Counter  (0) 2015.09.07
Interrupt Code, 초음파 센서 SRF05, Timer/Counter  (0) 2015.08.19
ARM UART Interrupt  (0) 2015.08.14
ARM USART(2)  (0) 2015.08.12
Posted by newind2000