ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • ATmega8535 - 타이머,카운터 제어 시계 설계
    Programming/Embeded 2009. 7. 9. 23:48

    Code Vison AVR C

    ATmega 8535

     

    타이머/카운터

    표시된 포트들을 사용 한다.

     

     

    타이머 카운터 0

    타이머/카운터 0 는 범용이며 싱글채널 8비트 타이머/카운터 모듈이다.

    타이머/카운터 0은 overflow 인터럽트(타이머/외부 입력 카운터), 비교일치 인터럽트, PWM으로 사용된다.

    ATmega8535에는 타이머/카운터 0에는 출력을 위한 OC0(PB3)핀과 카운터 입력을 위한 T0(PB0)핀이 있다.

    이것이 타이머로 동작할 경우는 시스템 클럭 소스로 사용하며, 시스템 클록은 프리스케일러에 의해 1, 18, 64,256, 1024 중의 하나로 분주하여 클록 소스로 공급된다. 클록 입력을 차단하면 타이머/카운터 기능이 정지된다.

    TCNT0 레지스터에 동작 모드에 따라 클록에서 입력되는 값이 저장되며 0xFF에서 0x00되는 순간 overflow 인터럽트가 발생한다. 또 출력 비교 일치 레지스터 OCR0와 비교하여 그 값이 일치하면 출력비교일치 인터럽트가 발생한다.

     

     

     

    TCCR0 레지스터 (Timer/Counter 0 Control Register)

    타이머 제어 레지스터로써 다름과 같은 구조로 되어 있고 역시 8비트로 셋팅한다.

    FOC0

    WGM0

    COM1

    COM0

    WGM1

    CS2

    CS1

    CS0

    1. FOC (Force Output Compare) : Normal과 CTC모드에서 이 비트가 1로 셋팅 되는 순간 OC0에 출력값이 나오게 하는 것으로 그다지 많이 사용 되지 않는다.
    2. WGM0, WGM1 (Waveform Generation Mode): 타이머의 동작 모드를 결정하는 비트로써 4가지 모드를 선택 한다.

    WGM0

    WGM1

    MODE

    0

    0

    Normal

    1

    0

    PWM

    0

    1

    CTC

    1

    1

    Fast PWM

    Normal 모드 : 0에서 255까지 도달하게 되면 인터럽트를 발생하고 다시 0으로 돌아가는 모드로 초기 값을 조절 하여 주기를 더 짧게 만들 수 있다. 업 카운터로만 동작하며, 카운트가 동작 중 클리어 되지 않으며, 항상 0x00에서 0xFF로 반복 한다.

    CTC 모드 : 0에서 프로그래머가 셋팅해 둔 값에 도달하면 인터럽트를 발행 시키고 다시 0으로 돌아가는 모드, 0x00 -> OCR0의 값으로 카운터를 반복 수행 한다.

    PWM 모드 : 디지털적으로 아날로그를 제어하는 방법 (전구의 밝기, 모터의 속도..)

     

    1. COM1, COM0 (Compare Match Output Mode) : OC0 핀의 기능을 정한다.

    COM1

    COM0

    MODE

    0

    0

    범용 I/O 포트로 동작(OC0 핀 차단)

    0

    1

    OC0 핀 출력 토글

    1

    0

    OC0 핀 출력을 0으로 클리어

    1

    1

    OC0 핀 출력을 1로 설정

    1. CS0, CS1, CS2 (Clock Select): 클럭의 분주를 설정한다. CPU에 사용한 크리스탈의 주파수를 얼마만큼 분주 할 것인지 설정한다.

    CS2

    CS1

    CS0

    기능

    0

    0

    0

    클럭 입력 차단(타이머 사용 안함)

    0

    0

    1

    시스템클럭 / 1

    0

    1

    0

    시스템클럭 / 8

    0

    1

    1

    시스템클럭 / 64

    1

    0

    0

    시스템클럭 / 256

    1

    0

    1

    시스템클럭 / 1024

    1

    1

    0

    외부 입력 클럭 하강 엣지

    1

    1

    1

    외부 입력 클럭 상승 엣지

     

    OCR0 (Output Compare Register)레지스터

    분주된 클럭이 몇 번 발생한 후 인터럽트를 발생하게 하는지를 설정하는 레지스터

    Ex) OCR0 = 125;         // 클럭이 125번 발생하면 인터럽트를 발생한다.

    (결국 분주의 기능을 가지고 있음)

     

    TCNT0 (Timer/Counter Register)레지스터

    TCNT0 레지스터는 프로그램이 실행되는 동안 분주된 클럭의 주기로 0에서 부터 몇 번째 주기가 발행 했는지 나타낸다. 이 레지스터는 쓸 수도 있고 읽을 수도 있다. 값을 쓰면 주기를 더 빠르게 할 수 있다. 레지스터의 값은 인터럽트가 걸리면 자동으로 0으로 클리어 되고 다시 분주된 주기마다 한 개씩 값이 늘어난다.

     

    TIMSK (Timer/Counter Interrupt Mask Register)레지스터

     

    TOIE1

    OCIE1A

    OCIE1B

    OCIE2

    TICE1

    TOIE2

    TOIE0

    OCIE0

     

    TOIE0(Timer0 Overflow Interrupt Enable) 비트를 1로 셋팅하고 시스템 인터럽트를 인에이블 하면 Normal모드의 타이머 인터럽트가 작동.

    OCIE0(Timer0 Output Compare Match Interrupt Enable) 비트를 1로 셋팅하고 시스템 인터럽트를 인에이블 하면 CTC모드의 타이머 인터럽트가 작동.

     

    사용 함수

    sei( ) : 인터럽트를 인에이블 시키는 함수

    sli( ) : sei의 반대 되는 것으로 시스템 인터럽트를 디스에이블 시킨다.

    SIGNAL( ) : 인터럽트가 발생 했을 때 이 함수로 점프한다.

    SIG_OUTPUT_COMPARE0 : 내부, 외부 관계 없이 인터럽트가 발생하면 해당 번호에 따른 번지로 점프하게 된다.

     

     

    타이머/카운트를 이용한 LCD 시계를 만들어 보자

    /*********************************************

    This program was produced by Talsu

    Date : 2008-02-22

    *********************************************/

     

    #include <mega8535.h>

    #include <stdio.h>

    #asm

    .equ __lcd_port=0x15 ;PORTC

    #endasm

    #include <lcd.h>

    unsigned char key;

    unsigned char sec_cnt;

    unsigned char sec0;

    unsigned char min0;

    unsigned char hour0;

    unsigned char bang_cnt;

    unsigned char bang;

    unsigned char backslash[8]={ //CG RAM에 입력할 글자 패턴을 저장하는 함수

    0b00001110,

    0b00010001,

    0b00011011,

    0b00010001,

    0b00010101,

    0b00010101,

    0b00001110,

    0b00000000};

     

    unsigned char ms1;

     

    void define_char(unsigned char *pc,unsigned char char_code)

    /*CG RAM에 글파 패턴을 입력하는 함수*/

    {

    unsigned char i,a;

    a=(char_code<<3) | 0x40;

    for (i=0; i<8; i++) lcd_write_byte(a++, *pc++);

    }

    interrupt [TIM0_OVF] void timer0_ovf_isr(void)        //카운터 인터럽트에 반응 하는 함수

    {

    sec_cnt++;

    if(sec_cnt == 125){         //0.1초를 맞추기위한 분주

    ms1++;

    bang_cnt++;

    sec_cnt = 0;

    PORTA = ~PORTA;

    }

    TCNT0 = 256 - 25;

    }

     

    void main(void)

    {

    char lcd_text[16];

    char lcd_text2[1];

     

    PORTA=0x55;

    DDRA=0xFF;

     

    DDRD=0x00;

    PORTD=0xFF;

     

    // Timer/Counter 0 initialization

    // Clock source: System Clock

    // Clock value: 31.250 kHz

    // Mode: Normal top=FFh

    // OC0 output: Disconnected

    TCCR0=0x04;

    TCNT0=256-250;

    OCR0=0x00;

     

    // Timer(s)/Counter(s) Interrupt(s) initialization

    TIMSK=0x01;

     

    // Analog Comparator initialization

    // Analog Comparator: Off

    // Analog Comparator Input Capture by Timer/Counter 1: Off

    ACSR=0x80;

    SFIOR=0x00;

     

    // LCD module initialization

    lcd_init(16);

     

    #asm("sei")

    define_char(backslash,0); //CG RAM에 원하는 패턴을 입력

    lcd_clear();

     

    while (1)

    {

        key = PIND & 0xFF;

        if(key == 0b11111110){

            hour0++;

            }

    if (ms1 == 10){         //0.1초가 10번 카운트되면

    sec0++;     //1초 증가

    ms1 = 0;        //0으로 초기화

    }

    if (sec0 == 60){

    min0++;

    sec0 = 0;

    }

    if (min0 == 60){

    hour0++;

    min0 = 0;

    }

    if (hour0 ==24){

    hour0 = 0;

    }

    if (bang_cnt == 4){

    bang_cnt = 0;

    }

    switch (bang_cnt){

    case 0: bang = '|'; break;

    case 1: bang = '/'; break;

    case 2: bang = '-'; break;

    case 3: bang = 0xA4; break;    //저장된 패턴을 불러옴

    }

     

        lcd_gotoxy(0,0);

        sprintf(lcd_text, " %2dh %2dm %2d.%is ",hour0,min0,sec0,ms1);    //시간을 출력

        lcd_puts(lcd_text);

        sprintf(lcd_text2,"%c",bang);

        lcd_gotoxy(0,1);

        lcd_puts(lcd_text2);

        lcd_putchar(0);

    lcd_puts(lcd_text2);

    lcd_putsf("...nclab..");

    lcd_puts(lcd_text2);

    lcd_putchar(0);

    lcd_puts(lcd_text2);

    };

    }



    from : http://talsu.net

    'Programming > Embeded' 카테고리의 다른 글

    DK-128  (0) 2012.12.26
    8255A - Programmable Peripheral Interface  (0) 2009.07.12
    ATmega8535 Datasheet  (0) 2009.07.10
    ATmega8535 - 시리얼통신 (UART)  (0) 2009.07.09
    ATmega8535 - FND & LCD 제어  (0) 2009.07.09
Designed by Tistory.