}
void main(void){
int i;
i = alfa(); /* return 값 = 1 */
i = alfa(); /* return 값 = 2 */
…
}
extern 선언 : 다른 파일에 선언된 변수는 extern 선언을 해야한다.
extern int xyz;
전역 변수는 SRAM의 Global Variables 영역에 저장되고, 지역 변수는 SRAM의 Data Stack 영역에 dynamic하게 할당된다.
l 외부 SRAM의 특정 번지에 전역 변수를 지정하는 방법
@ 연산자 사용하여 전역 변수를 특정 SRAM 위치에 배치할 수 있다.
int a @0x80 /* 정수 변수 a는 외부 SRAM 0x80에 할당 */
struct x {
int a;
char c;
} alfa @0x90 /* 0x90 번지에 구조체 alfa 할당 */
l 비트(bit) 변수
비트 변수는 레지스터 R2에서 R15까지 사용 가능: 최대 112 비트.
예:
bit alfa=1; /* bit0 of R2 */
bit beta; /* bit1 of R2 */
void main(void){
if(alfa) beta != beta;
…
}
비트 변수 크기 지정은 Project|Configure|C Compiler|Compilation|Bit Variable Size에서 지정할 수 있다.
가능한 작게 지정하는 것이 좋음 (전역 변수에서 많이 사용 가능)
l I/O 레지스터의 비트 단위 액세스
I/O 레지스터를 비트 단위로 액세스 할 수 있다.
예:
DDRA.0 = 1; /* Port A의 비트 0을 출력 포트로 함 */
DDRA.1 = 0; /* Port A의 비트 1을 입력 포트로 함 */
PORTA.0 = 1; /* Port A의 비트 0에 1 출력 */
If(PINA.1){ /* Port A의 비트 1를 판별하여 처리 */
/* 코드 추가 */
}
프로그램의 판독을 좋게 하려면 #define을 사용하여 의미 부여 사용.
#define alarm_input PINA.2
void main(void){
if(alarm_input)
…
}
l EEPROM 액세스
AVR 내부의 EEPROM 사용은 전역 변수 앞에 eeprom 키워드를 사용하여 가능하다.
예:
eeprom int alfa=1; /* Chip 프로그램 시에 EEPEOM에 1값 저장 */
eeprom char beta;
eeprom long array1[5];
eeprom char string[]=”Hello”; /* Chip 프로그램 시에 EEPEOM에 문자열 저장 */
void main(void){
int i;
int eeprom *ptr_to_eeprom; / EEPROM 포인터 */
…
alfa = 0x55; /* EEPROM에 0x55 값 직접 쓰기 */
ptr_to_eeprom=&alfa;
ptr_to_eeprom=0x55; / 포인터 사용하여 간접적으로 쓰기 */
i=alfa; /* EEPROM에서 직접적으로 값 읽기 */
i=*ptr_to_eeprom; /* EEPROM에서 간접적으로 값 읽기 */
}
EEPROM의 포인터는 항상 16비트를 사용함.
l 인터럽트 사용 하기
interrupt 키워드를 사용.
예: 여기서 벡터 번호는 AT90S8515에 대한 것 임.
interrupt [2] void external int0(void){ /* 외부 인터럽트 */
/* 여기에 처리 코드를 넣는다 */
}
interrupt [8] void timer0 overflow(void){ /* 타이머0 Overflow 인터럽트 */
/* 여기에 처리 코드를 넣는다 */
}
인터럽트 벡터 번호는 1부터 시작.
인터럽트 처리 시작 부분에서 자동적으로 레지스터를 스택에 저장하고 인터럽트 종료 시 다시 스택에서 레지스터로 회복해 놓는다.
자동적으로 저장하는 레지스터는 R0, R1, R22 ~ R31, SREG이다.
만일 레지스터를 대피하는 인터럽트 처리 시간을 조금이라도 단축하고자 하는 경우 #pragma savereg 지시자를 사용한다.
예:
#pragma savereg- /* 레지스터 저장 기능 OFF */
interrupt [1] void my_irq(void){
/* 사용하는 레지스터 만 저장 예: R30, R31, SREG 만 사용하는 경우 */
#asm
push r30
push r31
in r30, SREG
push r30
#endasm
/* 여기에 C 코드를 놓음 */
/* 레지스터 SREG, R31, R30 회복 */
#asm
pop r30
out SREG,r30
pop r31
pop r30
#endasm
}
#pragma savereg+ /* 레지스터 저장 기능 on */
l 어셈블리 언어 첨가
#asm 과 #endasm 사용
예:
void delay(unsigned char i){
while(i--){
#asm
nop
nop
#endasm
};
}
다음과 같이 한 줄로 표현 할 수도 있다.
#asm(“sei”) /* 인터럽트 인에이블 */
어셈블리 루틴에서 R0, R1, R22 ~ R31은 자유롭게 사용할 수 있다. 단 인터럽트 루틴 안에서 사용 시에는 스택에 저장 및 회복을 해야 한다.
l 딜레이(delay) 함수 사용
CodeVisionAVR에서는 일정 시간 동안 지연하는 2개의 딜레이 함수를 제공한다.
void delay_us(unsigned int n); /* micro(u) sec 단위 지연 함수 */
void delay_ms(unsigned int n); /* milli(m) sec 단위 지연 함수 */
예:
delay_us(100); /* 100 usec 지연 */
delay_ms(123); /* 123 msec 지연 */
딜레이 함수를 사용하기 전에 delay.h 헤더 파일을 포함해야 되고, 정확한 시간을 위해서는 Project|Configure|C Compiler 메뉴의 AVR chip 클럭 주파수가 정확히 설정되어야 한다.
지연 동안 인터럽트가 처리될 수 있고 인터럽트가 처리되면 지연 시간이 늘어 날 수 있다.좀더 정확한 시간을 원하면 지연 시간동안 인터럽트를 금지할 필요가 있다.
예:
…
#asm (“cli”) /* 인터럽트 디스어블 */
delay_us(100); /* 100 usec 지연 */
#asm(“sei”) /* 인터럽트 인에이블 */
…
l 표준 함수 및 응용 함수 사용
CodeVionAVR C 컴파일러에서는 거의 모든 ANSI 표준 함수를 제공하고 있으며, 기타 LCD, 온도 센서, 시계 소자 등 여러 가지 라이브러리 함수를 제공하고 있는데 이에 대한 자세한 내용은 “CodeVisionAVR User Manual”을 참조 바람.
'AVR & ATmega' 카테고리의 다른 글
Keil MDK, IAR Workbench 에서 H-JTAG을 이용한 다운로드 방법 (0) | 2012.03.21 |
---|---|
< ATMEGA128 교육용 Board > (0) | 2011.05.02 |
CodeVisionAVR ANSI C Language 요점 정리(1) (0) | 2010.04.19 |
Step Motor ( DC12v 용 JSM-24F, 제일엔지니어링) 구동 Program (0) | 2007.11.08 |
Motion Controller(Atmega128) 기본 Program (0) | 2007.11.04 |