CodeVisionAVR ANSI C Language 요점 정리
 
l        CodeVisionAVR 특징
- Atmel AVR용 통합 환경 C 컴파일러.
 통합 환경 내에 여러 가지 ISP 기능 포함.
 통합 환경 내에 비동기 통신 터미널 기능 내장.
- 윈도우 95, 98, NT4.0, 2000 환경에서 동작
- 생성된 COFF파일은 AVR Studio를 사용하여 소스 레벨 디버깅 가능.
- 표준 라이브러리 외에 아래의 여러 가지 주변 소자 라이브러리 포함
       문자형 LCD 모듈
       Philips I2C 버스
       온도 센서 소자(LM75, DS1820)
       Real Time Clock 소자 지원(PCF8563,PCF8583, DS1302, DS1307)
       Dallas 1 Wire 프로토콜
       Thermometer/Thermostat (ds1621)
       SPI
       Delay 함수
       Power management
-  자동 소스 생성 기능 내장
 
l        변수 / 함수 / 레벨의 이름(Identifiers) 지정
- 알파벳 문자(A..Z, a..z)와 숫자(0…9) 그리고 underscore(_)문자 사용 가능.
- 시작은 알파벳 문자나 underscore로 사용 가능.
- 대소문자 구분 있음.
- 최대 32문자까지 사용 가능.
 
l        CodeVisionAVR의 데이터 타입
데이터 타입
크기(bit)
범 위
Bit
1
0,1
Char
8
-128 ~ 127
Unsigned char
8
0 ~ 255
Signed char
8
-127 ~ 127
Int
16
-32768 ~ 32767
Short int
16
-32767 ~ 32767
Unsigned int
16
0 ~ 65536
Signed int
16
-32767 ~ 32767
Long int
32
-2147483648 ~ 2147483647
Unsigned long int
32
0 ~ 4294967295
Signed long int
32
-2147483648 ~ 2147483647
Float
32
-0.175e-38 ~ +0.402e38
Double
32
-0.175e-38 ~ +0.402e38
 
l        주석(Comments) 처리
주석 시작           /*
주석 끝              */
:        /* 이것은 주석 입니다 */
한 줄 주석 처리: //
:        // 이것도 주석입니다.
 
l        전처리(Preprocessor)
-         <![endif]>파일 포함 처리:
#include <file name>          /* 컴파일러 설치 사용 디렉터리에서 참조 */
#include file name           /* 현재 작업 디렉터리에서 참조 */
-         <![endif]>macro define:
#define  ALFA 0xff              /* ALFA 심볼을 0xff로 동일 처리 */
                                /* 소스 문에서 ALFA를 모두 0xff로 컴파일 처리 함 */
-         <![endif]>파라미터를 가질 수 있음:
#define  SUM(a,b) a+b
int         i=SUM(2,3);          /* i=2+3;으로 치환 처리 */
 
-         매크로 파라미터에 #을 사용하면 문자열로 치환:
#define PRINT_MESSAGE(t) printf(#t)
PRINT_MESSAGE(Hello);    /* printf(Hello)와 동일 처리 */
 
-         두개의 파라미터가 ## 연산자로 하나로 합해 짐:
#define ALFA(a,b) a ## b
char      ALFA(x,y)=1;         /* char xy=1; 과 동일  처리 */
 
-         역 슬래시()를 사용하여 다음 줄까지 연장:
#define MESSAGE This is a very    
long text…
 
-         define 취소: #undef 사용
#undef   ALFA
 
-         조건부 컴파일 처리 : #ifdef, #ifndef, #else, #endif
#ifdef macro_name
             [문 1 그룹]
#else                                             /* option */
             [문 2 그룹]
#endif
설명: 만일 macro_name이 define 되어 있으면 [문 1 그룹]을 컴파일 하고, 그렇지 않으면 [문 2 그룹]을 컴파일 한다.
 
-         또 다른 조건부 컴파일 처리: #if, #elif, #else, #endif
#if expression1
             [문 1 그룹]
#elif expression2
             [문 2 그룹]
#else
             [문 3 그룹]
#endif
설명: 만일 expression1이 true이면 [문 1 그룹]을 컴파일 하고,
그렇지 않고 만일 expression2가 true이면 [문 2 그룹]을 컴파일 하고,
그 외에는 [문 3 그룹]을 컴파일 한다.
 
-         #error 문: 컴파일을 중지하고 에러 메시지를 표시.
:
#error This is an error!
 
-         #pragma 문: 컴파일러 특수 지시 문
#pragma warn-                               /* warning 디스어블 */
#pragma warn+                               /* warning 인에이블 */
#pragma opt-                                  /* 최적화 안 함 */
#pragma opt+                                  /* 최적화 함 */
#pragma savereg-                           /* 레지스터 저장 안 함 */
#pragma savereg+                           /* 레지스터 저장 함 */
#pragma library mylib.lib     /* 링크 라이브러리 지정 */
 
n        상수(Constants)
2진수 : 0b로 시작(예 0b101001)
16진수 : 0x로 시작 (예. 0xff)
8진수 : 0으로 시작 (예. 0777)
Unsigned integer 상수는 뒤에 U사용: (예, 10000U)
Long integer 상수는 뒤에 L사용: (예, 99L)
Unsigned Long integer 상수는 뒤에 UL사용: (예, 99UL)
Floating point 상수는 뒤에 F사용: (예, 1.234F)
문자 상수는 1중 따옴표로 처리: (예, a)
문자열 상수는 2중 따옴표로 처리:  (예, Hello world)
(함수의 파라미터 안에 2중 따옴표 문자열이 있으면 FLASH 메모리에 놓임.)
행렬은 최대 8차까지 가능
 
n        변수(Variables)
전역(global) 변수와 지역(local) 변수가 있음.
전역(global) 변수 : 함수 외각에 선언, 프로그램 내의 모든 함수에서 사용 가능.
지역(local) 변수 : 함수 내부에 선언, 해당 함수 내에서만 사용 가능.
초기화하지 않은 전역 변수는 프로그램 초기에 0으로 초기화 됨.
 
:
/* 전역 변수 선언 */
char a;
int b;
long c = 0x12345678;            /* 초기화 */
 
void main(void){
/* 지역 변수 */
char d;
int e;
long f=22222222;    /* 초기화 */
}
행렬 변수: 8차까지 가능, 0부터 시작, 초기화하지 않은 전역 행렬 변수 값은 0으로 초기화.
 
/* 전역 행렬 변수 */
int global_array1[32];          /* 모든 값이 0으로 초기화 */
int global_array2[]={1,2,3};
int global_array3[4]={1,2,3,4};
char global_array4[]=This is a string;
int multidim_array[2,3]={{1,2,3},{4,5,6}};
void main(void){
 
/* 지역 행렬 변수 */
int local_array[3]={11,22,33};
}
 
static 변수: 지역 변수라도 static 선언을 하면 값을 보존할 수 있다.
:
int alfa(void){
static int n=1;        /* static 변수 선언 */
return n++;
}
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을 참조 바람.
Posted by 용학도리
,