관리 메뉴

거북이처럼 천천히

Separate Compilation 본문

Embedded Programming (AVR)/Atmega 128A (실습)

Separate Compilation

유로 청년 2024. 5. 25. 15:15

1. Separate compilation이란?

- 분할 컴파일은 프로그램 설계하는 과정에서 유사한 함수 및 기능끼리 묶어 별개의 파일로 만들어 개발하는 방법을 의미

 

2. Separate Compilation의 장점

- 코드의 가독성이 좋음.

- 유지 보수 측면에서 효율적

- 수정 작업이 이루어진 코드에 대해서만 컴파일하기 때문에 불필요한 시간 없어짐

 

- 아래 예시를 통해 Separate Complication의 장점을 살펴보자.

  ※ 아래 코드들은 다음과 같은 기능을 수행한다.

  ※ 0번 비트 -> 3번 비트로 Left Shift하고, 7번 비트 -> 4번 비트로 Right Shift 하는 동시에 반전 출력

  ※ 3번 비트 -> 0번 비트로 Right Shift하는 동시에 반전 출력하고, 4번 비트 -> 7번 비트로 Left Shift

 

3. 예시 1. Main 함수안에 모든 기능을 구현한 경우

#define F_CPU 16000000UL
#include <avr/io.h>
#include <util/delay.h>

// Time Constant
#define TIME 1000

int main(void) {
   // PORTD의 모든 핀을 출력으로 설정
   // PORTD = 1111 1111
   DDRD = 0xff;
   
   while(1) {
      // 0핀 -> 3핀으로 Left shift
      // 7핀 -> 4핀으로 Right shift하는데, 반전 출력
      for(int i=0; i<4; i++) {
         PORTD = (~(PORTD1<<(3-i))<<4)|(PORTD1<<i);
         _delay_ms(TIME);
      }
      
      // 3핀 -> 0핀으로 Right Shift하는데, 반전 출력
      // 4핀 -> 7핀으로 Left Shift
      for(int i=0; i<4; i++) {
         PORTD = ((PORTD1<<i)<<4) | (~(PORTD1<<(3-i)) & (0x0f));
         _delay_ms(TIME);
      }
   }
}

 

※ 소스 코드가 짧아 보이지만, 가독성과 유지 보수가 어렵다.

소스 코드의 일부분을 수정하더라도 전체를 Build해야 한다.


 

4. 예시 2. 비슷한 기능끼리 묶어서 함수로 구현한 경우

#define F_CPU 16000000UL
#include <avr/io.h>
#include <util/delay.h>

// Time Constant
#define TIME 1000

// Function prototype.
void initDDR();
void move_inwards();
void move_outwards();
void control_LED();
void GPIO_Output(uint8_t data);

// Main method.
int main(void) {
   initDDR();
   
   while(1) {
      control_LED();
   }
}

// Control LED.
void control_LED() {
   move_inwards();
   move_outwards();
}

// Initialization for Data Direction Register
void initDDR() {
   // PORTD의 8핀 모두를 출력으로 사용 설정
   // PORTD = 1111 1111
   DDRD = 0xff;
}

// Function that the LED bits to move inwards.
void move_inwards() {
   for(int i=0; i<4; i++) {
      // 왜 해당 data의 값이 아래와 같이 나왔는지 궁금하면 비트 단위로 그려보며 생각하기.
      uint8_t data = (~(PORTD1<<(3-i))<<4)|(PORTD1<<i);
      
      // 데이터 값 출력
      GPIO_Output(data);
      _delay_ms(TIME);
   }
}

// Function that the LED bits to move outward.
void move_outwards() {
   for(int i=0; i<4; i++) {
      uint8_t data = ((PORTD1<<i)<<4) | (~(PORTD1<<(3-i)) & (0x0f));
      
      // 데이터 값 출력
      GPIO_Output(data);
      _delay_ms(TIME);
   }
}

// GPIO Output
void GPIO_Output(uint8_t data) {
   PORTD = data;
}

 

※ main 함수에 모든 것을 구현한 경우보다 가독성과 유지 보수 측면에서 상대적으로 효율적이다.

※ 그러나 여전히 코드 일부분을 수정하면 전체를 Build 해야한다.

 


5. 에시 3. 비슷한 기능끼리 묶어 파일 단위로 분할하여 구현한 경우

- main.c 

- controlLED.c (LED를 컨트롤을 위한 함수들을 묶은 파일)

- commonHeader.h (기본적으로 제공하는 라이브러리 파일을 include한 명령어를 묶은 파일)

- PersonalHeader.h (함수 원형 선언, 상수 선언 등을 묶은 파일)

 

// Include Common header file
#include "PersonalHeader.h" 

// Main method.
int main(void) {
   initDDR();
   
   while(1) {
      control_LED();
   }
}

 

#include "PersonalHeader.h"

// Control LED.
void control_LED() {
   move_inwards();
   move_outwards();
}

// Initialization for Data Direction Register
void initDDR() {
   // PORTD의 8핀 모두를 출력으로 사용 설정
   // PORTD = 1111 1111
   DDRD = 0xff;
}

// Function that the LED bits to move inwards.
void move_inwards() {
   for(int i=0; i<4; i++) {
      // 왜 해당 data의 값이 아래와 같이 나왔는지 궁금하면 비트 단위로 그려보며 생각하기.
      uint8_t data = (~(PORTD1<<(3-i))<<4)|(PORTD1<<i);
      
      // 데이터 값 출력
      GPIO_Output(data);
      _delay_ms(TIME);
   }
}

// Function that the LED bits to move outward.
void move_outwards() {
   for(int i=0; i<4; i++) {
      uint8_t data = ((PORTD1<<i)<<4) | (~(PORTD1<<(3-i)) & (0x0f));
      
      // 데이터 값 출력
      GPIO_Output(data);
      _delay_ms(TIME);
   }
}

// GPIO Output
void GPIO_Output(uint8_t data) {
   PORTD = data;
}

 

#ifndef COMMONHEADER_H_
#define COMMONHEADER_H_

// Preprocessor
#define F_CPU 16000000UL
#include <avr/io.h>
#include <util/delay.h>

#endif

 

#ifndef PERSONALHEADER_H_
#define PERSONALHEADER_H_

// Time Constant
#define TIME 1000

// include CommonHeader file.
#include "commonHeader.h"

// Function prototype.
void initDDR();
void move_inwards();
void move_outwards();
void control_LED();
void GPIO_Output(uint8_t data);

#endif /* PERSONALHEADER_H_ */

구현 영상 

 

 

'Embedded Programming (AVR) > Atmega 128A (실습)' 카테고리의 다른 글

궁금증 정리 노트 - Atmega128A  (0) 2024.05.25
Pointer  (0) 2024.05.25
Atmega128a의 변수 정리  (0) 2024.05.25
GPIO - LED control (2)  (0) 2024.05.25
GPIO - LED control (1)  (0) 2024.05.25