AVR

TEXT LCD 제어 실습(외부 인터럽트)

행복하면 2009. 7. 21. 00:49

이번에는 저번시간에 연습한 TEXT LCD 제어에서 버튼을 입력 받아서
그 버튼에 해당하는 외부 인터럽트를 걸어 보았다.
이번에는 한번만에 성공을 하였다.

TEXT LCD 기본 소스에 조금만 추가를 시켰는데..
여기에서 Init() 함수의 순서를 TEXT LCD 함수 제일 밑에 두었다.
아직 선언하지도 않은 함수가 나와 경고가 떠서 조금 수정을 하였다.

참고로 외부 인터럽트 4,5,6,7은 PORTE 4,5,6,7이며 외부 인터럽트 0,1,2,3은 PORTD0,1,2,3 이다.

#include <avr/io.h>
#include <stdio.h>
#include <avr/signal.h> //외부인터럽트를 사용하기 위한 헤더 파일

/***** 포트가 바뀔 경우 여기에서 수정 ******/

//LCD의 4,5,6번의 포트
#define LCD_PORT_CONTROL PORTA
#define LCD_DDR_CONTROL DDRA

//LCD의 7~14번의 포트
#define LCD_PORT_DATA PORTB
#define LCD_DDR_DATA DDRB

// 변수 매크로
typedef unsigned char byte;

/***** Delay 함수 ******/

//delay 함수로 #include<avr/delay.h> 보다 나은것 같음
//이 소스는 윤덕용 선생님의 책을 인용한 것임

void Delay_us(int time_us)
{
 int volatile i;

 for(i=0; i<time_us; i++){ // 4 cycle +
  asm volatile("PUSH R0"); // 2 cycle +
  asm volatile("POP R0"); // 2 cycle + = 8 cycle = 1us for 8Mhz
  asm volatile("PUSH R0"); // 2 cycle +
  asm volatile("POP R0"); // 2 cycle + = 12 cycle for 11.0592MHZ
  asm volatile("PUSH R0"); // 2 cycle +
  asm volatile("POP R0"); // 2 cycle = 16 cycle = 1us for 16MHz
 }
}

void Delay_ms(int time_ms)
{
 int volatile i;

 for(i=0; i<time_ms; i++)
  Delay_us(1000);
}


/***** LCD 명령어 레지스터에 쓰는 함수 *****/

void Command(unsigned char command)
{
  LCD_PORT_CONTROL = 0x00;   // E = 0, R/W=0, Rs = 0
  LCD_PORT_DATA = command;   // 명령어 출력
  LCD_PORT_CONTROL = 0x04;   // E = 1 , R/W=0, Rs = 0(LCD 동작)
  Delay_us(1);
  LCD_PORT_CONTROL = 0x00;    // E = 0, R/W=0, Rs = 0
  Delay_us(50);
}

/***** LCD 데이터 레지스터에 쓰는 함수 *****/

void Data(unsigned char data)
{
  LCD_PORT_CONTROL = 0x01;   // E = 0, R/W=0, Rs = 1
  LCD_PORT_DATA = data;      // 데이터 내용 출력
  LCD_PORT_CONTROL = 0x05;   // E = 1, R/W=0, Rs = 1(LCD 동작)
  Delay_us(1);
  LCD_PORT_CONTROL = 0x01;   // E = 0, R/W=0, Rs = 1
  Delay_us(50);
}

/***** LCD에 글자 출력 함수 *****/

void String( unsigned char *string)
{
  while(*string != '\0')
  {
    Data(*string);
    string++;
  }
}

/***** AVR 초기화 및 LCD에 대한 초기화 *****/

void Init(void)
{
 LCD_DDR_DATA=0xff;
  LCD_DDR_CONTROL=0x07;
 Delay_ms(50);

  Command(0x38);  // function set(데이터 선을 8 bit 다 사용, 2줄표시 , 5x7 dot 사용)
  Command(0x0C); // display control(표시(display) 켬, 커서(cursor) 끔)
  Command(0x06);  // entry mode set(CGRAM이나 DDRAM을 써넣거나 읽을 때
                        // 어드레스를 1증가 시키고 커서를 우로 이동, 시프트는 안함
  Command(0x01);  // clear display
  Delay_ms(2);
}

/***** 외부인터럽트(PORTE4) 사용 함수 *****/

SIGNAL(SIG_INTERRUPT4)
{
        byte i;
       
        for(i=0; i<5; i++)
        {
             Command(0x80); // 첫줄 사용
             String("  INTERRUPT4  ");
             Command(0xC0); // 두번째 줄 사용
             String("   2009/07/20   ");
             Delay_ms(1000);
        }
}

/***** 외부인터럽트(PORTE5) 사용 함수 *****/

SIGNAL(SIG_INTERRUPT5)
{
        byte i;
       
        for(i=0; i<5; i++)
        {
             Command(0x80); // 첫줄 사용
             String("  INTERRUPT5  ");
             Command(0xC0); // 두번째 줄 사용
             String("   2009/07/20   ");
             Delay_ms(1000);
        }
}

/***** 외부인터럽트(PORTE6) 사용 함수 *****/

SIGNAL(SIG_INTERRUPT6)
{
        byte i;
       
        for(i=0; i<5; i++)
        {
             Command(0x80); // 첫줄 사용
             String("  INTERRUPT6  ");
             Command(0xC0); // 두번째 줄 사용
             String("   2009/07/20   ");
             Delay_ms(1000);
        }
}

/***** 외부인터럽트(PORTE7) 사용 함수 *****/

SIGNAL(SIG_INTERRUPT7)
{
        byte i;
       
        for(i=0; i<5; i++)
        {
             Command(0x80); // 첫줄 사용
             String("  INTERRUPT7  ");
             Command(0xC0); // 두번째 줄 사용
             String("   2009/07/20   ");
             Delay_ms(1000);
        }
}

int main(void)
{
  Init();                     


  DDRE = 0x00;
  PORTE = 0xF0;   // int4,5,6,7 pull-up
  EIMSK = 0xF0;    // 외부 인터럽트 4,5,6,7 인에이블 설정
  EICRB = 0xAA;    // 외부 인터럽트 4,5,6,7 하강에지 설정
  SREG |= 0x80;   // 전체 인터럽트 인에이블

 

  while(1)
  {
      Command(0x80); // 첫줄 사용
      String("  PURESTARMAN  ");
      Command(0xC0); // 두번째 줄 사용
      String("   2009/07/15   ");
      Delay_ms(1000);
   
  }
}