Você está na página 1de 10

Lógica de programação desenvolvida para PIC18F4550 com compilador C18

(PWM)

A sigla PWM é traduzida como Modulação por Largura de Pulso, um sinal PWM
pode ser definido como um sinal de frequência fixa e largura de pulso variável. A
largura de pulso, também chamada de ciclo ativo (Duty Cycle) é a parte do sinal que
se mantém em lógico 1.

Embora o sinal PWM seja digital, existe um nível DC (valor médio) associado a ele,
a variação na largura do ciclo ativo resulta na variação do seu nível DC, assim
temos:

Tempo do ciclo ativo


Vdc = x Valor de pico da tensão
Período do sinal PWM

Ex: Suponha um sinal PWM de 5V de pico com período de 10us e ciclo ativo de 5us
(o que corresponde a 50% do ciclo ativo), assim temos um nível DC de:

5us
Vdc = x 5 = 2,5v
10us

Se ligarmos o sinal PWM a uma lâmpada de 5V e fizermos seu nível DC variar de


0v a 5v você perceberá que o brilho da lâmpada irá aumentar à medida que o nível
DC aumentar.

Podemos implementar um conversor D/A (Digital para analógico) com um sinal


PWM, para isso precisamos de um filtro passa-baixas na saída PWM do PIC
Onde Vin será o sinal PWM vindo do PIC e Vout será o sinal analógico gerado e seu
valor será o nível DC associado ao PWM, porém para que o circuito possa
recuperar o nível DC do sinal com sucesso a frequência de corte do filtro deve ser
pelo menos duas vezes menor que a frequência do sinal PWM, onde:

1
Fc =
2 πRC

Para entendermos o funcionamento do PWM precisamos ver um módulo importante


para esta aplicação que é o:

● Timer 2

O módulo timer 2 só pode funcionar como um temporizador de 8 bits.

Diferentemente do Timer 0 o Timer 2 só gera um estouro quando o seu conteúdo se


iguala ao conteúdo do registrador PR2, quando isso ocorre o seu conteúdo e zerado
e a contagem se reinicia.

O registrador T2CON é responsável pela configuração do Timer 2

Bit7) Não implementado, deve ser lido como zero.


Bit6:3) T2OUTPS3:T2OUTPS0) Seleção do postscaler

0000 = 1:1
0001 = 1:2
0010 = 1:3
0011 = 1:4
.
.
.
1111 = 1:16

Bit2)TMR2ON) Liga o módulo Timer 2

Bit1:0)T2CKPS1:T2CKPS0) Seleção do prescaler

00 = 1:1
01 = 1:4
10 = 1:8
11 = 1:16

Observe que além do prescaler anteriormente estudado, temos também o


postscaler, ele serve para atrasar a interrupção, ou seja, o registrador do timer 2
(TMR2) deve estourar x vezes para que a interrupção seja gerada, sendo x o valor
correspondente do postscaler.

Ex: Suponha que escolhamos o postscaler de 1:8 assim será necessário 8 estouros
do TMR2 para que a interrupção seja gerada.

Dois módulos são capazes de gerar o sinal PWM no PIC, são eles o CCP1 e CCP2,
onde os registradores CCP1CON e CCP2CON são responsáveis por ativar o modo
de operação PWM

CCP1CON:
Mostraremos como gerar o PWM pelo módulo CCP1 que está ligado a saída física
RC2 do PIC (Pino 17), assim o pino RC2 deve ser configurado como saída e seu
valor de saída será o sinal PWM.

Podemos usar 4 saídas do PIC para tratar o PWM, são elas P1A,P1B,P1C,P1D

Através dos bits 7:6 (P1M1:P1M0) do registrador CCP1CON definimos como essas
saídas serão utilizadas:

00 = saída única; P1A modulando e P1B,P1C,P1D atribuidos como pinos de porta


01 = saída em ponte completa; P1D modulando, P1A ativo e P1B,P1C inativos
10 = Saída em meia ponte; P1A, P1B modulando com controle de banda morta,
P1C, P1D atribuído como pinos de porta
11 = Saída de ponte completa reversa; P1B modulado, P1C ativo, P1A e P1D
inativos.
Com essas configurações podemos selecionar a polaridade do sinal, ajustar a
banda morta, fazer parada e reinício automático.

Em nosso material usaremos a configuração 00 onde queremos apenas P1A


modulando o sinal PWM, que no caso será o pino 17 do PIC (RC2), as demais
aplicações com P1B,P1C,P1D podem ser exploradas a medida da necessidade.
Para alterar o período do sinal PWM devemos ter em mente a ligação do módulo
timer 2 e o sinal PWM: Uma vez que o timer 2 estoura (TMR2 = PR2) o sinal do
PWM é levado a nível alto, assim que o valor de TMR2 se iguala aos registradores
responsáveis pelo ciclo ativo, o sinal PWM vai a nível baixo. No próximo estouro do
timer 2 o sinal PWM volta a nível alto e o processo se repete.

Assim sendo para alterarmos o período do sinal PWM devemos alterar o valor
armazenado no registrador PR2

O valor exato do período é dado pela fórmula abaixo:

T(PWM) = (PR2 +1 ) x 4 x (1/Fosc) x Prescaler_do_timer2

Podemos encontrar o valor de PR2 dado um período desejado pela seguinte


fórmula:

PR2 = [Fosc / (FPWM x 4 x Prescaler_do_timer2) ] - 1

Ex: Qual valor deve ser inserido no PR2 para que o PWM tenha uma frequência de
15625Hz sendo a frequência do oscilador principal de 8MHz e prescaler de 1:1 no
Timer 2?

PR2 = [8000000/ (156625 x 4 x 1)] -1 = 127

O tempo correspondente ao ciclo ativo do sinal PWM é controlado por 10bits,


chamados de bits de controle, os quais são compostos pelo registrador CCPR1L
mais dois bits do registrador CCP1CON (bits 5 e 4): DC1B1:DC1B0

Assim:

DC1B1 DC1B0
CCPR1

9 8 7 6 5 4 3 2 1 0

Observe que CCPR1 permanece com os 8 bits mais significativos dos 10 bits.

Ex: Suponha que deva ser colocado o valor de 200(10) = 0011001000(2) no


registrador (CCPR1L+DC1B1:DC1B0) assim:

CCP1CON = 0bxx00xxxx;
CCPR1 = 0b00110010;

O PIC incrementa 2 bits adicionais ao registrador TMR2 obtidos do oscilador


principal e do prescaler, assim quando TMR2 se iguala ao valor de 10 bits
mostrados acima (CCPR1L+DC1B1:DC1B0) , o sinal PWM vai a nível baixo.

Logo temos que quando TMR2 = PR2 o PWM vai a nível alto e quando
TMR2 = (CCPR1L+DC1B1:DC1B0) o PWM vai a nível baixo.

O tempo do ciclo ativo pode ser calculado pela seguinte fórmula:

PWM(ciclo ativo) = (CCPR1L+DC1B1:DC1B0) x (1/Fosc) x Prescaler_do_timer2

Onde (CCPR1L+DC1B1:DC1B0) é o valor do registrador de 10 bits explicado acima.

Os bits CCP1M3:CCP1M0 (CCP1CON<3:0>) podem ser configurados da seguinte


forma para PWM:

1100 = modo PWM: P1A, P1C active-high; P1B, P1D active-high


1101 = modo PWM: P1A, P1C active-high; P1B, P1D active-low
1110 = modo PWM: P1A, P1C active-low; P1B, P1D active-high
1111 = modo PWM: P1A, P1C active-low; P1B, P1D active-low

onde active-high (ativo em nível alto) e active-low (ativo em nível baixo) funcionam
conforme a figura abaixo:
Na nossa aplicação queremos o sinal PWM do tipo ativo em nível alto, como nossa
saída será o P1A, temos que usar a configuração: 1100 ou 1101 nos bits
CCP1M3:CCP1M0 (CCP1CON<3:0>)

Ex: Gerando um sinal PWM na saída P1A(RC2) através do módulo CCP1, o sinal
gerado terá frequência de 20kHz e duty cycle de 25us (50% do ciclo ativo). O tipo do
PWM será ativo em nível alto. (Obs: Fosc = 20MHz)

#include "lib.h"

void Inic_Regs (void) // Função que inicializa os registradores


{
TRISA = 0x00; // PORTA saída
TRISB = 0x00; // PORTB saída
TRISC = 0x00; // PORTC saída
TRISD = 0x00; // PORTD saída
TRISE = 0x00; // PORTE saída

ADCON1 = 0x0F; // Define todos pinos como digitais

PORTA = 0; // Limpa PORTA


PORTB = 0; // Limpa PORTB
PORTC = 0; // Limpa PORTC
PORTD = 0; // Limpa PORTD
PORTE = 0; // Limpa PORTE
}

void config_pwm(void)
{

T2CON = 0b00000100; //Postscaler 1:1; Liga Modulo Timer 2; Prescaler 1:1


PR2 = 249; // Define uma frequência de sinal PWM de 20KHz(T=50us)
CCP1CON = 0b00001100 ; // Saída única P1A; 00 como bits menos
significativos dos 10 bits que são somados ao
CCPR1L; define P1A como ativa em nível alto
CCPR1L =0b01111101 ; // 0111110100 equivale a 500 para se obter
um ciclo ativo de 25us (50% do período total), observe
que os últimos 2 bits do número estão configurados
em
CCP1CON
}

void main (void) // Função principal


{
Inic_Regs (); // invoca a função de inicialização dos registradores
config_pwm(); // invoca a função pwm criada
// ativa a porta RC2 para gerar o sinal PWM
}

Outra maneira de fazer este mesmo programa será mostrado a seguir:

Obs: Colocaremos valores numéricos em vez de valores binários no registrador de


10 bits (CCPR1L+DC1B1:DC1B0) isso pode facilitar na hora de mudar os ajustes de
PWM constantemente

A seguinte função altera o ciclo ativo do PWM:

void DutyCycle_PWM(unsigned int valor) // já declara a variável valor como


retorno
//da função
{
CCP1CONbits.DC1B0 = valor;
CCP1CONbits.DC1B1 = valor >> 1;
CCPR1L = valor >> 2;
}
A seguinte função altera o período do PWM:

void Periodo_PWM(unsigned int period)


{
T2CON = xxxxxxx;
PR2 = period;
}
Podemos alterar o ciclo ativo e período do nosso PWM da seguinte forma:

DutyCycle_PWM ();
Periodo_PWM();

O código completo é mostrado a seguir:

#include "lib.h"

void Inic_Regs (void) // Função que inicializa os registradores


{
TRISA = 0x00; // PORTA saída
TRISB = 0x00; // PORTB saída
TRISC = 0x00; // PORTC saída
TRISD = 0x00; // PORTD saída
TRISE = 0x00; // PORTE saída

ADCON1 = 0x0F; // Define todos pinos como digitais

PORTA = 0; // Limpa PORTA


PORTB = 0; // Limpa PORTB
PORTC = 0; // Limpa PORTC
PORTD = 0; // Limpa PORTD
PORTE = 0; // Limpa PORTE
}

void Inicializa_PWM(void)
{
CCP1CON = 0b00001100 ;
T2CON = 0b00000100;
}

void DutyCycle_PWM(unsigned int valor)


{
CCP1CONbits.DC1B0 = valor;
CCP1CONbits.DC1B1 = valor >> 1;
CCPR1L = valor >> 2;
}

void Periodo_PWM(unsigned int period)


{
PR2 = period;
}

void main (void)


{
Inic_Regs ();
Inicializa_PWM();
Periodo_PWM(249); // O valor dentro dos parênteses deve ser :

// PR2 = [Fosc / (FPWM x 4 x Prescaler_do_timer2) ] - 1

DutyCycle_PWM(500); // O valor dentro dos parênteses deve ser :

// (CCPR1L+DC1B1:DC1B0)=PWM(ciclo ativo) /[(1/Fosc) x Prescaler_do_timer2]

Você também pode gostar