본문 바로가기
# Semiconductor/- Semicon Academy

[Harman 세미콘 아카데미] 28일차 - ATmega128 과제(UART와 LED활용)

by Graffitio 2023. 7. 27.
[Harman 세미콘 아카데미] 28일차 - ATmega128 과제(UART와 LED활용)
728x90
반응형
[UART + LED]

 

과제

 

UART를 활용하여 입력된 신호에 따라서 LED bar를 작동시켜라

- R 입력 시, 오른쪽 방향으로 LED bar On(순차적으로)

- L 입력 시, 왼쪽 방향으로 LED bar On(순차적으로)

- B 입력 시, Blink(점멸)

 

 

Code

 

<Header File>

// LED_BAR.h //

#ifndef LED_BAR_H_
#define LED_BAR_H_

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

#define LED_BAR_PORT	PORTA // LED_BAR를 PORTA에 연결
#define LED_BAR_DDR		DDRA  // 입/출력 방향
#define LED_COUNT		8     // LED_BAR는 총 8칸

typedef struct _led
{
	volatile uint8_t *port; // 컴파일러 마음대로 해석하지 말라는 의미
	uint8_t pin;
}LED; // LED라는 이름을 가진 구조체 생성

extern LED leds[LED_COUNT]; // leds 배열이 정의된 것이 아니라, 다른 소스 파일에서 정의된 leds 배열을 참조하게 된다.

void LED_Init(); // LED_BAR 초기화를 위한 함수
void LED_BAR_Init(); // LED_BAR 초기화
void LED_On(LED *led); // LED On을 위한 함수
void LED_Off(LED *led); // LED Off를 위한 함수
void LED_Left_Shift(LED *leds); // LED 좌시프트
void LED_Right_Shift(LED *leds); // LED 우시프트
void LED_Blink(uint8_t *LED_Data); // LED Blink
void LED_Single_On(); // LED Lamp On


#endif /* LED_BAR_H_ */

 

// UART.h //

ifndef UART_H_
#define UART_H_

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


void UART_Init();
void UART_Transmit(char data);
unsigned UART_Receive();


#endif /* UART_H_ */

 

<Source File>

// LED_BAR.c //

#include "LED_BAR.h"

LED leds[LED_COUNT] = {
	{&PORTA, 0}, // (주소값, 핀번호)
	{&PORTA, 1},
	{&PORTA, 2},
	{&PORTA, 3},
	{&PORTA, 4},
	{&PORTA, 5},
	{&PORTA, 6},
	{&PORTA, 7},
};


void LED_Init(LED *led)
{
	*(led->port - 1) |= (1<< led->pin);
}


void LED_BAR_Init()
{
	LED_BAR_DDR = 0xff; // 출력 모드 설정
	LED_BAR_PORT = 0x00; // 꺼진 상태로 출발
	
	for (int i = 0 ; i < LED_COUNT ; i++)
	{
		LED_Init(&leds[i]);
	}
}


void LED_On(LED *led)
{
	*(led->port) |= (1<<led->pin);
}

void LED_Off(LED *led)
{
	*(led->port) &= ~(1<<led->pin);
}


void LED_Left_Shift(LED *leds)
{
	for (int i = 0 ; i < LED_COUNT ; i++)
	{
		LED_On(&leds[i]);
		_delay_ms(200);
	}
	for (int i = 0 ; i < LED_COUNT ; i++)
	{
		LED_Off(&leds[i]);
		_delay_ms(200);
	}
}

void LED_Right_Shift(LED *leds)
{
	for (int i = 7 ; i >= 0 ; i--)
	{
		LED_On(&leds[i]);
		_delay_ms(200);
	}
	for (int i = 7 ; i >= 0 ; i--)
	{
		LED_Off(&leds[i]);
		_delay_ms(200);
	}
}


void LED_Blink(uint8_t *LED_Data)
{
	LED_BAR_PORT = 0xaa;
	for (int i = 0 ; i < 15 ; i++)
	{
		LED_BAR_PORT = ~LED_BAR_PORT;
		_delay_ms(300);
		i++;
	}
	LED_BAR_PORT = 0x00;
}

void LED_Single_On()
{
	PORTD |= (1<<PIND2);
	_delay_ms(1000);
	PORTD &= ~(1<<PIND2);
}

 

// UART.c //

#include "UART.h"


void UART_Init()
{
	UBRR0H = 0x00;
	UBRR0L = 0xcf; // 9600bps, 2배속
	
	UCSR0A = (1<<U2X0); // 2배속 모드 set
	
	UCSR0B |= (1<<RXEN0); // 수신 가능(RX PIN 허용)
	UCSR0B |= (1<<TXEN0); // 송신 가능(TX PIN 허용)
	UCSR0B |= (1<<RXCIE0); // 수신 Interrupt Enable
}


void UART_Transmit(char data)
{
	while(!((UCSR0A) & (1<<UDRE0))); // UDR이 비어있다면, 다음 문장으로 넘어감
	UDR0 = data;
}

unsigned UART_Receive()
{
	while(!((UCSR0A) & (1<<RXC0)));
	return UDR0;
}

 

<main.c>

#include "LED_BAR.h"
#include "UART.h"

FILE OUTPUT = FDEV_SETUP_STREAM(UART_Transmit, NULL, _FDEV_SETUP_WRITE);

char rxBuff;
uint8_t rxFlag = 0;


ISR(USART0_RX_vect)
{
	rxBuff = UDR0;
	rxFlag = 1;
}


int main(void)
{
	UART_Init();
	LED_BAR_Init();
	stdout = &OUTPUT;
	sei();
	
	while (1)
	{
		if (rxFlag == 1)
		{
			rxFlag = 0;
			switch(rxBuff)
			{
				case 'R' :
				printf("%c", rxBuff);
				LED_Right_Shift(&leds);
				break;
				
				case 'L' :
				printf("%c", rxBuff);
				LED_Left_Shift(&leds);
				break;
				
				case 'B' :
				printf("%c", rxBuff);
				LED_Blink(&leds);
				break;
				
				default:
				printf("Finish");
				LED_Single_On();
				break;
			}
		}
	}
	return 0;
}

 

 

Result

 

각 버튼의 입력에 따라 LED Bar가 동작하며,

동작이 종료되면 Finish를 출력하고, LED Lamp가 On되도록 코딩

 

 

 

728x90
반응형