블로그 이미지
송시혁

calendar

1 2 3 4 5
6 7 8 9 10 11 12
13 14 15 16 17 18 19
20 21 22 23 24 25 26
27 28 29 30

Notice

Tag

Recent Post

Recent Comment

Recent Trackback

Archive

2013. 10. 17. 08:48 임베디드/Arm2567SAM


cStart. 소스 파일에서 주석문을 제외하고 제일 처음에 vector table을 만나게 된다.


ldr 명령어는 레지스터에 해당주소를 저장하는 레지스터?(말이 이상함)



위 빨간네모를 보면 pc(program counter)에 reset_handler에 주소를 가지게 된다.

reset_handler는 아래와 같다.



위 그림에서 또 다시 pc에 _low_level_init에 주소를 가진다. 이제 부터 추적, 추적을 해서 복잡하게 될것이다.


_low_level_init은 아래그림과 같다.




ldr 명령어로 레지스터 r2 아래그림의 라벨을 따르고 있다. 그전에 알아야 할것은 arm은 레지스터가 총 r0~

r15까지 16개의 레지스터가 있다. 그중에서 r0~r12까지는 일반 레지스터이다. r13~r15까지는 특정 레지스터이다.

설명은 위의 그림의 주석으로 설명함.



이 그림에서 2개의 .word ~~~~가 있다. 

ldmia 명령어에 의해서 r0=lowlevel_init

r1=TOP_OF_MEMORY를 가르키게 된다. 그리고 그것을 통째로 r2가 가르키는 것이다.



위의 그림보다 더 길지만, 자세하게 하지않으므로 생략. init함수에서 우리가 확인 하는 것은 주파수체배기 18MHz정도 되는 주파수를 48MHz로 증폭하는 소스이다. (하드웨어 회로도 구성되어 있으며 그것을 동작하기 위한 함수라는 것만 확인

하면 되겠다.)



다음은 TOP_OF_MEMORY를 추척해보면 다음과 같은 그림이 나온다.


위의 헤더파일 200000과 10000이 정의되어 있다. 이 주소를 더하면 0x210000이 된다. 즉, sram의 

주소 시작주소이다.








다음은 메모리 map이다. 아래 그림처럼 SRAM영역은 0X0020000부터 0X002FFFF로 되어있다.

그러나 부팅 CODE에 의해서 0X210000이 된다.






'임베디드 > Arm2567SAM' 카테고리의 다른 글

4월 relay 정리  (0) 2013.06.02
4월 LED정리  (0) 2013.05.31
4월 17일 LCD문자입력함수 만들기  (0) 2013.05.30
4월 16일 CMD_Write와 DATA_write함수 만들기  (0) 2013.05.28
5월 27일 LCD에 한글이름 찍기  (0) 2013.05.27
posted by 송시혁
2013. 6. 2. 10:58 임베디드/Arm2567SAM

main()함수


먼저 main()함수에서 relay_init()을 호출한다.

아래 그림의 relay_init()함수를 주목한다.

realay.c



헤더파일에서 RELAY_PIN은 1로 정의하였다. 이것은 1번핀을 relay와 arm칩을 연결하기 위해서이다.






p248


init ()함수에서 

PIO_OER =1<<RELAY_PIN; -> 출력 활성화 레지스터에  1번자리에 1을 넣어 출력 활성화한다.

P250참고





P251참고


PIO_PER = 1<<RELAY_PIN;-> 핀을 활성화 레지스터. 1번핀을 사용하기 위해 핀 활성화 레지스터 1번 자리에 1을 넣는다.

PIO_SODR =1<<RELAY_PIN;->출력 데이터 레지스터 자리에 1을 넣어 high값으로 만든다.


P254참고


main()함수에서 init()함수가 호출되고 셋팅되어 아래 반복문이 실행된다.

dbgu 하이퍼 터미널과 연결이 되어 3번을 누르는 순간, 딸깍하는 소리가 나야 한다. 그러기 위해서 

relay_toggle()함수


static unsigned int uiState=0; 전역변수 선언. 전역변수는 한 번만 초기화 한다.

다음 조건에 만즌 if문이 실행된다. 

PIO_CODR=1<<RELAY_PIN; -> 출력데이터를 0v로 만드는 레지스터에 1번 자리에 1을 넣어 출력데이터를 0v로 만든다.

p255참고



uiState = 1; 그리고 uistat를 1로 만든다.

그러면 if문이 종료되고 함수가 종료된다.



다시 main()에서 반복문에 의해 실행되고 한번 더 3번으 누르면, relay_toggle()함수가 호출된다.

uiState가 if문에서 종료직전에 1을 넣었기 때문에 else문으로 가서 실행된다.


PIO_SODR=1<<RELAY_PIN; ->출력 데이터 레지스터 자리에 1을 넣어 high값으로 만든다.

p250참고

uiState = 0; ->다시 0을 넣는다.


이런방식으로 계속해서 반복하여 '딸깍'소리를 낼수 있게 동작한다.

그리고 relay를 결선시 아래그림을 참고하여 결선.




posted by 송시혁
2013. 5. 31. 21:48 임베디드/Arm2567SAM


LED는 발광다이오드, 빛을 내는 센서.

ARM칩에 핀을 활성화하여 결선하여 led를 동작하게 만든다.

그래서 스펙에 핀에 해당하는 PIO(병렬 입출력)레지스터를 참고하여 INIT()함수를 만든다.


먼저 헤더파일을 정의 한다.



그리고 LED_PIN은 0으로 정의 하여, 0번자리에 LED를 꽂아서 사용하기 위함.



아래표를 참고하여 주소값을 적어 준다.



위의 스펙 20페이지에 PIO에 해당하는 MEMORY  주소만, 잘라서 붙인 그림이다.위의 빨간색 네모가 PIO의 시작수소이다.




시작주소가 0XFFFF F400이다. PIO_PER같은 경우는 OFFSET이 0X0000이므로 그대로 0XFFFF F400이 된다.

그러나 PIO_PER는 0X0010이므로 0XFFFF F400에서 0X0010더하여 0xFFFF F410이 된다. 

아래그림도 동일하다.





아래그림은 LED.C의  init()함수 소스 파일이다.




INIT()함수에서 목적은 핀 활성화에 있다.

0번의 핀을 활성화 하기 위해서, 위의 그림과 같이 3단계를 거친다.

1. 출력을  활성화=핀을 사용하기 전에 ARM칩으로 전류를 보내어 LED를 동작시키기 때문에

    출력레지스터인 PIO_OER을 활성화 시킨다. 


PIO_OER  = PIO출력 활성화 레지스터


다음은 PIO_OER의 관한것이다.


핀을 모두 다 사용이 가능하다. 0번자리를 사용하는데 헤더파일에 이미 LED_PIN을 0으로 정의 했기 때문에

1<<LED_PIN을 PIO_OER에 넣으면 된다.0을 넣으면, 아무런 효과가 없다.

그래서 PIO_OER=1<<LED_PIN;


2. 핀 활성화 

    PIO_PER =PIO 활성화 레지스터


PIO_CODR=출력데이터 클리어(0V), 0v로 만들때 사용. LOW신호

PIO_CODR=1<<4;인 경우, 4번자리에 1을 넣으면, 비활성화 된다.



3. 출력 데이터를 셋팅, 즉 사용하고자 하는 해당비트에 1을 넣었을때, high값을 갖느다.

    

PIO_SODR= 출력데이터 셋(set, 5v), vcc(5v,3.3v), HIGH일때 사용.

PIO_SODR=1<<4;인 경우 4번 자리에 활성화









 MAIN()함수.



LED_TOGGLE() 함수



LED를 역방향으로 연결한다. 그이유는 ARM칩의 흐르는 고유의 전류(PC로부터 연결하여 받는 전류가 아닌)

가 LED로 흐를 수 있다고 생각하여 안전을 위하여 LED를 역방향으로 연결한다.

즉, VCC의 5V가 인가하면, 꺼지고 0V일때, 켜지게 해야 한다.




MAIN함수에서 토글 함수를 한 번 호출이 된다. 그러면, 아래와 같이 IF문이 실행되면서, 

LED불이 잠시동안 꺼진다.

(참고로 MS_Delay함수는 말그대로 지연 함수이다.)



토글함수 세부내용.

static unsigned int uiState=0;일단 먼전 변수를 선언한다.


if(0==uiState)

{

PIO_CODR=1<<LED_PIN;

uiState = 1;


}

uiState가 0이면, PIO_CODR= 0번핀을  출력데이터를 0V로 만들어주는 레지스터에 넣으면, 0V가 되어

LED가 꺼진다. 

PIO_CODR= LEC_PIN;

실행되고 난 뒤, uiState = 1;을 넣고 함수가 한 번 종료한다.

그러면 LED불은 꺼지고 함수는 종료한다.


else

{

PIO_SODR=1<<LED_PIN;

uiState = 0;

} 

다시 MAIN에서 MS_DELAY함수가 실행되고 시간이 지나면, 두 번째 토글함수가 실행된다.

이 때, 변수 uiState 마지막에 1을 대입하여 1이되기 때문에 else문이 실행된다.


이번에는 PIO_SODR=1<<LED_PIN; 0번 자리에 출력데이터를 5V 또는 3.3V(led는 5V일 경우 탈 수도 있기에

여기서는 3.3V)를 받아 led의 불이 들어온다.그리고 다시 uiState =0;이 된다. 그래서, 무한 반복문 while(1)에 의해

계속 깜박이면서 꺼졌다 켜쪘다를 반복한다.


static unsigned int uiState=0; static을 사용한 이유


1.static변수를 선언한 이유는 한 번만 초기화가 되기 때문에 if와 else문이 번갈아 동작된다. 

만약에 그냥 변수를 썼다고 가정하면, if/else문이 실행되기전에 항상 0이라는 값으로 초기화 하므로 

조건에서 if문만 만족하여 led는 항상 꺼지는 상태가 된다.


지역변수는 함수가 호출되면 종료되고 다시 함수가 호출

되어 생성되고 , 즉 생성과 삭제가 반복이 되기 때문에 속도가 느리다. 

따라서, static을 써주면, 항상 고정되어 있기 때문에 프로그램인 종료되지 않는 이상 사라지지 않는다.

그래서 삭제와 생성이 반복되지 않아 속도가빠르다. 즉, 함수실행에서 속도가 빠른것.

 

posted by 송시혁
2013. 5. 30. 21:02 임베디드/Arm2567SAM


LCD STRING함수는 인자로 문자를 입력받아서 LCD에 문자를 출력하게 하는 함수이다.


main()함수에

LCD_String("hello"); 호출하여 인자로 출력하고픈 문자열을 인자로 받는다.

void *vp void형으로 한 이유는 정해진 자료형이 없기 때문이다.




while(1) 무한 반복문을 돌린 이유는 "HELLO"문자열 즉, H,E,L,L,O,\0인데 이것을 

처음에는 H,E,.....순으로 LCD_Data_WRITE에 넘겨야 LCD에 문자가 찍히기 때문이다.




*((unsigned char *)vp 캐스탕한 이유는 void형이라 자료형이 없다. 그래서 문자이고 양의 정수 값인 

unsigned char형으로 캐스팅한다. 그리고 앞에 '*'를 붙여서 포인터 값을 의미한다. 

즉, vp도 주소를 가진다고 보면 된다. 그 주소를 지금, "hello"문자의 주소를 받아서 LCD_Data_WRITE()에서

데이터를 입력받아 LCD에 찍는다. 

vp= (unsigned char *)vp+1;는 HELLO라는 글자에서 먼저 'H'를 찍으면 그다음 배열 인덱스 주소인 'E'를 찍기위해

VP에다가 1을 더한것이다.  (unsigned char *)vp+1에  (unsigned char *)캐스팅 부분이다. 실제로는 VP=VP+1;

이므로 주소를 더하고 있다고 생각하면 된다. 주소를 1더해서 'H'다음에 'E'를 포인터 VP가 가르키고  LCD_Data_WRITE()에 호출된다.

이과정을 반복하다가 NULL값인 0을 만나면, while문은 종료가 된다.



다음 소스는 lcd에 숫자를 출력하는 함수

void LCD_Number(unsigned int iLine, unsigned short usNum)
{//
  unsigned char ucString[]= "00000";

  ucString[0]= '0' + (usNum/10000);
  ucString[1]= '0' + (usNum%10000)/1000;
  ucString[2]= '0' + (usNum%1000)/100;
  ucString[3]= '0' + (usNum%100)/10;
  ucString[4]= '0' + usNum%10;
  ucString[5]= '\0';

  for(cNum = 5; cNum > 0; --cNum)
  {
    ucString[cNum-1] = usNum % 10;
    usNum = usNum / 10;
  }

  if(1==iLine)
  {
    LCD_Cmd_WRITE(0x80);
    LCD_String("TEMP :");
  }
  else
  {
    LCD_Cmd_WRITE(0xc0);
    LCD_String("LIGHT:");
  }
   LCD_String(ucString);


  return;
}

main함수




'임베디드 > Arm2567SAM' 카테고리의 다른 글

4월 relay 정리  (0) 2013.06.02
4월 LED정리  (0) 2013.05.31
4월 16일 CMD_Write와 DATA_write함수 만들기  (0) 2013.05.28
5월 27일 LCD에 한글이름 찍기  (0) 2013.05.27
5월 23일 ULTRA 2.  (0) 2013.05.24
posted by 송시혁
2013. 5. 28. 23:29 임베디드/Arm2567SAM



LCD_Cmd_WRITE함수는 명령을 내리는 함수. 최초의 init함수에서 셋팅이 끝나면, 사용자가 LCD에 명령을 보내야 하는데

 그 역할을 이 LCD_Cmd_WRITE함수가 역할한다. 일단, 먼저 Timing Diagram을 참조해야한다.


1.(빨간색): 

RS=명령을 입력받을때는 LOW값이다. 그래서 PIO_CODR=LCD_RS;

RW = LOW일때, WRITE이므로 PIO_CODR=LCD_RW;

EN= 타이밍도를 보면 LOW인 상태.

DELAY는 타이밍도 전체 지연시간이다.

 

2.(주황색) RS가 명령을 받아 low가 되고  RW는 write에 해당하는 low값을로 변하여 아래로 내려가게 된다. 

하지만, low가 되기전에 delay를 시켜야한는데 얼마만큼 delay하느냐는 타이밍도를 참조해서 구해야 한다.

주황색으로 된 네모를 보면, RS, RW가 내려왔을때 지연되는 시간은 Tas- ter를 하면, 대략 구할 수 있다. 

15ns가 나오는데 전체 delay-delay1(15ns)를 하면 된다. 그 후에는 EN이 high로 되는 것을 볼 수 있다.

 그래서 활성화 레지스터인 PIO_SODR=LCD_EN; 이 된다.


3.  EN이 high로 되는데 시간이 또 걸린다. 그래서 다시 for문으로 다시 지연시킨다. 시간계산을 위해서는 타이밍도를 

보고 만들 수 밖에 없다.  EN이 활성화 된뒤에 DB(데이터 버스)에서 값이 변화하기까지 지연시킨다.

전체 delay에서 ter의 값을 빼면 된다.

PIO_CODR = LCD_BS;BS를 16번자리에만, 0V로 만든다.

PIO_SODR = ucdata<<16; DB가 데이터를 받아 16번자리에 넣는다.


4. 값이 오랫동안 유지되는 구간이다. 그러다가 EN이 내려가는것이 보인다.

    EN이 바로 내려가기 직전까지 전체 delay에서 빼준다.

     LCD_delay - LCD_delay3;

LCD_delay3= pweh-tdsw;


5. EN은 이미 low가 된상태, 다른값들은 유지되는 구간이다. 이 전체delay에서

    빼준다.

    LCD_delay - LCD_delay4;

    LCD_delay4= tef+th










LCD_DATA_WRITE부분은 데이터를 입력받는 부분이기 때문에 RS를 HIGH값으로 바꿔주면 된다.

PIO_SODR= LCD_RS;가 된다.

나머지는 위의 CMD_WRITE와 동일하다.




'임베디드 > Arm2567SAM' 카테고리의 다른 글

4월 LED정리  (0) 2013.05.31
4월 17일 LCD문자입력함수 만들기  (0) 2013.05.30
5월 27일 LCD에 한글이름 찍기  (0) 2013.05.27
5월 23일 ULTRA 2.  (0) 2013.05.24
5월 23일 ultra1(진행중)  (0) 2013.05.23
posted by 송시혁
2013. 5. 27. 16:29 임베디드/Arm2567SAM


LCD에 문자를 출력하기 위해서는 폰트를 만들어야 한다. 폰트에 기본적으로 알파벳은 들어가 있다. 알파벳은 출력하고자 하는 알파벳을 LCD위치만 설정한다면,

CG ROM에서 폰트를 찾아 화면(LCD)에 출력된다.CG ROM에는 기본문자(아스키코드 알파벳, 도형, 일본어, 기타 등....)가 있어서 LCD에 출력이 가능하다.

하지만, 한글은 없다. 그래서 한글 폰트를 만들어야 한다.


폰트를 새로정의 하는 부분은 CGRAM에서 관장한다.

우리가 쓰는 LCD에 해당하는 도트(.)은 가로5칸, 세로7카인 5*7이다.



  7  6   5   4  3  2   1   0


위 그림은 '소'을 찍어내기 위한 도트 LCD모듈에서의 CG RAM adress부분.

제일 윗줄에는 아무것도 나태내지 않기 때문에 전부 0이다. 2번째 부분부터

도트를 찍는데 2번 자리에 1이 들어간다. 나머지는 모두 0이다.

0x04= 0000 0100이기 때문에 밑에 소스에 각 비트에 해당하는 번호를 

넣었다.


unsigned char font[] = {0x00, 0x04,.........,}

처음부터 8개까지 위의 그림의 '소'에 해당하는 CG RAM adress의 도트이다.


LCD에 찍힐 때는      

   *

 *  *

   *

   *

*****

이런식으로 화면에 나온다. 





LCD_Cmd_WRITE함수는 예전에 만들어 놓았던 명령을 내리는 함수이다. 인자인 0x40은  Set CGram adress이다. 즉, CGram adress로 인자로 받아서, CGRAM에

지정할 문자를 받을 준비를 한다(???)





for(i=0; i<64;i=i+1)

{

LCD_Data_WRITE(font[i]);

}

이 부분을 반복문을 돌려서 font[]배열에 있는 헥사값들을 LCD_Data_WRITE()에 넣어서, 데이터를 입력한다.LCD_Data_WRITE는 실제 데이터를 입력하는 함수이다.



아래는 main()함수와 DD RAM adress



커서의 위치를 설정하는 부분이다. 커서를 해당주소에 위치시키는 것.

여기서 0x80은 첫 번째행 맨 앞에 주소.

이 주소에 커서를 위치시켜서 사용하는 문자를 쓴다. 커서를 변경하고 싶으면,

위의 그림에 보이는 DD RAM ADRESS표를 참고하여 해당 주소만큼 0x80에

더하여 커서를 위치시키면 된다. 








'임베디드 > Arm2567SAM' 카테고리의 다른 글

4월 17일 LCD문자입력함수 만들기  (0) 2013.05.30
4월 16일 CMD_Write와 DATA_write함수 만들기  (0) 2013.05.28
5월 23일 ULTRA 2.  (0) 2013.05.24
5월 23일 ultra1(진행중)  (0) 2013.05.23
5월 22일 소스 define방법  (0) 2013.05.22
posted by 송시혁
2013. 5. 24. 09:09 임베디드/Arm2567SAM

다음은 타이머 카운트로 거리를 측정한다.

그러기 위해서 기존에 있던 타이머 소스를들고 와서 약간 수정한 형태.







분주비 오차가 제일 적은 353;




나머지는 그대로 놔두다가 아래그림에서 보이는 utimer_init()함수 

제일 끝에 2줄을 주목한다. 



이 빨간색 부분은 타이머가 시작하는 부분이다. 그러나 INIT함수에서는 저두줄을 지워야 한다.







posted by 송시혁
2013. 5. 23. 22:53 임베디드/Arm2567SAM

1. 트리거 펄스 함수.

    실제로 타이밍도를 보면 펄스를 보내주는 부분.

즉, 우리가 손댈수 있는 부분은 펄스(신호를 보내는 부분)

은 펄스밖에 없다. 그러나 과정은 복잡하다!!!!

서론은 끝내고 본론으로 들어가겠다.



트리거 init함수에서

1. 핀 출력 레지스터 활성화

2.핀 활성화

3.핀 출력 데이터를 클리어(GND, 혹은 레지스터에 혹시 모를 쓰레기값 지움)



트리거 pulse 함수(상승엣지 부분)

처음에 low상태 (AT91C_BASE_PIOA->PIO_SODR =1<<TRG_PIN)였다가

 set output data register를 사용한다.

AT91C_BASE_PIOA->PIO_CODR=1<<TRG_PIN;


밑에 for문은 low상태에 신호가 지연됨으로서 상승되는 클럭을

의미한다. 정확히는 클럭의 길이라고 보면 된다. 보통 2~4클럭.


그리고 일정시간이 흐르면 다시 핀14번을 꺼서 유지상태로 만듬.

AT91C_BASE_PIOA->PIO_CODR =1<<TRG_PIN;(핀을 0v상태로 만든다,

즉, 더 이상 상승하지 않는다는 의미로 상승 종료)







ECHO_INIT()함수- 외부 인터럽터(AIC), 거리측정

그대로 끌고와서 이름만 변형한 것.





단, 주의점은 풀업저항 부분은 주석처리 한다. 




핸들러 함수. 인터럽트를 발생시키는 부분이다. 인터럽트를 발생시켜서

하강하는 엣지를 찾기위하여 인터럽트를 사용한다.






AT91C_BASE_PIOA->PIO_ISR;= 인터럽트 상태레지스터를 읽는다.






++uIctic;= 타이머가 거리를 측정하는 부분이다. 1클럭당 1cm씩 세고

계속해서 증가시킨다. 결국, 증가하면서 거리를 측정하고있다.











  









'임베디드 > Arm2567SAM' 카테고리의 다른 글

5월 27일 LCD에 한글이름 찍기  (0) 2013.05.27
5월 23일 ULTRA 2.  (0) 2013.05.24
5월 22일 소스 define방법  (0) 2013.05.22
5월 21일 ultra(수정중)  (0) 2013.05.21
5월 21일 AIc 2.(수정중)  (0) 2013.05.21
posted by 송시혁
2013. 5. 22. 13:55 임베디드/Arm2567SAM

1.AT91SAM7S.h파일에 가서 제일 위페이지에서

ctr+F키를 누른다. 거기서 base를 검색한다.





해당하는 레지스터의 이름에 해당하는 부분을 더블클릭하여 소스에 복사시킨다.





AT91C_BASE_PMC를 복사한뒤 AT91C_BASE_PMC->PMC_PCER(해당레지스터 이름)을 입력한다.



2. 레지스터를 더블클릭한다.여기서는 PMC_PCER을 더블클릭

   찾고자 하는 레지스터명을 더블 클릭, 아래에 #define문이 보인다.

   



여기서 #define PMC_PCER(AT91_CAS(AT91_REG *)0xFFFFFC10)을 더블클릭하면,

아래그림과 같은곳으로 이동이 된다.



구조체 형식으로 되어 있다. 여기서 레지스터가 있는지 확인한다. 없으면

따로 만들어서 define 하는 수 밖에 없다.





TC0는 저번시간에 타이머 카운트를 설계시 define을 만들어 사용했던 것이다.

그래서 아무리 찾아봐도 같은 이름을 찾을 수 없다. 그러나 그렇다고 해서 

헤더파일에 define되어 있는지 아닌지 확정할 수 없는 상태이다.

그래서 최대한 잘 찾아야 한다. 










여기서 TC0는 장치 번호라는 것을 알 수 있다.

따라서 헤더파일에도 또한 장치를 define한 부분을 찾아야 한다.

아래그림은 TC0가 define되어있는것을 헤더파일에서 찾아낸 그림.





그래서 저것을 복사하면된다.






'임베디드 > Arm2567SAM' 카테고리의 다른 글

5월 23일 ULTRA 2.  (0) 2013.05.24
5월 23일 ultra1(진행중)  (0) 2013.05.23
5월 21일 ultra(수정중)  (0) 2013.05.21
5월 21일 AIc 2.(수정중)  (0) 2013.05.21
5월 20일 AIC  (0) 2013.05.20
posted by 송시혁
2013. 5. 21. 16:48 임베디드/Arm2567SAM




'임베디드 > Arm2567SAM' 카테고리의 다른 글

5월 23일 ultra1(진행중)  (0) 2013.05.23
5월 22일 소스 define방법  (0) 2013.05.22
5월 21일 AIc 2.(수정중)  (0) 2013.05.21
5월 20일 AIC  (0) 2013.05.20
5월 16일 타이머 정리2(예정)  (0) 2013.05.16
posted by 송시혁
prev 1 2 3 next