본문 바로가기

디지털회로/AT91SAM7S256

PWM 제어기

 

AT91SAM7S256에는 모두 4채널의 PWM(Pulse Width Modllation) 제어기가 있는데 각 채널은 서로 독립적으로 클록 입력을 받아 동작하여 주기, 듀티 사이클,  출력 파형의 극성 등을 선택적으로 제어할 수 있다.

PWM제어기 블럭 구성도

PIO에 의한 외부 핀 멀티플렉싱에서 Peripheral B로 설정

PWM제어기는 기본적으로 클록이 공급되어 있지 않은 상태이므로 PMC에서 클록을 공급하도록 설정해야한다.

클록 발생기와 4개의 채널로 구성, 클록 발생기는 마스터 클록 MCK를 사용하여 13가지의 클록을 PWM 제어기에 공급한다.

클록 발생기는 마스터 클록 MCK를 N(1,2,4,8,16,32,64,128,256,512,1024)으로 분주한 11가지의 클록 신호를 발생하며, 이밖에도 11가지의 클록을 힘의로 선택하여 이를 다시 1~255로 분주한 clkA/clkB 출력 신호를 발생한다.
clkA/clkB 신호를 발생하기 위한 클록의 선택은 PWM_MR 레지스터에서 PREA|PREB로 설정하며 이를 다시 분주하기 위한 분주비 1~255는 DIVA/DIVB로 설정한다.

clkA출력주파수 = MCK/N/DIVA
clkB출력주파수 = MCK/N/DIVB

만약 DIVA/DIVB를 0으로 설정하면 각각 clkA/clkB 출력신호의 발생이 금지된다.

 

클록발생기


PWM제어기의 각 채널은 클록 선택부, 카운터, 비교기 등으로 구성
클록 선택부는 클록 발생기에서 만든 13가지 클록 소스 중에서 1가지를 선택하여 카운터로 공급하는데, 이러한 클록 선택은 PWM_CMRx 레지스터에서 CPRE필드로 수행한다.
카운터는 16비트로 되어 있고 비교기는 현재의 카운터 값과 파형을 발생하기 위해 설정한 값을 비교하여 출력의 상태를 결정한다.
각 채널 구조


PWM출력 파형의 주기는 PWM_CPRDx 레지스터에서 CPRD필드의 16비트로 지정한다.
카운터가 톱니파처럼 증가하여 출력 파형이 좌측으로 정렬된다면 마스터클록 MCK를 N으로 분주한 클록펄스가 CPRD만큼 입력될 때 PWM 출력의 1주기가 만들어진다.
즉, 카운터가 0에서부터 증가하여 CPRD에 도달하면 리셋되어 1주기를 완료한다.

그외 카운터가 삼각파처럼 증가하였다가 감소하여 출력 파형이 중앙으로 정렬된다면 마스터클록 MCK를 N으로 분주한 클록펄스가 2xCPRD만큼 입력될 때 PWM출력의 1주기가 만들어진다.
즉, 카운터가 0에서부터 증가하여 CPRD에 도달하면 카운터는 다시 감소하기 시작하고 이것이 다시 0이 되면 1주기를 완료한다.

PWM 출력 파형이 좌측으로 정렬될지 중앙으로 정렬될지는 PWM_CMRx레지스터의 CALG 비트로 설정한다.
 - CALG = 0 (좌측정렬), CALG = 1(중앙정렬)

또한 PWM 출력 파형 극성의 한 주기가 시작될 때 신호가 0상태로 될지 또는 1상태로 될지를 나타내는데, 이는 PWM_CMRx 레지스터의 CPOL 비트로 설정한다.
 - CPOL = 0 (L레벨), CPOL = 1 (H레벨)

출력 파형의 극성은 PWM 채널의 동작을 허용하기 전에 먼저 설정해야 한다.

CDTY = 0 / CPOL = 1 또는 CDTY = CPRD / CPOL = 0으로 설정하면
출력 파형 = 0

CDTY = 0 / CPOL = 0 또는 CDTY = CPRD / CPOL = 1로 설정하면
출력 파형 = 1

PWM 제어기의 출력 파형


PWM 제어기의 동작

사용할 레지스터를 헤더파일에 include 한다.
전원공급을 pmc로 하며, 풀업저항은 금지시키고, Priepheral B로 설정한다.
그리고 사용할 pwm3채널의 병렬I/O를 금지시킨다.
PWM_MR에서 각 핀에 사용할 값을 입력한다.
PWM_CMRx(3)에 CPD,CPOL,CALG,CPRE을 설정한다.
pwm.h

#ifndef __PWM_H__
#define __PWM_H__
#include "pio.h"  //b를 사용하기 위해
#include "pmc.h"

#define PWM_MR  (*((volatile unsigned int *)0xFFFCC000)) 
//모드 레지스터
#define PWM_CMR3 (*((volatile unsigned int *)0xFFFCC260))
//채널 모드 레지스터
#define PWM_CPRD3 (*((volatile unsigned int *)0xFFFCC268)) 
//채널 주기 레지스터
#define PWM_CDTY3 (*((volatile unsigned int *)0xFFFCC264)) 
//채널 듀티 사이클 레지스터
#define PWM_CUPD3 (*((volatile unsigned int *)0xFFFCC270)) 
//채널 업데이트 레지스터
#define PWM_IER  (*((volatile unsigned int *)0xFFFCC010)) 
//PWM 인터럽트 허용 레지스터
#define PWM_ENA (*((volatile unsigned int *)0xFFFCC004)) 
//PWM 허용 레지스터
#define PWMC 10
#define PWM3 14
// PWM_MR
#define PREA  8
#define PREB  24
#define DIVA  0
#define DIVB  16
// PWM_CMRx(PWM3)
#define CPRE  0  //분주비
#define CALG  8  //톱니파, 삼각파 설정
#define CPOL  9  // H/L설정
#define CPD  10  // 듀티 / 주기 수정
// PWM_CDTYx
#define CDTY  0
#define CPRD  0
#define CHID  3  

void PWM3_init(void);
void PWM3_dutyset(unsigned int uiDuty);
#endif //__PWM_H__




pwm.c

#include "pwm.h"

void PWM3_init(void)
{
  PMC_PCER = (1<<PWMC);      // 주변장치 클록 허용 레지스터 (1<<10);, PWMC => PID10

  PIO_PUDR = (1<<PWM3);        // 풀업저항 off
  PIO_BSR = (1<<PWM3);        // Peripheral B mode
  PIO_PDR = (1<<PWM3);        // 이 핀을 병렬i/o로 사용하는것을 금지

  //48,000,000Hz / 8 / 30 = 200,000HZ => 200KHz
  PWM_MR = (3<<PREB) |(3<<PREA) | (30<<DIVA) | (30<<DIVB);
  //CPD(duty),CPOL(H),CALG(single),CPRE(CLKA)
  PWM_CMR3 = (0<<CPD) | (1<<CPOL) | (0<<CALG) | (11<<CPRE);  
  
  PWM_CDTY3 = 100;    //시작하자마자 100 (1/8)
  PWM_CPRD3 = 800;    //최대값

  PWM_ENA = (1<<CHID);  //채널 3번 사용하겠다는 명령

  
  return;
}

void PWM3_dutyset(unsigned int uiDuty) //듀티비로 LED조절 
{
  if(800 < uiDuty)
  {
    uiDuty = 800;
  }
  
  PWM_CUPD3 = uiDuty;
}

'디지털회로 > AT91SAM7S256' 카테고리의 다른 글

동기 클럭 / 비동기 클럭  (0) 2011.09.26
SPI - 직렬통신 포트  (0) 2011.09.26
A/C 컨버터(ADC)  (1) 2011.09.19
초음파 SRF-05 실행시키기  (0) 2011.09.16
오늘 바꾼 TIMER / main 외 ULTRA  (0) 2011.09.09