Harman 세미콘 아카데미/Atmega128a

2024.6.4 이전(1) [ATmega 128a]② - 데이터 핀, LED_shift, LED_pointer

U_Pong 2024. 6. 18. 17:30

경기 인력 개발원에서 주최하는 Harman 세미콘 아카데미 - 반도체 설계 수업은 2024.5.29일에 수업이 시작되었다.

하지만 바로 그 다음주인 2024.6.3일에 이 수업에 대해 알게되어 본격적으로 수업을 듣게 된 것은 2024.6.4이기 때문에 그 이전의 수업 내용은 책을 보면서 블로그에 적게 되었다.


< ATmega 128a >

ATmega 128a는 64개의 핀으로 구성된 마이크로컨트롤러이다.

전원, 크리스털 등을 위한 11개의 핀을 제외하고 53개의 핀(비트)로 데이터를 교환하는 것이 가능하다.

8개의 입출력 핀을 묶어 PORT라는 이름으로 관리한다.

핀 53개는 A~G까지 7개의 포트로 나뉜다.(한 부분당 8개씩, 마지막 G포트에는 핀 5개)

ATmega 128에는 256개(2의 8승)의 레지스터를 정의할 수 있으며,

32개의 범용 레지스터, 105개의 입출력 레지스터가 정의되어 있다.


포트를 통해 디지털 데이터를 출력하기 위해 사용하는 레지스터는 PORTx(x= A,...G) 이다.

PORTA~PORTF는 위 사진의 A 자리만 바뀌고 나머지는 동일하다.

 

PORTG만 유일하게 5개의 핀만 사용 가능하다, 상위 3비트는 사용할 수 없다

 

*PORT, PIN, DDR

PORT: 데이터 핀으로 데이터를 출력하기 위해 사용된다.

PIN: 입력이나 출력으로 사용할 수 있지만, 입출력을 동시에 사용할 수는 없다.

DDR: 데이터 핀을 입력, 출력으로 사용하기 위해 DDRx를 통해 데이터의 입출력 방향을 결정한다

DDRA~DDRF는 위 사진의 A 자리만 바뀌고 나머지는 동일하다
DDRG만 유일하게 5개의 핀만 사용 가능하다, 상위 3비트는 사용할 수 없다

 

 

< LED_shift >

/*
 * LED_shift.c
 */ 

#define F_CPU 16000000UL  // CPU 클럭 주파수를 16MHz로 설정
#include <avr/io.h>       // AVR 입출력 헤더 파일 포함
#include <util/delay.h>   // _delay_ms() 함수 사용을 위한 헤더 파일 포함

int main(void)
{
	DDRC = 0xff;	// C포트를 출력방향으로 설정
	
	while (1)       // while(1)이면 항상 참
	{
		//0000 0000 : PORTA 의 초기값
		//// 내가 원하는 패턴
		//0x10 << i	0x08 >> i
		//0001 1000 == 00010000 | 00001000 : i = 0
		//0010 0100 == 00100000 | 00000100 : i = 1
		//0100 0010 == 01000000 | 00000010 : i = 2
		//1000 0001 == 10000000 | 00000001 : i = 3
		//0100 0010 == 01000000 | 00000010
		//0010 0100 == 00100000 | 00000100
		//-----------------------------------------
		
		
		for (uint8_t i = 4; i < 8; i++)
		{
			PORTC = 0x01 << i | 0x80 >> i;
			_delay_ms(500);
		}
		for (uint8_t i = 6; i > 4; i--)
		{
			PORTC = 0x01 << i | 0x80 >> i;
			_delay_ms(500);
		}
	}
}

 

 

LED_shift에서는 LED 대신 아래의 사진과 같은 부품을 사용한다.

LED를 8개로 압축시켜놓은 부품으로, 이 부품을 사용하여

500ms마다 정 중앙의 두칸을 기준으로 한칸씩 이동되는 것을 실행한다.

 

위의 소스코드를 실행하면 아래와 같은 결과를 볼 수 있다.

 

 

< LED_pointer >

/*
 * led.h
 */ 

#include <avr/io.h>

#ifndef LED_H_
#define LED_H_


#define LED_DDR		DDRC	//LED 출력 방향 설정(레지스터)
#define LED_PORT	PORTC	//LED 포트 출력(레지스터)

void GPIO_Output(uint8_t data);
void ledInit(void);
void ledLeftShift(uint8_t i, uint8_t *data);



#endif /* LED_H_ */

 

/*
 * led.c
 */ 


#include "led.h"


// LED 출력 함수
void GPIO_Output(uint8_t data)	// 8비트 짜리 data를 넘겨받겠죠
{
	LED_PORT = data;	// 예를들어서 00101100 (0x2C)
	// i = 0 : 00000001
	// i = 1 : 00000010
	
	// i = 7 : 10000000
}

// LED 포트 초기화 함수
void ledInit()
{
	LED_DDR = 0xff;	// LED 포트를 출력 방향으로 잡겠다
}

// LED 이동하는 함수
void ledLeftShift(uint8_t i, uint8_t *data)
{
	*data = (1<<i);
	// i = 0 : 00000001
	// i = 1 : 00000010
	
	// i = 7 : 10000000
}

 

/*
 * LED_pointer.c
 */ 

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

#include "led.h"


int main(void)
{
	ledInit();	//DDRC = 0xff;
	uint8_t ledData = 0x01; // 0b00000001 (stack 영역)
	
	while (1)
	{
		for (uint8_t i = 0; i < 8; i++)
		{
			ledLeftShift(i, &ledData);
			GPIO_Output(ledData);
			_delay_ms(100);
		}
	}
}

 

LED_pointer는 소스코드가 총 3개가 필요하다.

 

헤더파일과 main이 아닌 또다른 c파일이 필요한데, 추가하고자 하는 프로젝트 이름에서

오른쪽클릭을 하여 Add->New Item을 클릭하면된다.

 

 

헤더파일, c파일 추가하는 법

 

이것도 마찬가지로 LED_shift에서 사용했던 부품을 가지고 결과를 확인할 수 있다.


ATmega 128a 데이터 핀, LED_shift, LED_pointer 끝!