[Embedded Software] 경희대 임베디드 소프트웨어 과제1 - LED

경희대학교 컴퓨터공학과 조진성 교수님의 ‘임베디드 소프트웨어’ 강의의 과제입니다.


개발 환경




실습 1


1.1 LED 모두 켜기/끄기

#define F_CPU 16000000UL

#include <avr/io.h>
#include <util/delay.h>

int main() {
	// LED 8개가 A포트에 연결되어 있다.
	// 따라서 A포트의 DDR을 모두 사용으로 선언한다.
	DDRA = 0xFF;
	
	while(1) {
		// LED는 Output으로 사용되기 때문에 PORT를 사용한다.
		PORTA= 0xFF;
		_delay_ms(1000);
		PORTA= 0x00;
		_delay_ms(1000);
	}
	
}


1.2 첫번째(2, 3, …, 8번째) LED만 켜기/끄기

#define F_CPU 16000000UL

#include <avr/io.h>
#include <util/delay.h>

int main() {
	// unsigned로 선언한 이유는 singed bit(부호 비트)를 제거하여 사용하기 위함이다.
	// 이렇게 선언함으로써 음수를 사용할 수는 없지만,
	// 저장 가능한 양수의 범위가 두배로 늘어난다.
	// 지금처럼 음수가 나오지 않을 경우에 사용하면 좋다.
	unsigned char value = 1;
	DDRA = 0xFF;
	while(1) {
		PORTA = value;
		_delay_ms(10000);
		
		// LED의 배열이 2비트 단위로 나열되어 있기 때문에 2를 곱했다.
		value *= 2;
	}
}


1.3 LED 하나씩 건너서 켜기/끄기

#define F_CPU 16000000UL

#include <avr/io.h>
#include <util/delay.h>

int main() {
	DDRA = 0xFF;

	while(1) {
		PORTA = 0xAA;
		_delay_ms(10000);
		PORTA = 0x55;
		_delay_ms(10000);
	}
}


1.4 LED 2개씩 짝지어 켜기/끄기

#define F_CPU 16000000UL

#include <avr/io.h>
#include <util/delay.h>

int main() {
	DDRA = 0xFF;
	// 끝의 2개 비트의 LED를 킨다.
	PORTA = 0x03;
	_delay_ms(10000);
	while(1) {
		// 한 칸씩 left shift 시켜준다.
		// A <<= 1 라는 코드는
		// A = A << 1 과 같다.
		PORTA <<= 1;
		_delay_ms(10000);
	}
}


1.5 양쪽 끝 한개만 LED 켜기/끄기

#define F_CPU 16000000UL

#include <avr/io.h>
#include <util/delay.h>

int main() {
	DDRA = 0xFF;
	PORTA = 0x81;
}


실습 2


2.1 2진 카운터 표현하기 (0~255, up)

#define F_CPU 16000000UL

#include <avr/io.h>
#include <util/delay.h>

int main() {
	int i;
	
	DDRA = 0xFF;
	
	while(1) {
		PORTA = 0x00;
		for(i = 0; i < 0xFF; i++) {
			PORTA += 0x01;
			_delay_ms(10000);
		}
	}
}


2.2 링 카운터 표현하기(1개, 오른쪽으로 계속 이동)

#define F_CPU 16000000UL

#include <avr/io.h>
#include <util/delay.h>

int main() {
	// 오른쪽으로 이동하기 위해 MSB(Most Significant Bit) LED를 키는 것으로 초기화한다.
	unsigned char value = 128;
	DDRA = 0xFF;
	while(1) {
		PORTA = value;
		_delay_ms(500);
		
		// 한 칸씩 right shift 한다.
		value >>= 1;
		
		// LSB까지 이동을 하였으면 다시 MSB로 초기화하여 무한 루프를 돌게 한다.
		if(value == 0) {
			value = 128;
		}
	}
}


2.3 좌우로 왔다갔다 표현하기(1개씩)

#define F_CPU 16000000UL

#include <avr/io.h>
#include <util/delay.h>

#define LEFT 0
#define RIGHT 1

int main() {
	// LSB에서 MSB로 left shift 하는 것으로 초기화한다.
	unsigned char value = 1;
	int direction = LEFT;

	DDRA = 0xFF;
	value = 128;
	while(1) {
		// left shift 하는 도중 MSB까지 도달하였을 경우
		// right shift로 변경한다.
		// value 값이 64인 이유는 오른쪽으로 한 비트 가기 위함이다.
		if(direction == LEFT && value == 128) {
			value = 64;
			direction = RIGHT;
		}
		
		// left shift 를 하고 있지만 아직 MSB에 도달하지 못한 경우
		else if(direction == LEFT && value != 128){
			value <<= 1;
		}
		
		// right shift 하는 도중 LSB까지 도달하였을 경우
		// left shift로 변경한다.
		// value 값이 2인 이유는 왼쪽으로 한 비트 가기 위함이다.
		else if(direction == RIGHT && value == 1) {
			value == 2;
			direction = LEFT;
		}
		
		// 나머지 경우
		// right shift 를 하고 있지만 아직 LSB에 도달하지 못한 경우
		else {
			value >>= 1;
		}
		PORTA = value;
		_delay_ms(500);
	}
}


2.4 스피커 볼륨 표현하기

#define F_CPU 16000000UL

#include <avr/io.h>
#include <util/delay.h>

#define INCREASE 1
#define DECREASE 0

int main() {
	// 볼륨 스펙트럼이 증가하는 것처럼 보이기 위해,
	// LSB에서 MSB로 left shift 하는 것으로 초기화 한다.
	unsigned char value = 1;
	int direction = INCREASE;

	DDRA = 0xFF;
	while(1) {
		PORTA = value;
		_delay_ms(500);

		// left shift 하는 경우
		if(direction == INCREASE) {
			// MSB까지 도달한 경우
			if(value == 255) {
				direction = DECREASE;
				value = 127;
			}
			
			// 아직 MSB까지 도달을 못한 경우
			// LED를 누적해서 키기 위해 2의 배수의 +1 로 계산한다.
			else {
				value = value * 2 + 1;
			}
		}
		
		// right shift 하는 경우
		else {
			// LSB까지 도달한 경우
			if(value == 0) {
				direction = INCREASE;
				value = 1;
			}
			
			// 아직 LSB까지 도달을 못한 경우
			else {
				value = value / 2;
			}
		}
	}
}


2.5 X-mas 트리(Random) 표현하기

#define F_CPU 16000000UL

#include <avr/io.h>
#include <util/delay.h>

#define F_CPU 160000000UL

int main() {
	unsigned int a=17, b=49, c=103;
	unsigned int value;
	DDRA = 0xff;

	while(1) {
		value = (a++) * (b++) + (c++);
		PORTA = value;
		_delay_ms(1000);
	}
}


실습 응용


문제: LED의 왼쪽에서부터 오른쪽까지를 ‘도레미파솔라시도’의 8음계라고 가정하고, 간단한 동요를 LED로 표현하는 프로그램을 작성하라.

노래: 작은별

#define F_CPU 16000000UL

#include <avr/io.h>
#include <util/delay.h>

int main() {
	// '작은별' 의 노트를 배열 형태로 미리 작성했다.
	// '작은별' 은 총 42개의 음으로 이루어져 있으며, 각 음의 길이는 일정하나
	// 7번째의 음마다 나머지 음 보다 음의 길이가 두 배 이상 길어진다. 
	unsigned int song[ ] = {0x80, 0x80, 0x08, 0x08, 0x04, 0x04, 0x08,
							0x10, 0x10, 0x20, 0x20, 0x40, 0x40, 0x80,
							0x08, 0x08, 0x10, 0x10, 0x20, 0x20, 0x40,
							0x08, 0x08, 0x10, 0x10, 0x20, 0x20, 0x40,
							0x80, 0x80, 0x08, 0x08, 0x04, 0x04, 0x08,
							0x10, 0x10, 0x20, 0x20, 0x40, 0x40, 0x80};
	unsigned int i;
	
	DDRA = 0xff;
	for(i = 0; i < 42; i++) {
		// 7번째 음마다 음의 길이를 길게 하기 위한 조건문
		if((i % 7) == 6) {
			PORTA = song[i];
			_delay_ms(300);
		}

		PORTA = song[i];
		_delay_ms(500);
		PORTA = 0x00;
		_delay_ms(500);
	}
}