-
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
-
FOC (Force Output Compare) : Normal과 CTC모드에서 이 비트가 1로 셋팅 되는 순간 OC0에 출력값이 나오게 하는 것으로 그다지 많이 사용 되지 않는다.
-
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 모드 : 디지털적으로 아날로그를 제어하는 방법 (전구의 밝기, 모터의 속도..)
-
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로 설정
-
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 -