ATMEGA128 LED 제어

2023. 5. 31. 23:42Embedded/마이크로프로세서

728x90
  • LED 1
#include <avr/io.h>
#include <util/delay.h>
#define F_CPU 16000000UL

void Initial_set(void)
{
   DDRA = 0xFF;
   PORTA = 0xFE;
   DDRC = DDRC & ~(1<<DDC0);
   PORTC = PORTC | 1<<PC0;
}

int main(void)
{
   unsigned char led = 0xFE;
   Initial_set();
      
   while(1){
      if(!(PINC & 1<<PC0)){
         do{
            PORTA = led;
            _delay_ms(500);
            led <<= 1;
            led |= 0x01;
         }while(led != 0x7f);

         do{
            PORTA = led;
            _delay_ms(500);
            led >>=1;
            led |= 0x80;
         }while(led != 0xfe);
      }
      else PORTA = 0xfe;  
   }
   return 0;
}

 

  • 코드설명
 DDRA = 0xFF;	//포트A의 DDA7~DDA0까지 전부 입력을 받는다 
 PORTA = 0xFE;	//포트A의 DDA0번만을 출력으로 받는다​

포트A의 입출력 상태를 나타낸다.

 DDRC = DDRC & ~(1<<DDC0);	//포트C의 DDC0번만 입력으로 받는다.
 PORTC = PORTC | 1<<PC0;	//PC0번에만 1을 받는다.

 

bit 7 6 5 4 3 2 1 0
DDRC DDR7 DDR6 DDR5 DDR4 DDR3 DDR2 DDR1 DDR0
X X X X X X X 0
PORTC PC7 PC6 PC5 PC4 PC3 PC2 PC1 PC0
X X X X X X X 1

DDRC에서 DDRC & ~(1<<DDC0)코드는 0xFE와는 다른 코드이다. 이 코드는 DDC7~DDC1까지는 1로 받는게 아니라 포트자체를 쓰지 않는다는 의미 이다. PORTC | 1<<PC0 이 코드 또한 PC7~PC1까지는 포트자체를 쓰지 않겠다는 의미이다.

 

do{
            PORTA = led;
            _delay_ms(500);
            led <<= 1;
            led |= 0x01;
         }while(led != 0x7f);
bit 7 6 5 4 3 2 1 0
led 1 1 1 1 1 1 1 0
led<<=1 1 1 1 1 1 1 0 0
led|=0x01 1 1 1 1 1 1 0 1
led 1 1 1 1 1 1 0 1

Led값이 1111 1110에서 1111 1101로 자리이동 한다. 이때 do while반복문 안에 있으므로 led값이 1111 1110, 1111 1101, 1111 1011...0111 1111이 될 때까지 반복한다.

 

do{
            PORTA = led;
            _delay_ms(500);
            led >>=1;
            led |= 0x80;
         }while(led != 0xfe);
bit 7 6 5 4 3 2 1 0
led 0 1 1 1 1 1 1 1
led>>=1 0 0 1 1 1 1 1 1
led|=0x80 1 0 1 1 1 1 1 1
led 1 0 1 1 1 1 1 1

이 반복문도 0111 1111, 1011 1111, 1101 1111...의 순으로 진행하며 1111 1110이 될 때까지 반복한다.

 

if(!(PINC & 1<<PC0))

이때 1<<PC0을 받아 0000 0001이 되고

PINC & 1<<PC0으로 0000 000PINC0이 된다.

!(PINC & 1<<PC0)이기 때문에 PINC00이되면 1이 되고 1이 되면 0이 된다. 그러므로 PINC0의 기능을 하는 스위치1번을 올리면 IF문을 반복하고 내리면 반복을 멈춘다.

 


 

  • LED 2
#include <avr/io.h>
#include <util/delay.h> 
#define F_CPU 16000000UL
unsigned char led[8]={0xFE,0xFD, 0xFB, 0xF7,0xEF, 0xDF, 0xBF, 0x7F};

void Initial_set(void)
{
    DDRA = 0xFF ;
    PORTA = 0xFE ;
    DDRC = DDRC & ~(1<<DDC0 | 1<<DDC1 | 1<<DDC2 | 1<<DDC3);
    PORTC = PORTC | 1<<PC0 | 1<<PC1 | 1<<PC2 | 1<<PC3;
}

void Left_4led(void)
{ PORTA = ~(led[0] & led[1] & led[2] & led[3]); }

void Right_4led(void)
{ PORTA = (led[0] & led[1] & led[2] & led[3]); }

void Odd_led(void)
{ PORTA = (led[1] & led[3] & led[5] &led[7]); }

void Even_led(void)
{ PORTA = ~(led[1] & led[3] & led[5] &led[7]); }

void Shift_left(void){
   for(int i = 0; i<8; i++){
      if(i==8){
         i = 0;      
      }
   PORTA = led[i];
   _delay_ms(1000);
   }
}

void Shift_right(void){
   for(int i=7; i>0; i--){
      if(i==-1){
         i=7;
      }
   PORTA = led[i];
   _delay_ms(1000);
   }
}

void Off_led(void){
   PORTA = ~(led[0] & led[1] & led[2] & led[3] & led[4] & led[5] & led[6] &led[7]); }

int main(void)
{
    unsigned char keyin; // 입력데이터를 받아 저장할 메모리 확보
    Initial_set();
    while(1){
    keyin= PINC & 0x0F; // 상위 4비트는 0으로 mask, 하위 4비트를 조사
    switch(keyin){
       case 0x0E :
          Left_4led();
         break;
      case 0x0D:
         Right_4led();
         break;
      case 0x0B:
	 Odd_led();
         break;
      case 0x07:
         Even_led();
         break;
       case 0x0C:
         Shift_left();
         break;
       case 0x09:
         Shift_right();
         break;
      case 0x03:
         Off_led();
         break;
      default : 
         PORT
         A = 0xFE;
         break; } 
 } 
 return 0;
}

 

  • 코드설명
 DDRC = DDRC & ~(1<<DDC0 | 1<<DDC1 | 1<<DDC2 | 1<<DDC3);
 PORTC = PORTC | 1<<PC0 | 1<<PC1 | 1<<PC2 | 1<<PC3;
Bit 7 6 5 4 3 2 1 0
DDRC DDA7 DDA7 DDA7 DDA7 DDA7 DDA7 DDA7 DDA7
X X X X 0 0 0 0
PORTC PA7 PA7 PA7 PA7 PA7 PA7 PA7 PA7
X X X X 1 1 1 1

DDRC에선 0~3번까지만 입력을 받고 PORTC0~3번까지만 출력을 하게 한다. 이번실험에선 스위치가 PINC에 해당하므로 1,2,3,4의 스위치를 입출력 받게 설정한다.

 

void Left_4led(void)
{ PORTA = ~(led[0] & led[1] & led[2] & led[3]); }

void Right_4led(void)
{ PORTA = (led[0] & led[1] & led[2] & led[3]); }

void Odd_led(void)
{ PORTA = (led[1] & led[3] & led[5] &led[7]); }

void Even_led(void)
{ PORTA = ~(led[1] & led[3] & led[5] &led[7]); }
bit 7 6 5 4 3 2 1 0
Left_4led 0 0 0 0 1 1 1 1
Right_4led 1 1 1 1 0 0 0 0
Odd_led 0 1 0 1 0 1 0 1
Even_led 1 0 1 0 1 0 1 0

각 함수들은 위의 표와 같이 Led가 출력된다.

 

void Shift_left(void){
   for(int i = 0; i<8; i++){
      if(i==8){
         i = 0; }
   PORTA = led[i];
   _delay_ms(1000); }
}

이 함수는 for문을 이용하여 초기상태에서 좌측으로 자리이동을 나타내는 함수이다.

 

void Shift_right(void){
   for(int i=7; i>0; i--){
      if(i==-1){
         i=7;
      }
   PORTA = led[i];
   _delay_ms(1000);
   }
}

이 함수는 for문을 이용하여 초기상태에서 우측으로 자리이동을 나타내는 함수이다.

 

void Off_led(void){
   PORTA = ~(led[0] & led[1] & led[2] & led[3] & led[4] & led[5] & led[6] &led[7]); }

Led의 출력을 나타내는 PORTAled[0]~led[7]의 코드를 이용해 모든 Led를 점등하게 한 후 NOT기호를 사용하여 모든 Led를 소등하게 한다.

switch(keyin){
       case 0x0E :
          Left_4led();
         break;
      case 0x0D:
         Right_4led();
         break;
      case 0x0B:
	 Odd_led();
         break;
      case 0x07:
         Even_led();
         break;
       case 0x0C:
         Shift_left();
         break;
       case 0x09:
         Shift_right();
         break;
      case 0x03:
         Off_led();
         break;
      default : 
         PORT
         A = 0xFE;
         break; }

이 코드는 switch문을 사용하여 스위치를 올렸을시 사용되게 하는 코드를 설정한 코드이다. 만약 스위치가 모두 내려갔으면 default문을 통해 Led가 초기상태인 0xFE상태로 바뀌게 해준다.

 

'Embedded > 마이크로프로세서' 카테고리의 다른 글

ATMEGA128 포토인터럽트 제어 실험  (0) 2023.06.01
ATMEGA128 Roullette 모형 제어  (0) 2023.06.01
ATMEGA128 Motor 제어 실험  (0) 2023.06.01
ATMEGA128 RELAY 제어 실험  (0) 2023.06.01
ATMEGA128 FND제어 실험  (0) 2023.06.01