728x90

변수


전역변수 : 함수밖 선언 - Data

지역변수 : 함수내 선언 - Stack




전역 변수 사용

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

int A;

int main()
{
    printf("%d\n",A);
    return 0;
}



Output:

1
0


전역변수는 0으로 초기화(bss)

지역변수는 stack의 쓰레기 값이 표시됨






두번째 예제

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

int A;

int main()
{
    int A = 100;
    printf("%d\n",A);
    return 0;
}

printf가 속한 곳이 우선, 없으면 전역변수의 값이 표시

Output:

1
100



전역변수 사용은 아래와 같은 이유 때문에 최소화하는 것이 좋다.

  • 실행파일 용량 증가

  • 변수 관리의 어려움 (값을 어떤걸 대입하게 될지 모르기에 헷갈릴 수가 있다)

  • 전역변수는 프로그램 종료시까지 메모리를 차지한다.


Code(text)

 .EXE


Compile

Time

Data

BSS

Heap

 실행시

Run

Time

Stack


unsigned int가 메모리에 최적화된 가장 빠른 변수이다.




전역, 지역변수의 주소를 출력하고 할당된 메모리 공간 나누기
#include <stdio.h>

int D;
int E=98;
int F;
int G;
int H;

int main()
{
	int A=0;
	int B;
	int C=100;

	printf("--------stack--------------------\n");
	printf("A의 주소	: %p\n", &A);
	printf("B의 주소	: %p\n", &B);
	printf("C의 주소	: %p\n", &C);
	printf("---------data---------------------\n");
	printf("G의 주소	: %p\n", &G);
	printf("E의 주소	: %p\n", &E); 
	printf("---------bss-----------------------\n");
	printf("H의 주소	: %p\n", &H);
	printf("F의 주소	: %p\n", &F);
	printf("D의 주소	: %p\n", &D); 
	printf("---------code-----------------------\n");
	printf("printf의 주소   : %p\n", printf); 
	printf("main의 주소     : %p\n", main);

	return 0;
}



Output:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
--------stack--------------------
A의 주소	: 0xfffcd00c
B의 주소	: 0xfffcd008
C의 주소	: 0xfffcd004
---------data---------------------
G의 주소	: 0x8049950
E의 주소	: 0x8049934
---------bss-----------------------
H의 주소	: 0x8049948
F의 주소	: 0x804994c
D의 주소	: 0x8049944
---------code-----------------------
printf의 주소   : 0x80483c0
main의 주소     : 0x80484a4




Atmega 카운터 인터럽트실습


14일에 배운 것을 응용하여 Switch를 통한 인터럽트를 추가해준다. 


main.h / main.c

#ifndef __MAIN_H__ 
#define __MAIN_H__

void Init(void);
void Port_Init(void);
void INT_Init(void);

#define PINA (*((volatile unsigned char *)0x20))
#define DDRA (*((volatile unsigned char *)0x21))
#define PORTA (*((volatile unsigned char *)0x22))

#define EICRA (*((volatile unsigned char *)0x69))
#define EICRB (*((volatile unsigned char *)0x6A))
#define EIMSK (*((volatile unsigned char *)0x3D))

#define SREG (*((volatile unsigned char *)0x5F))

#define INT7 7
#define INT6 6
#define INT5 5
#define INT4 4
#define INT3 3
#define INT2 2
#define INT1 1
#define INT0 0

#define ISC7 6
#define ISC6 4
#define ISC5 2
#define ISC4 0
#define ISC3 6
#define ISC2 4
#define ISC1 2
#define ISC0 0

#define sei()   __asm__ __volatile__ ("sei" ::) //sei(); 어셈블리어로 7번비트만 1로 만듬
#define sleep() __asm__ __volatile__ ( "sleep" "\n\t" :: )

void __vector_1(void) __attribute__((signal, used, externally_visible)); //신호사용 외부호출 INT0.
void __vector_2(void) __attribute__((signal, used, externally_visible)); // INT1.

#endif //__MAIN_H__

#include "main.h" volatile unsigned int uiState; int main(void) { volatile unsigned int uiCnt; volatile unsigned int uiloop; uiCnt = 0; Init(); uiState = 1; while(1) { PORTA = ((uiCnt/10)<<4)|(uiCnt%10); for(uiloop = 0; uiloop < 45000; ++uiloop); for(uiloop = 0; uiloop < 50000; ++uiloop); if(1==uiState) { ++uiCnt; } if(uiCnt > 99) //세그먼트에서 앞자리가 9를 넘어가면 지워지는 이유는 uiCnt가 100을 넘어갔을 때이다. 그래서 if문으로 재정의. { uiCnt = 0; } } return 0; } void Init(void) { INT_Init(); Port_Init(); } void Port_Init(void) { DDRA = 0xff; PORTA = 0x00; } void INT_Init(void) { EICRA=(3<<ISC0)|(3<<ISC1); // INT0 0000 0011 3 (2진수 11 = rising edge) INT1도 마찬가지 EIMSK=(1<<INT0)|(1<<INT1); // INT0,1 Enable SREG=SREG|(1<<7); // sei(); 전역 인터럽트 활성화 } void __vector_1(void) { volatile unsigned int uiCnt; uiState = 1; } void __vector_2(void) { volatile unsigned int uiCnt; uiState = 0; }



결과.

두 스위치를 통해 카운터를 시작/정지할 수 있게 된다.


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

20160317-펌웨어(타이머 카운터)  (0) 2016.03.17
20160316-LCD출력  (0) 2016.03.17
20160314-펌웨어 분석(외부 인터럽트)  (0) 2016.03.15
20160311-펌웨어분석 (FND, LED Test)  (0) 2016.03.12
20160310-CPU 모듈2  (0) 2016.03.10

+ Recent posts