728x90


CPU 모듈


실습에 사용하는 장비 : Atmel ATmega 2560


135 instruction  - Cpu에게 내릴 수 있는 기계어 명령어 수


주파수 -> 초당 진동수, 이 주파수는 cpu에서 초당 계산 능력과도 연관된다.

 "주기(cycle)"가 1초에 몇번이냐에 따라 - Hz 등으로 표현  



전류 - 전기의 흐름

전압 - 전기의 압력


물탱크의 수압과 꼭지를 통해 흐르는 물을 생각하고 대입하면 이해하기 쉽다.


V=IR - 저항이 클수록 전류는 적게 흐름


일반적으로 한국은 AC(Alternating Current) 220v 60hz 

이는 1초동안 60번 +,- 극성이 바뀌는 것을 의미



P = VI

   = 220v * 1A

   = 220W = 0.22 KW



Atmel ATmega 2560 실습


개발 환경 구축


AVR Studio 설정




선이 연결되는 위치와 기반의 방향에 주의.

어댑터를 연결할 때는 전원을 꼭 내린채로 연결! 절대 주의!


windows 10 dll FILE

msys-1.0.zip

winavr문제해결.txt



AVR Studio 설정



Tools-Program AVR-Connect...  선택




STK500-COM3 연결

포트 연결은 시스템-장치관리자의 포트 항목에서도 확인 가능하다. 



Atmega2560을 선택한 후, Read Signature를 눌렀을 때 모두 OK!가 나오는지 확인.



Makefile 

각종 명령어가 담겨있으며 아래 항목들을 메모장으로 열어 환경에 맞게 수정해준다.


# MCU name

MCU = atmega2560  


# Processor frequency.

F_CPU = 16000000


# Target file name (without extension).

TARGET = main  // 항상 main.c를 기준으로 한다면 바꾸지 않음. main.c로 코딩하는 이유



LED제어를 위한 예제.

DDRA, PORTA, PINA 기능과 주소 부분은 Atmega25060의 datasheet 파일에서 확인 가능하다.


main.c 파일로 아래와 같이 소스를 짠다.

1
2
3
4
5
6
7
8
9
10
11
12
#define DDRA	(*((volatile unsigned char *)0x21))
#define PORTA	(*((volatile unsigned char *)0x22))
#define PINA	(*((volatile unsigned char *)0x20))

int main(void) //void 안적으면 컴파일시 warning isn't a prototype
{
	DDRA=0xFF; // 출력으로 쓴다.
	PORTA=0xFF; //모든 다리를 5v로 만듬
	
	while(1); //초기상태로 돌리지 않기위해 항상 씀. 	
return 0;
}


명령창에서 make를 입력후 엔터하면 위와 같이 파일들이 생성된다.



int main() 에서 괄호안에 void를 안 적으면 아래와 같이 Warning message가 출력




make clean은 main.c와 Makefile을 제외하고 모두 지우는 명령어



int main(void)라고 수정후 make.  Warning 뜨지 않음


컴파일이 성공적으로 되었으면 Program탭에서 Flash 항목에  HEX File을 선택후 Program을 누른다. (당연히 전원 들어온 상태에서만 쓰기가능)



LED 제어 실습

먼저 LED를 10번 GND부터 연결, 극성과 위치를 설계도를 보며 잘 확인할 것!


설계도를 볼때는 x,y축을 통해 원하는 정보의 위치를 대략적으로 찾을 수도 있다.



메인보드 뒤쪽에도 번호가 적혀있다.



LED가 극성에 맞게 모두 잘 연결되었다면 위와 같이 LED에 불빛이 들어온다.



깜박거리는 LED 만들기

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#define DDRA	(*((volatile unsigned char *)0x21))
#define PORTA	(*((volatile unsigned char *)0x22))
#define PINA	(*((volatile unsigned char *)0x20))

int main(void) //void 안적으면 컴파일시 warning isn't a prototype
{
	volatile unsigned int uiCnt;
	DDRA=0xFF; // 출력으로 쓴다.

	while(1)
	{
		for(uiCnt=0; 60000>uiCnt;++uiCnt); //숫자가 낮으면 빨리 깜박임
		PORTA=0xFF;
		for(uiCnt=0; 60000>uiCnt;++uiCnt);
		PORTA=0x00;
	}
	return 0;
}


어제 배운 volatile을 응용한 예제이다. 의도적인 지연을 통해 불빛이 들어오고 나가는 시간을 조절할 수 있다.


make clean후 다시 make.

아까전 Program탭에서 Flash 항목에서 다시 Program을 누른다.


실습 결과 LED가 일정한 간격으로 깜박거리는 것을 볼 수 있다.




'Study > Embedded' 카테고리의 다른 글

20160316-LCD출력  (0) 2016.03.17
20160315-펌웨어 분석 및 학습  (0) 2016.03.16
20160314-펌웨어 분석(외부 인터럽트)  (0) 2016.03.15
20160311-펌웨어분석 (FND, LED Test)  (0) 2016.03.12
20160310-CPU 모듈2  (0) 2016.03.10
728x90

구구단 3단 소스 (http://codepad.org/ZT1RrUn5)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#include <stdio.h>

int main()
{
	int iCnt;
	iCnt=1;  // 아래 소스에서 for 함수로 정리 ⓐiCnt=1;
	
	while(10>iCnt) // for 함수 정리ⓑ(10>iCnt);  
	{
		printf("3 x %d = %d\n", iCnt, 3*iCnt);
		iCnt=iCnt+1;  // for 함수 정리ⓒiCnt=iCnt+1
	}
	return 0;
}
 


iCnt=iCnt+1


iCnt=++iCnt;


iCnt=iCnt++


을 위의 소스에 대입해도 모두 같은 결과 값을 얻을 수 있지만 첫번째가 권장된다.


처리속도는 동일하기에 소스를 짤 때 인간(프로그래머)이 보기에 헷갈리지 않게, 

보기 편하게 소스를 짜는 것이 좋다. 




이제 위의 소스를 for 함수를 사용해 정리해보자 (http://codepad.org/NhNOP5Qt)

1
2
3
4
5
6
7
8
9
10
11
12
#include <stdio.h>

int main()
{
	int iCnt;
		
	for(iCnt=1;10>iCnt;iCnt=iCnt+1)
	{
		printf("3 x %d = %d\n", iCnt, 3*iCnt);
	}
	return 0;
}



for (); 




for ()

{

}




for () {}


모두 같은 값을 얻을 수 있다.




두 소스 모두 output이 동일하다.


Output:

1
2
3
4
5
6
7
8
9
3 x 1 = 3
3 x 2 = 6
3 x 3 = 9
3 x 4 = 12
3 x 5 = 15
3 x 6 = 18
3 x 7 = 21
3 x 8 = 24
3 x 9 = 27




volatile 변수


volatile 휘발성의


1
2
3
4
5
6
7
8
9
10
11
12
#include <stdio.h>
int main()
{
 volatile int iCnt;  // volatile = 휘발성의
 for(;;) // = while(1)
 {
   for(iCnt=0;100000000>iCnt;iCnt=iCnt+1)
  { }
  printf("test\n");
 }
 return 0;
}



바로 위의 소스에서 volatile 변수를 쓰지 않는다면 CPU의 register내에서 모두 연산하고 Memory에 값을 저장하는 내부 최적화를 진행한다.


컴파일러가 자체적으로 메모리 접근을 최소화 시키는 것이다.


volatile은 이런 최적화를 하지않게 선언해서, CPU가 "매 값마다" 참/거짓을 판별, 연산하고 

메모리에 저장하고 가져오는 과정을 반복하게 한다.


명령창에서 실행해보면 volatile 변수를 쓴 것과 쓰지않은 것의 차이를 눈으로 확인할 수 있다.





UNION


여러 종류의 변수들을 같은 메모리 공간에 묶는다.


예제 소스 (http://codepad.org/vSaMCGCW)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#include <stdio.h>

struct smart
{
    int A;
    short B;
    int C;
    char D;
};

int main()
{ 
    printf("Size of Smart: %d\n", sizeof(struct smart));
    
    return 0;
}


Output:

1
Size of Smart: 16




smart구조체를 UNION으로 수정 (http://codepad.org/rDFsMFkY

#include <stdio.h>

union smart 
//struct smart
{
    int A;
    short B;
    int C;
    char D;
};

int main()
{
    union smart obj;
    obj.A=0x12345678;
    obj.B=0x12345678;
    obj.C=0x12345678;
    obj.D=0x12345678;
 
  //printf("Size of Smart: %d\n", sizeof(struct smart));
    printf("Size of Smart: %d\n", sizeof(union smart));

    printf("%x\n", obj.A); 
    printf("%x\n", obj.B); 
    printf("%x\n", obj.C); 
    printf("%x\n", obj.D); 

    return 0;
}



Output:

1
2
3
4
5
Size of Smart: 4
12345678
5678
12345678
78


output 첫번째 줄을 보면 알 수 있듯이, size가 16에서 4로 바뀌었다.

smart 구조체를 union으로 바꿔주면 모두 4byte 안에 들어가게 된다. 

(int A; short B; int C; char D;)                         


각 데이터의 크기에 따라 각각 다른 값이 출력되게 되며, 다음과 같이 출력된다.


Little Endian

78 

 56

 34

 12


obj.A=12345678   // int A

obj.B=5678        // short B

obj.C=12345678  // int C

obj.D=78           // char D




함수 포인터를 사용하는 이유


①프로그램 코드의 간결


②중복 코드를 줄이기 위해서


③상황에 따라 해당되는 함수를 호출할 수 있음




type알아내기


type을 알아야 함수 포인터를 만들 수 있다.

아래와 같이 따라하면 원형에서 쉽게 type을 알아낼 수 있다.


1. void smart();   원형

2.        (*)

3. void (*) (); // void (*) ()가 type



int printf(const char *, ...);  // 원형

int (*)  (const char *, ...);  // Type



함수 포인터 예제 소스 (http://codepad.org/YiQTHzi9)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#include <stdio.h>
void smart1()
{
 printf("1번함수\n");
}
void smart2()
{
 printf("2번함수\n");
}
int main()
{
 void (*test)( );
 test=smart1;
 test( );
 test=smart2;
 test( );
 return 0;
}


Output:

1
2
1번함수
2번함수


type 이름; 


1. void (*test) ();

2. test=smart1; 

3. test();




반도체 (Semi Conductor)


반/도체

Semi/Conductor


도체

전기 또는 열이 잘 통하는 물체


부도체

전기 또는 열에 대한 저항이 매우 커서 전기나 열을 잘 전달하지 못하는 물체


반도체

극성에 따라 전기가 흐르거나 흐르지 않는다.



마이크로 컨트롤러 제품군 중의 하나인 "AVR"


AVR 개발환경, Intel과 AVR의 교차개발 환경 구축을 위해 둘 사이에 WIN AVR이라는 컴파일러를 사용한다. 이를 Cross Compiler라고 한다.

윈도우에 visual studio가 있다면 avr은 avr studio가 있다.


아키텍처의 종류

RISC 

CISC  


장단점이 각각 있지만, 서로 단점을 보완하며 닮아가고 있다.




'Study > C' 카테고리의 다른 글

2016-04-06-업무일지_포인터 및 함수  (0) 2016.04.06
20160405_포인터와 배열  (0) 2016.04.05
20160401_전역변수와 포인터  (0) 2016.04.04
20160329_C기초, 디버깅  (0) 2016.03.29
20160307_업무일지_파일 입출력  (0) 2016.03.07
728x90

- 파일 열기 


파일을 액세스하려면 먼저 대상 파일을 열어야(Open) 한다. 파일을 오픈한다는 것은 파일 입출력을 하기 위한 준비를 한다는 뜻이다. 

* 여기서 엑세스(Access)는 말 그대로 파일에 접근하는 것을 뜻한다.



스트림 입출력을 위해서는 파일의 데이터를 잠시 저장하는 내부 버퍼가 필요하며 파일의 현재 위치(FP)를 초기화해야 하는데 이런 준비를 하는 과정이 오픈이다. 

* Stream - 길이를 측정할 수 없는 특정한 data가 왔다갔다하는 것을 말하며, 이를 스트림 입출력이라고 한다. 

스트리밍 서비스의 음악, 동영상 감상 등이 이를 이용한 것이다. 받는 data의 양은 상황과 환경에 따라 유동적이다.


* 내부 버퍼 - 파일의 데이터를 잠시 임시로 저장하는 메모리 공간을 말한다.

모든 변수도 버퍼에 저장된다 볼 수 있다.


* 현재위치(File Pointer)  

                                   파일 (FILE)


탐색한다(SEEK) 

                         △ 여기서 파일을 탐색한 특정 지점을 FP라고 할 수 있다.




파일을 오픈할 때는 다음 함수를 사용한다. 

FILE *fopen(const char *filename, const char *mode);


먼저 인자의 갯수가 일치하는지 확인하고 인자의 Type이 서로 맞는지 확인한 다음, 최종적으로 반환값 일치여부를 확인한다.


  1.  #include <stdio.h>  
  2.   
  3. void smart(int Z); // int Z에서 type name Z는 컴파일에서 크게 중요하지 않음, 하지만 구분을 위해 의미있는 이름을 쓰기도 한다.  
  4.   
  5. int main()  
  6. {  
  7.     //FILE *fp;  
  8.     FILE *fp=fopen("A.txt""w");   
  9.     fprintf(fp, "파일입출력");  
  10.     //smart(printf);    
  11.     printf("파일입출력");  
  12.     fclose(fp);  // 파일을 닫음
  13.     return 0;  
  14. }  
  15. void smart(int A)  
  16. {  
  17. }  
다음의 예제 소스를 보자. 

파일경로에서 \\를 2개 쓰는 이유는 만약 \ 하나를 쓴다면 컴파일러에서 이를 개행(new line \n)으로 인식하고 컴파일하기 때문이다.

  1.  #include <stdio.h>  
  2.   
  3.   
  4. int main()  
  5. {  
  6.     FILE *f;  
  7.     f=fopen("c:\\영화\\코미디\\영구와땡칠이.avi","rb");  
  8.     if (f==NULL) {  
  9.                 printf("얼씨구. 파일이 안 보이네요\n");  
  10.              }  
  11.   
  12.     int fclose(FILE *stream);  // 사용한 stream 파일을 닫고, 버퍼를 비우게 된다.
  13.     return 0;  
  14. }  
컴파일 후 실행했을 때의 결과.

"c:\영화\코미디\" 디렉토리에 영구와땡칠이.avi 라는 파일을 읽을 수 없다면
(NULL) 을 리턴하고 ("얼씨구. 파일이 안 보이네요\n") 를 출력하게 된다.




여기서 도스 명령창을 통해 명령어와 절대 경로<->상대 경로를 배운다.

절대 경로가 변하지 않는 경로라면, 상대경로는 특정 위치를 기준으로 변화하는 경로이다. 



"c:\영화\코미디\"  디렉토리에서 cd c:\영화\ 명령어를 통해 이동한다면 

이는 절대경로를 이용한 것이다.




하지만 c:\영화\코미디\ 디렉토리에서 현재 위치를 기준으로 상위 디렉토리로 이동할 때,

cd .. 명령어를 통해 c:\영화로 이동할 수 있다. 

이는 상대경로를 이용한 것이다.



dir 명령어를 쳐보면 알 수 있지만 점 하나(.)는 은 현재 폴더 점 두개(..)는 상위 폴더를 의미한다.


도스, 윈도우즈에서는 대소문자의 구분을 하지 않으며, 여러 운영체제의 시초라고 할 수 있는 유닉스에서는 대소문자를 모두 구분한다.



개행 코드를 의미하는 CR/LF


ASCII 

 

 

 10

 CR

 Carriage Return

 18

 LF (\n)

 Line Feed


C언어에서 개행 코드를 의미하는 CR/LF 조합은 LF로 변환되어 읽혀지며 LF를 기록하면 CR/LF가 출력된다. 


CR(Carriage Return) : 커서를 맨 앞으로 이동한다. 

LF(Line Feed) : 다음 줄로 이동한다.


이런 변환을 해 주는 이유는 C 문자열 출력 함수들은 개행을 위해 확장열 LF(\n)를 사용하기 때문. 



파일의 끝을 의미하는 EOF = End Of File


Ctrl+Z(0x1A)는 EOF -1로 정의되며, 반환 파일의 끝을 표현하기 위한 상수 (-1)의 값을 지닌다.

명령어 Ctrl + Z는 ASCII Code로 0x1A이다.


안녕

하세요


-> 안 / 녕 / \n / 하 / 세 / 요 / 1A->EOF(-1)



NULL은 숫자 0을 의미

# define NULL 0

   주소  0을 리턴





실행파일을 2진파일(BIN)로 바꾸어서 열어보기


왼쪽부터 주소/ HEXA값 / ASCII 코드를 볼 수 있다. 헥사값을 바꿀시 아스키 코드도 따라서 바뀌는 것을 확인할 수 있을 것이다.




비트맵 파일(BMP)을 BIN파일로 바꾸고 열어보았을 때, HEXA값을 통해 파일의 확장자를 알 수 있다. 이를 MAGIC NUMBER라고 한다.



다음은 헥사값을 보기 위한 예제이다.


  1.  #include <stdio.h>  
  2.   
  3. void Hexaview(unsigned char *ucpData, unsigned int uiLen)  
  4. //void Hexaview(char *cpData, unsigned int uiLnt)  
  5. {  
  6.     unsigned int uiCnt;  
  7.     unsigned int ui16Cnt;     
  8.   
  9.     printf("====================Hexa Viewer============================\n");         
  10.     uiCnt=0;  
  11.     while(160>uiCnt)  
  12.     {  
  13.     printf("%p ", uiCnt);  
  14.   
  15.         ui16Cnt=0;  
  16.         while(16>ui16Cnt)  
  17.         {  
  18.             printf("%02x ", *ucpData);  // %02 -> 2자리로 출력하되 값이 없는 자리는 0으로 출력하라, %x는 16진수 출력을 의미
  19.             ui16Cnt=ui16Cnt+1;  
  20.             ucpData=ucpData+1;  
  21.         }         
  22.            
  23.         uiCnt=uiCnt+16;  
  24.         printf("\n");  
  25.     }  
  26.      printf("===========================================================\n");   
  27. }  
  28. int main()  
  29. {  
  30.     unsigned char ucBuff[ ]="1234567890ABCDEF";  // 헥사 값 16바이트. 즉, 한줄씩 저장되는 버퍼. 
  31.     //Hexaview(NULL, 0);  
  32.     Hexaview(ucBuff, 0);  
  33.     return 0;  
  34. }  

    cl hexa.c

    컴파일 후 실행 결과 


빨간선을 기준으로 왼쪽은 주소를 가리킨다. 아래로 내려오면서 16바이트씩 증가함을 볼 수 있다.

     오른쪽에 출력되는 부분은 아스키코드로 0x30은 문자 0이며, 0x31은 문자1과 같다.   (아스키 코드표 http://www.asciitable.com/)


    






'Study > C' 카테고리의 다른 글

2016-04-06-업무일지_포인터 및 함수  (0) 2016.04.06
20160405_포인터와 배열  (0) 2016.04.05
20160401_전역변수와 포인터  (0) 2016.04.04
20160329_C기초, 디버깅  (0) 2016.03.29
20160308_업무일지_그 밖의 기초 학습  (0) 2016.03.08

+ Recent posts