본문 바로가기

AVR

타이머 / 카운터 0 일반모드(실습)

이제 계속적으로 LCD를 사용하면서 다른 기능들을
연습 하기 위해 계속 LCD 소스를 넣어 보았다. ㅋ
이 실습을 하니깐.. 시간이 0.1초 정도 밖에 안되어..
눈으로 보기에는 오버플로우 인터럽트가 계속 걸려 있는 것처럼
보였다.


#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


/***** 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);
}


/***** 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);
}

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

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

unsigned char cnt = 0, led = 0xFF;


SIGNAL(SIG_OVERFLOW0)                   // 타이머/카운터0 오버플로우 함수
{                                                       // MAIN에서 인터럽트 발생 주기를 1/16us * 1024 분주 * (256-0) = 16,384us로
       unsigned char i;                          // 하여 16,384us 때 오버플로우가 생겨 이 함수로 들어옴
        TCNT0 = 0x00;
        cnt++;
        if(cnt >= 10)
        {
            cnt = 0;
            led = (led << 2);
            if(led == 0x00)
           {
               led = 0xFF;
            }
            PORTD = led;
   
           for(i = 0; i < 3; i++)
          {
               Command(0x80); // 첫줄 사용
               String("  OVERFLOW0  ");
               Delay_ms(500);
               Command(0xC0); // 두번째 줄 사용
               String("   2009/07/24   ");
               Delay_ms(500);
           }
       }
}

int main(void)
{
 TIMSK = 0x01; // 오버프로우 인터럽트 인에이블 비트
 TCCR0 = 0x07; // 1024분주
 TCNT0 = 0x00; // 타이머 카운터를 0으로 함
 SREG |= 0x80; // 인터럽트 사용
 DDRD = 0xFF;
 PORTD = 0xFF;
 Init();
 while(1)
 {
  Command(0x80); // 첫줄 사용
     String("  PURESTARMAN  ");
     Delay_ms(1000);
  Command(0xC0); // 두번째 줄 사용
     String("   2009/07/15   ");
     Delay_ms(2000);
   }
}

 

 



 

'AVR' 카테고리의 다른 글

간단한 송신 프로그램  (0) 2009.11.11
스텝모터 구동  (0) 2009.09.14
타이머 / 카운터 0 일반모드(이론)  (0) 2009.07.25
TEXT LCD 제어 실습(외부 인터럽트)  (0) 2009.07.21
TEXT LCD 제어 실습  (0) 2009.07.17