본문 바로가기

Hacked Brain/embeddedland.net

pwm


http://blog.naver.com/okh0217/60017574469

PWM(Pulse Width Modulation)


주파수는 변하지 않고 On/Off의 비율을 변화시키는 것을 펄스폭 변조라고 한다.  이 신호를 증폭해서 LED나 모터에 연결하면 On일 때의 시간이 길수록 더 많은 출력을 얻게 된다. 따라서 LED의 밝기나 모터의 속도를 제어할 수 있다. 아래 그림에서는 위로 올라갈수록 더 높은 출력을 얻게 된다.

80C196KC에는 PWM을 출력하는 핀이 3개 마련되어 있다.

  P2.5 (PWM)
  P1.3 (PWM1)  80C196KC 이상
  P1.4 (PWM2)  80C196KC 이상

이를 제어하기 위해 IOC1.0 (IOC1 레지스터의 0번 비트), IOC2.2, IOC3.2, IOC3.3 을 사용한다.
 

IOC1.0

 0 : P2.5 I/O     1: PWM

P2.5를 I/O로 쓸 것인지 PWM으로 쓸 것인지를 결정

IOC2.2

 0 : f = 20MHz / 512    (39.1KHz)
 1 : f = 20MHz / 1024  (19.5KHz)

PWM 신호의 주파수를 결정

IOC3.2

 0 : P1.3 I/O     1 : PWM1

P1.3을 I/O로 쓸 것인지 PWM1로 쓸 것인지를 결정

IOC3.3

 0 : P1.4 I/O     1 : PWM2

P1.4를 I/O로 쓸 것인지 PWM2로 쓸 것인지를 결정

IOC2.2 설명란의 20MHz는 CPU 입력 클럭 주파수이다.

그리고 펄스폭을 조정하기 위해서 pwm_control, pwm_control1, pwm_control2 이렇게 3개의 레지스터가 준비되어 있다. 위에 있는 표의 4개의 비트를 설정하고, pwm_control 레지스터에 원하는 값을 써 넣으면 된다. 값이 높을수록 On/Off의 비율은 커진다. (아래 그림 참조)

SFR(Special Function Register표를 참조하면서 다음 프로그램을 본다.

 

#pragma code
#pragma model(kc)

#include <80c196.h>

void delay (int i)
{
     int c,j;
     j=30000;
     for (c=0;c<I;c++)
     while(j--);
}

void _main(void)
{
    wsr=0;  
    ioc1=1;                         /* 00000001B    P2.5를 PWM신호로 사용 */
    ioc2=4;                         /* 00000100B    PWM 의 주파수를 19.5KHz로 설정 */
   
    while (1) {
      for (i=0;i<256;i++) {
            pwm_control = i;   /* 펄스의 on/off 비율을 지정 */
            delay(1);
      }

      for (i=255;i>0;i--) {
            pwm_control = i;   /* 펄스의 on/off 비율을 지정 */
            delay(1);
      }
    }
}


위 프로그램을 pwm.c로 저장하고 컴파일과 링크를 한다.

프로그램을 실행하고 오실로스코프로 P2.5에서 나오는 파형을 관찰하면 주파수의 변화는 없이 On/Off의 비율이 늘었다 줄었다 하는 것을 볼수 있다.  오실로스코프가 없다면 LED를 연결해 본다. 불의 밝기가 밝아졌다 어두어졌다를 반복할 것이다. 마찬가지로 신호를 증폭해서 모터에 연결하면 모터의 속도가 빨라졌다 느려졌다를 반복한다.

 PWM1과 PWM2를 사용하려면 다음과 같이 한다. pwm_control1, pwm_control2, ioc3가 모두 wsr=1에 있으므로 pwm_control1,2 그리고 ioc3에 값을 써넣기 전에 먼저 wsr=1로 설정하는 것을 잊으면 안된다. 단, 80c196.h파일(한번 보세요)에  ioc3가 정의되어 있지 않으므로 ioc3와 같은 번지(0CH)를 사용하는 timer2를 이용해야 한다. (SFR표 참조) timer2와 ioc3는 같은 번지이므로 wsr을 설정함으로써 구분한다.
 

코  드

wsr=0;
timer2=0xff;

wsr=1;
timer2=0xff;

의  미

timer2 <- 0xff

ioc3 <- 0xff



대략적인 코드는 다음과 같다.

 

wsr = 0;
ioc2 = 4;                         /* 00000100B    PWM 의 주파수를 19.5KHz로 설정 */

wsr = 1;
timer2 = 12;                   /* ioc3=00001100B    PWM1, PWM2 Enable   */
pwm_control1=200;
pwm_control2=50;


P1.3, P1.4에서 나오는 파형을 오실로스코프로 확인해본다.

전에 L298을 이용한 모터제어 실험을 했었다.
L298의 enable단자를 P1.2에 연결하여 단순히 On, Off신호를 주었다. 이번에는 P2.5의 PWM신호를 L298의 enable단자에 입력시켜본다. 모터를 빠르게 On, Off하게 된다. 위에 있는 pwm.c 프로그램을 실행시키면 모터의 속도가 빨라졌다 느려졌다 한다. 단 pwm_control값이 너무 낮으면 모터에 전달되는 출력이 낮아서 모터가 돌지 않으므로 pwm_control의 값을 적당한 값이상 주도록 한다. delay값이 너무 낮아도 결과를 확인하기 힘들므로 delay값을 많이 주어서 실험해 본다
.

80C196KC에는 8채널 10비트 AD 컨버터가 내장되어 있다. 그럼 DC컨버터는?
다음 회로도처럼 로우패스 필터를 달아주면 DC컨버팅이 가능하다.