2010년 4월 5일 월요일

[AVR] 16Bit_Timer1.h / 16Bit_Timer1.c

/******************************************************
**
** 16Bit_Timer1.h
**
** Version : 1.0
** Target : ATmega128
** Created : 2010.01.15
** Author : Chang-Su Lee (ELCO Kookmin Univ.)
** Reference : Datasheet
**
******************************************************/


#ifndef __16BIT_TIMER1_H__
#define __16BIT_TIMER1_H__

void Counter1_Init();
unsigned int Counter1_Get_Value();

void Timer1_CTC_Init();
void Timer1_CTC_Control(unsigned char flag); // Compare match 인터럽트 인에이블
void Timer1_CTC_SetTimer(unsigned int top);

void Timer1_PC_PWM_Init(); // TOP가 ICR1인 모드 (OC1A, OC1B, OC1C 모두에서 PWM출력 가능)
void Timer1_PC_PWM_Set_TOP(unsigned int top);
void Timer1_PC_PWM_Set_OC1A_Duty(unsigned int Duty);
void Timer1_PC_PWM_Set_OC1B_Duty(unsigned int Duty);
void Timer1_PC_PWM_Set_OC1C_Duty(unsigned int Duty);

void Timer1_Fast_PWM_Init(); // TOP가 ICR1인 모드 (OC1A, OC1B, OC1C 모두에서 PWM출력 가능)
void Timer1_Fast_PWM_Set_TOP(unsigned int top);
void Timer1_Fast_PWM_Set_OC1A_Duty(unsigned int Duty);
void Timer1_Fast_PWM_Set_OC1B_Duty(unsigned int Duty);
void Timer1_Fast_PWM_Set_OC1C_Duty(unsigned int Duty);

void Timer1_PFC_PWM_Init(); // TOP가 ICR1인 모드 (OC1A, OC1B, OC1C 모두에서 PWM출력 가능)
void Timer1_PFC_PWM_Set_TOP(unsigned int top);
void Timer1_PFC_PWM_Set_OC1A_Duty(unsigned int Duty);
void Timer1_PFC_PWM_Set_OC1B_Duty(unsigned int Duty);
void Timer1_PFC_PWM_Set_OC1C_Duty(unsigned int Duty);

#endif








/*******************************************************
**
** 16Bit_Timer1.c
**
** Version : 1.0
** Target : ATmega128
** Created : 2010.01.15
** Author : Chang-Su Lee (ELCO Kookmin Univ.)
** Reference : Datasheet
**
******************************************************/


#include <avr/io.h>
#include "16Bit_Timer1.h"

/*********************************************************
** 모드: Normal모드
** 기능: 카운트 값의 클리어가 카운팅 동작 중에는 이루어 지지 않기 때문에 항상 최대값 0xFFFF까지
** 카운팅을 수행한 후 다시 0x0000부터 카운팅을 수행하게 된다. 또한 0xFFFF에서 0x0000으로
** 바뀌는 순간에 Overflow인터럽트가 발생하게 된다.
** 단순하게 증가하는 타이머/카운터이므로 외부에서 입력되는 펄스 수를 세는 카운터 동작으로
** 사용하는데 적합하다.
*********************************************************/


void Counter1_Init()
{
TCCR1A = 0x00; // COM1A1 = 0,COM1A0 = 0,COM1B1 = 0,COM1B0 = 0,COM1C1 = 0,COM1C0 = 0,WGM11 = 0,WGM10 = 0
// PWM출력핀인 OC1A~OC1C의 상태는 COM1A1~COM1C0의 레지스터들로 설정한다.
TCCR1B = 0x06; // ICNC1 = 0,ICES1 = 0, 0,WGM13 = 0,WGM12 = 0,CS12 = 1,CS11 = 1,CS10 = 0
// ICNC1과 ICES1 레지스터는 입력캡쳐 기능을 설정하는 레지스터이다. 이는 어떤신호가 해당
// 핀으로 들어오면 타이머의 값을 ICR1레지스터에 저장시키는 기능이다.
// CS12, CS11, CS10레지스터는 프리스케일러의 분주비를 선택하는 기능이다. (clk/256)

TCCR1C = 0x00; // FOC1A = 0,FOC1B = 0,FOC1C = 0, 0, 0, 0, 0, 0
// 이 레지스터는 강제로 비교매치가 된 것과 같은 출력을 내보낸다. PWM 모드가 아닌 경우에만
// 유효하다. 특별한 경우가 아니라면 이비트는 0으로 둔다.
TIMSK &= 0xC3; // OCIE2 = 0,TOIE2 = 0,TICIE1 = 0, OCIE1A = 0, OCIE1B = 0,TOIE1 = 0,OCIE0 = 0,TOIE0 =0
// 타이머/카운터 인터럽트를 개별적으로 허용하는 기능을 수행하는 레지스터이다.
TIFR = 0x00; // OCF2 = 0,TOV2 = 0,ICF1 = 0,OCF1A = 0,OCF1B = 0,TOV1 = 0,OCF0 = 0, TOV0 = 0
// 인터럽트 플랙 레지스터이다.
ETIMSK &= 0xFE; // 0, 0,TICIE3 = 0, OCIE3A = 0,OCIE3B = 0, TOIE3 = 0,OCIE3C = 0, OCIE1C = 0
// TIMSK와 같은 기능이다.
ETIFR = 0x00; // 0, 0,ICF3 = 0,OCF3A = 0,OCF3B = 0,TOV3 = 0,OCF3C = 0,OCF1C = 0
// TIFR과 같은 기능이다.
SFIOR = 0x00; // TSM = 0, 0, 0, 0, ACME = 0,PUD = 0, PSR0 = 0,PSR321 = 0
// 프리스케일러를 리셋시키는 기능의 레지스터이다. 특별한 경우가 아니라면 0으로 둔다.
}

unsigned int Counter1_Get_Value()
{
return (TCNT1H<<8)+TCNT1L;
}

/***************************************************************
** 모드: CTC(Clear Timer on Compare Match)모드 (TOP이 OCR1X인 모드이다.)
** 기능: 이 모드에서는 타이머/카운터 레지스터의 값이 출력비교 레지스터 OCR1X의 값과 일치하면 그 다음
** 클럭 사이클에서 0으로 클리어된다. 따라서, 이모드에서는 클록 입력에 의하여 타이머/카운터
** 레지스터의 값이 항상 0x0000~OCR1의 범위에서 계수동작이 반복되며, TCNT1의 값이 증가하다가 OCR1X
** 레지스터 값과 같게 되면 그 다음 주기에 출력비교 인터럽트가 요청된다.
**************************************************************/


void Timer1_CTC_Init()
{
TCCR1A = 0x00; // COM1A1 = 0,COM1A0 = 0,COM1B1 = 0,COM1B0 = 0,COM1C1 = 0,COM1C0 = 0,WGM11 = 0,WGM10 = 0
// PWM출력핀인 OC1A~OC1C의 상태는 COM1A1~COM1C0의 레지스터들로 설정한다.
TCCR1B = 0x0C; // ICNC1 = 0,ICES1 = 0, 0,WGM13 = 0,WGM12 = 1,CS12 = 1,CS11 = 0,CS10 = 0
// ICNC1과 ICES1 레지스터는 입력캡쳐 기능을 설정하는 레지스터이다. 이는 어떤신호가 해당
// 핀으로 들어오면 타이머의 값을 ICR1레지스터에 저장시키는 기능이다.
// CS12, CS11, CS10레지스터는 프리스케일러의 분주비를 선택하는 기능이다. (clk/256)
TCCR1C = 0x00; // FOC1A = 0,FOC1B = 0,FOC1C = 0, 0, 0, 0, 0, 0
// 이 레지스터는 강제로 비교매치가 된 것과 같은 출력을 내보낸다. PWM 모드가 아닌 경우에만
// 유효하다. 특별한 경우가 아니라면 이비트는 0으로 둔다.

SFIOR = 0x00; // TSM = 0, 0, 0, 0, ACME = 0,PUD = 0, PSR0 = 0,PSR321 = 0
// 프리스케일러를 리셋시키는 기능의 레지스터이다. 특별한 경우가 아니라면 0으로 둔다.
TIMSK &= 0xEF; // OCIE2 = 0,TOIE2 = 0,TICIE1 = 0, OCIE1A = 0, OCIE1B = 0,TOIE = 0,OCIE0 = 0,TOIE0 =0
// 타이머/카운터 인터럽트를 개별적으로 허용하는 기능을 수행하는 레지스터이다.
TIFR = 0x00; // OCF2 = 0,TOV2 = 0,ICF1 = 0,OCF1A = 0,OCF1B = 0,TOV1 = 0,OCF0 = 0, TOV0 = 0
// 인터럽트 플랙 레지스터이다.
}

void Timer1_CTC_Control(unsigned char flag) // Compare match 인터럽트 인에이블
{
if( flag )
TIMSK |= 0x10; // OCR1A의 인터럽트 Enable (조정하여 OCR1B, OCR1C 도 Enable시킬수 있다.)
else
TIMSK &= 0xEF; // Disable
}

void Timer1_CTC_SetTimer(unsigned int top)
{
OCR1A = top;
}

/**********************************************************
** 모드: Phase Correct PWM모드
** 기능: PC PWM 모드는 높은 분해능의 PWM 출력 파형을 발생하는데 유용하다. 이 동작 모드에서는 타이
** 머/카운터 레지스터의 계수동작이 상향 카운터로서 0x0000~TOP까지 증가하였다가 다시 하향 카운터
** 로서 TOP~0x0000으로 감소하는 동작을 반복적으로 수행한다.
** ICR1을 TOP로 사용하는 모드는 캡쳐기능을 사용할 수 없고 OCR1A를 TOP로 사용하는 모드는
** PWM을 OC1B, OC1C 두 핀으로만 출력할 수 있다.
**************************************************************/


void Timer1_PC_PWM_Init() // TOP가 ICR1인 모드 (OC1A, OC1B, OC1C 모두에서 PWM출력 가능)
{
TCCR1A = 0xAA; // COM1A1 = 1,COM1A0 = 0,COM1B1 = 1,COM1B0 = 0,COM1C1 = 1,COM1C0 = 0,WGM11 = 1,WGM10 = 0
// PWM출력핀인 OC1A~OC1C의 상태는 COM1A1~COM1C0의 레지스터들로 설정한다.
TCCR1B = 0x14; // ICNC1 = 0,ICES1 = 0, 0,WGM13 = 1,WGM12 = 0,CS12 = 1,CS11 = 0,CS10 = 0 (clk/256)
// ICNC1과 ICES1 레지스터는 입력캡쳐 기능을 설정하는 레지스터이다. 이는 어떤신호가 해당
// 핀으로 들어오면 타이머의 값을 ICR1레지스터에 저장시키는 기능이다.
// CS12, CS11, CS10레지스터는 프리스케일러의 분주비를 선택하는 기능이다.
TCCR1C = 0x00; // FOC1A = 0,FOC1B = 0,FOC1C = 0, 0, 0, 0, 0, 0
// 이 레지스터는 강제로 비교매치가 된 것과 같은 출력을 내보낸다. PWM 모드가 아닌 경우에만
// 유효하다. 특별한 경우가 아니라면 이비트는 0으로 둔다.

SFIOR = 0x00; // TSM = 0, 0, 0, 0, ACME = 0,PUD = 0, PSR0 = 0,PSR321 = 0
// 프리스케일러를 리셋시키는 기능의 레지스터이다. 특별한 경우가 아니라면 0으로 둔다.
DDRB |= 0xE0;
}

void Timer1_PC_PWM_Set_TOP(unsigned int top)
{
ICR1 = top;
}

void Timer1_PC_PWM_Set_OC1A_Duty(unsigned int Duty)
{
OCR1A = Duty;
}

void Timer1_PC_PWM_Set_OC1B_Duty(unsigned int Duty)
{
OCR1B = Duty;
}

void Timer1_PC_PWM_Set_OC1C_Duty(unsigned int Duty)
{
OCR1C = Duty;
}

/**********************************************************
** 모드: Fast PWM모드
** 기능: Fast PWM모드는 높은 주파수의 PWM 출력 파형을 발생하는데 유용하다. 이 동작 모드에서는
** 타이머/카운터 레지스터 TCNT1의 계수동작이 항상 0x0000~TOP의 범위에서 증가
** 하는 방향으로만 반복적으로 수행되며, 이때 타이머/카운터 레지스터 TCNT1의 값은 항상 출력비교
** 레지스터 OCR1의 값과 비교되어 OC1X, 의 출력신호를 변형시킨다.
** ICR1을 TOP로 사용하는 모드는 캡쳐기능을 사용할 수 없고 OCR1A를 TOP로 사용하는 모드는
** PWM을 OC1B, OC1C 두 핀으로만 출력할 수 있다.
** OCR1X의 값을 바꾸는 순간 비대칭 파형을 발생하기 때문에 듀티를 자주 바꿔줄 필요가 있을때
** 이모드는 적합하지 않다.
**************************************************************/


void Timer1_Fast_PWM_Init() // TOP가 ICR1인 모드 (OC1A, OC1B, OC1C 모두에서 PWM출력 가능)
{
TCCR1A = 0xAA; // COM1A1 = 1,COM1A0 = 0,COM1B1 = 1,COM1B0 = 0,COM1C1 = 1,COM1C0 = 0,WGM11 = 1,WGM10 = 0
// PWM출력핀인 OC1A~OC1C의 상태는 COM1A1~COM1C0의 레지스터들로 설정한다.
TCCR1B = 0x1C; // ICNC1 = 0,ICES1 = 0, 0,WGM13 = 1,WGM12 = 1,CS12 = 1,CS11 = 0,CS10 = 0 (clk/256)
// ICNC1과 ICES1 레지스터는 입력캡쳐 기능을 설정하는 레지스터이다. 이는 어떤신호가 해당
// 핀으로 들어오면 타이머의 값을 ICR1레지스터에 저장시키는 기능이다.
// CS12, CS11, CS10레지스터는 프리스케일러의 분주비를 선택하는 기능이다.
TCCR1C = 0x00; // FOC1A = 0,FOC1B = 0,FOC1C = 0, 0, 0, 0, 0, 0
// 이 레지스터는 강제로 비교매치가 된 것과 같은 출력을 내보낸다. PWM 모드가 아닌 경우에만
// 유효하다. 특별한 경우가 아니라면 이비트는 0으로 둔다.

SFIOR = 0x00; // TSM = 0, 0, 0, 0, ACME = 0,PUD = 0, PSR0 = 0,PSR321 = 0
// 프리스케일러를 리셋시키는 기능의 레지스터이다. 특별한 경우가 아니라면 0으로 둔다.
DDRB |= 0xE0;
}

void Timer1_Fast_PWM_Set_TOP(unsigned int top)
{
ICR1 = top;
}

void Timer1_Fast_PWM_Set_OC1A_Duty(unsigned int Duty)
{
OCR1A = Duty;
}

void Timer1_Fast_PWM_Set_OC1B_Duty(unsigned int Duty)
{
OCR1B = Duty;
}

void Timer1_Fast_PWM_Set_OC1C_Duty(unsigned int Duty)
{
OCR1C = Duty;
}

/**************************************************************
** 모드: Phase and Frequency Correct PWM모드
** 기능: Phase Correct PWM모드와 매우 유사하며 출력비교 레지스터가 삼각파의 저점에서 갱신되므로
** 이를 수정하여 듀티비를 가변하거나 PWM의 주기를 변경하더라도 항상 대칭적인 PWM 출력을
** 발생하게 되는 장점을 가진다. 따라서 이 모드는 PWM 출력의 듀티비와 스위칭 주파수를 모두 변경
** 하여야 하는 응용에 적합하다.
***********************************************************/


void Timer1_PFC_PWM_Init() // TOP가 ICR1인 모드 (OC1A, OC1B, OC1C 모두에서 PWM출력 가능)
{
TCCR1A = 0xA8; // COM1A1 = 1,COM1A0 = 0,COM1B1 = 1,COM1B0 = 0,COM1C1 = 1,COM1C0 = 0,WGM11 = 0,WGM10 = 0
// PWM출력핀인 OC1A~OC1C의 상태는 COM1A1~COM1C0의 레지스터들로 설정한다.
TCCR1B = 0x14; // ICNC1 = 0,ICES1 = 0, 0,WGM13 = 1,WGM12 = 0,CS12 = 1,CS11 = 0,CS10 = 0 (clk/256)
// ICNC1과 ICES1 레지스터는 입력캡쳐 기능을 설정하는 레지스터이다. 이는 어떤신호가 해당
// 핀으로 들어오면 타이머의 값을 ICR1레지스터에 저장시키는 기능이다.
// CS12, CS11, CS10레지스터는 프리스케일러의 분주비를 선택하는 기능이다.
TCCR1C = 0x00; // FOC1A = 0,FOC1B = 0,FOC1C = 0, 0, 0, 0, 0, 0
// 이 레지스터는 강제로 비교매치가 된 것과 같은 출력을 내보낸다. PWM 모드가 아닌 경우에만
// 유효하다. 특별한 경우가 아니라면 이비트는 0으로 둔다.

SFIOR = 0x00; // TSM = 0, 0, 0, 0, ACME = 0,PUD = 0, PSR0 = 0,PSR321 = 0
// 프리스케일러를 리셋시키는 기능의 레지스터이다. 특별한 경우가 아니라면 0으로 둔다.
DDRB |= 0xE0;
}

void Timer1_PFC_PWM_Set_TOP(unsigned int top)
{
ICR1 = top;
}

void Timer1_PFC_PWM_Set_OC1A_Duty(unsigned int Duty)
{
OCR1A = Duty;
}

void Timer1_PFC_PWM_Set_OC1B_Duty(unsigned int Duty)
{
OCR1B = Duty;
}

void Timer1_PFC_PWM_Set_OC1C_Duty(unsigned int Duty)
{
OCR1C = Duty;
}

댓글 없음:

댓글 쓰기