제목 : 타이머0 편하게 사용하기
보통 타이머0를 사용하면서 1과 2를 더 써도 문제는 없다.
그리고, 하나만 제대로 사용할 수 있게 익혀두면 굳이 다른 모드로 바꿔가며 사용할 필요도 없다.
간단하게 타이머0 에서 모드1을 사용하는 방법을 설명한다. (이걸 익숙하게 해서 타이머인터럽트는 이걸로 다 사용한다고 생각하고 쓰자. 웬지 그게 마음이 편할 듯 싶다. ^^)
1. 시간, 오실레이터 값으로 TH0, TL0 정하기
인터럽트 발생시간을 정하는 것이 필요하다.
인터럽트시간을 SEC 라고 하자. 그리고 오실레이터값을 XTAL 라고 하자. 이때 TH0과 TL0를 결합한 것을 THL이라 하자.
인터럽트 1회 시간은 1/XTAL 이고, Machane Cycle 은 12/XTAL 이 된다. (0xffff - THL) 이 인터럽트 발생까지의 횟수가 되고, 이때 걸리는 시간은 (0xffff - THL)*12/XTAL 이 된다. 이 시간을 SEC 라 했으므로,
**********************************
THL = 0xffff - SEC * XTAL / 12
**********************************
이 공식을 가지고 XTAL = 24MHz, SEC = 10ms 를 넣어보면,
THL = 0xffff - 0.01 * 24000000 / 12
THL = 65535 - 20000 = 45535 = 0xB1DF
*****************************
TH0 = 0xB1 , TL0 = 0xDF
*****************************
2. 계산된 값을 TH0, TL0 에 입력할수 있도로 한다.
#define TH0_VALUE 0xB1
#define TL0_VALUE 0xDF
3. 타이머초기화 함수
void timer0init(void) {
TMOD &= 0xF0;
TMOD |= 0x01; // timer0 16비트 설정
TH0 = TH0_VALUE; // 초기값 설정
TL0 = TL0_VALUE;
ET0=1; // timer0 가능
EA=1; // 인터럽트가능
TR0=1; // 타이머0 시작
}
4. 타이머0 인터럽트루틴
void it_timer0(void) interrupt 1 /* interrupt address is 0x000b */
{
TH0 = TH0_VALUE;
TL0 = TL0_VALUE;
cnt++;
}
//---------------------- 예제 프로그램 시작 -----------------------------//
/*
타이머0, 모드1 사용, 10ms
*/
#include <AT89X52.H>
#define HIGH10MS 0xB1
#define LOW10MS 0xDF
volatile unsigned int ui_cnt;
unsigned char uc_cnt;
void main(void)
{
TMOD &= 0xF0;
TMOD |= 0x01;
TH0 = HIGH10MS;
TL0 = LOW10MS;
ET0=1;
EA=1;
TR0=1;
ui_cnt = uc_cnt = 0;
while(1) {
if(ui_cnt>100) {
ui_cnt-=100;
P1_3=!P1_3;
if(uc_cnt>10) {
uc_cnt=0;
P1_4=!P1_4;
}
uc_cnt++;
}
}
}
void it_timer0(void) interrupt 1 /* interrupt address is 0x000b */
{
TH0 = HIGH10MS;
TL0 = LOW10MS;
ui_cnt++;
P1_2=!P1_2;
}
--------------------------------------
Timy의 전자카페
기분좋은 하루되세요. ^^
http://www.electoy.net
--------------------------------------