Language/AVR

ATmega 128 : LED Bar 구조체 동작 구현

짱도르딘 2024. 5. 28. 20:14
728x90

이번에는 구조체를 활용하여 LED Bar를 동작시키는 코드를 구현해봤다.

 

이번에도 포인터 동작때와 같이 헤더파일, 소스파일, 메인파일을 구분하여 진행하였다.

 

 

가장 먼저 led 소스파일부터 확인해보겠다.

 

#include "led.h"

void ledInit(LED_t *led) //led는 LED 타입
{
	// 포트에 해당하는 핀을 출력으로 설정함
	*(led->port - 1) |= (1 << led->pinNumber);
	// *(led->port - 1) = *(led->port - 1) | (1 << led->pinNumber);
	// DDR 레지스터는 PORT레지스터보다 1 낮게 위치하고 있으므로
	// *(led->port - 1) 를 이용하여 PORT에서 DDR로 접근한다. (데이터시트 참조)
	// |= (1 << led->pinNumber) or 연산을 통하여 led->pinNumber로 지정된 포트에 출력으로 설정한다. (pinNumber로 지정된 포트를 1로 설정)
}

void ledOn(LED_t *led)
{
	*(led->port) |= (1 << led->pinNumber);
	// *(led->port) = *(led->port) | (1 << led->pinNumber);
}

void ledOff(LED_t *led)
{
	*(led->port) &= ~(1 << led->pinNumber);
	// *(led->port) = *(led->port) | &= ~(1 << led->pinNumber)
}

 

ATmega128a Datasheet

 

Datasheet를 확인해보면 PORT 레지스터 밑에 DDR 레지스터가 있는것으로 확인되어 (led -> port -1)을 통하여 DDR로 접근을 진행한다.

 

ledOn 함수에서는 OR 연산자를 활용하여 동작을 원하는 포트에 출력을하여 동작을 구현시킨다.

 

ledOff 함수에서는 ledOn과는 달리 AND 연산과 NOT 연산을 진행하여 led 소등 동작을 구현한다.

 

 

다음은 led 헤더파일이다.

 

#ifndef LED_H_
#define LED_H_

#include <avr/io.h>

#define LED_DDR DDRC	
#define LED_PORT PORTC

// LED 구조체 정의
typedef struct
{
	volatile uint8_t *port; // LED가 연결된 포트, volatile은 컴파일러에게 최적화해서 하지말고, 제대로 연산해라 라는 뜻
	uint8_t pinNumber;	    // LED가 연결된 핀 번호
}LED_t;					    // 구조체를 LED_t로 정의

void ledInit(LED_t *led);
void ledOn(LED_t *led);
void ledOff(LED_t *led);

#endif /* LED_H_ */

 

led 헤더파일에서는 DDRC와 PORTC, 구조체 그리고 위에 소스파일에서 구현한 ledInit, ledOn, ledOff 함수를 넣어 진행하였다.

 

다음은 메인함수이다.

 

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

#include "led.h" // led 헤더파일 불러오기

int main(void)
{
	// LED 구조체 인스턴스 생성 및 초기화
	LED_t led;
	led.port = &PORTC;
	led.pinNumber = 3;
	
	ledInit(&led);
	
    while (1) 
    {
		ledOn(&led);
		_delay_ms(400);
		ledOff(&led);
		_delay_ms(400);
    }
}

 

pinNumber를 3으로 선언하여 4번째 LED가 깜빡이는 것을 확인할 수 있다.

 

 

 

728x90