Fork me on GitHub

24/02/13

Tutorial 7: Configuração do PWM

Configuração do PWM



Criei este post para mostrar a vocês como funciona o PWM do PIC. Ao invés de usas aquelas funções do MikroC ou CCS, vocês também podem gerar sinais de PWM apenas configurando os registros. É muito simples.

Para gerar um sinal PWM com o PIC, nós utilizamos o TIMER2 que é um timer de 8 bits. O TIMER2 é usado como base de tempo para a modulação PWM com o módulo CCP(compare/capture/pwm).

Período do PWM
O período do PWM é especificado pelo registro PR2. Pode ser calculado pela seguinte fórmula:

P = (PR2 + 1) * 4 * Tosc * Prescaler

Tosc = 1 / Freq do oscilador


Duty Cycle do PWM
O duty cycle é configurado usando 10 bits: 8 MSB do registro CCPR1L e 2 adicionais LSB. O resultado é um número de 10 bits, presente na fórmula:

DutyCycle = CCP1L * Tosc * Prescaler


Exemplo: Calcular a frequência e duty cycle, sendo que o cristal é de 20 MHz, prescaler 1:16, PR2= 255, CCPR1L=100.

P = (255 + 1) * 4 * 0,05us * 16;
P = 819,2 us
Freq = 1/P = 1/819,2 = 0,0012207 MHz = 1,22 KHz

                  
DutyCycle = (CCP1L << 2) * Tosc * Prescaler
DutyCycle = (100 * 4) * 0,05us * 1
DutyCycle = 400 * 0,05 * 16 = 320us
DutyCycle(%) = 320us / 819,2us * 100 = 39,06%


Veja, que foi necessário deslocar CCP1L (8bits) para podermos ter 10 bits. Deslocar dois bits para esquerda é a mesma coisa que multiplicar por 4.

LEMBRE-SE: O valor de PR2 deve ser maior que o valor de CCPR1L
 




Observe que no caso do PIC16F877A existem 2 canais PWM.



Operação para a configuração:
1 - Define o periodo escrevendo o valor de PR2
2 - Define o duty cycle escrevendo o valor de CCPRxL
3 - Define pino RC2(canal 1) ou RC1(canal 2) como saída
4 - Define o valor do prescaler, bits 1 e 0 do registro T2CON.
00 = prescaler 1:1
01 = prescaler 1:4
1x = prescaler 1:16
5 - Habilitar o timer2, setando o bit TMR2ON do registro T2CON
6 - Configure o modulo CCP1(ou CCP2) no modo PWM, setando o bit 3 e 2 do registro CCPxCON

EXEMPLO:
//EXEMPLO UTILIZANDO O CANAL 1
void main()
{
//define periodo
PR2 = 200;
//define duty cycle
CCPR1L = 50;
//define rc2 como saida
TRISC.RC2 = 0;
//prescaler 1:1
T2CON.T2CKPS1=0;
T2CON.T2CKPS0=0;
//habilitar TIMER2
T2CON.TMR2ON=1;
//configurar modo PWM
CCP1CON.CCP1M3=1;
CCP1CON.CCP1M2=1;

while(1);
}


Usando os valores acima e utilizando um cristal de 20MHz, a frequência e o duty cycle será:

Tosc = 1/20 = 0,05us

P = (200 + 1) * 4 * 0,05us * 1
P = 40,2 us
Freq = 1 / P = 1/40,2 = 0,02487 MHz = 24,87 KHz



DutyCycle = (50 * 4) * 0,05us * 1
DutyCycle = 200 * 0,05 * 1 = 10 us
DutyCycle(%) = 10us / 40,2us * 100 = 24,90%

19 comentários:

  1. Fantástica as explicações do Blog, esta sobre PWM me auxilou. Mais uma vez dou os parabéns pela didática e por usar a lógica com registradores, sem apelar para o uso de funções de biblioteca, assim fica tudo muito mais interessante de se aprender e entender. Abraços.

    ResponderExcluir
  2. Olá, não é bem o mesmo assunto mas estou com dificuldade em configurar a habilitação da interrupção do CCP (CCPxIE bit), vc poderia me dar uma dica? Estou tentando usar o modo Captura do pic 18f4520.

    ResponderExcluir
    Respostas
    1. Jovem, Porque o PR2 deve ser maior que o CCPR1L ? Seria pelo PWM trabalhar com 10 bits ? Grato.

      Excluir
    2. Sempre que (TMR2 = PR2), TMR2 é resetado. Então se o valor de PR2 for menor, o TMR2 nunca será comparado com CCPR1L e assim não terá um sinal de PWM.

      Excluir
    3. ' Cara, manjei da parada. rsrs Muito grato mesmo. Abraço.

      Excluir
  3. Amigo.... como fica a configuração para o 18f4550?

    ResponderExcluir
  4. Ola . Como devo configurar o registrador do pwm para teabalhar com 10bits. Pois quero capturar o sinal do conversor ad (10bits) e colocar no Pwm

    ResponderExcluir
    Respostas
    1. tem que salvar os 8 bits mais significativos do conversor AD para o CCPR1L.
      O jeito mais simples seria:
      Configurar os bits de saida do AD justificado para esquerda -> ADCON1.ADFM = 0;
      passar o valor de ADRESH para CCPR1L -> CCPR1L = ADRESH;

      Excluir
  5. Obrigado pela dica.
    Ok mais desse jeito estou utilizando apenas 8 bits, e os outros 2 bits do ADRESL preciso colocá-los no CCP1CON <5:4>? como faço isso .

    Desde já agradeço

    ResponderExcluir
    Respostas
    1. Esse dois bits são insignificantes, mas se quiser colocar, faça isso:
      CCP1CON.B5 = ADRESL.B7;
      CCP1CON.B4 = ADRESL.B6;

      Excluir
  6. PPergunta :

    DutyCycle = (CCP1L << 2) * Tosc * Prescaler
    DutyCycle = (100 * 4) * 0,05us * 16
    DutyCycle = 400 * 0,05 * 16 = 320us
    DutyCycle(%) = 320us / 819,2us * 100 = 39,06%


    Veja, que foi necessário deslocar CCP1L (8bits) para podermos ter 10 bits. Deslocar dois bits para esquerda é a mesma coisa que multiplicar por 4.

    E se nós deslocarmos 2 bits para a direita, seria uma divisão por 4? isso mesmo?

    ResponderExcluir
  7. Estou tentando utilizar esse algoritmo no PIC18F46K80 e não está funcionando, sabe me dizer porque?

    ResponderExcluir
  8. É possivel termos dois sinais de pwm no PIC 16f877?ou seja, CCP1=10Khz e CCP2= 6Khz

    ResponderExcluir
  9. Como ter baixa frequencia de pwm no pic? posso usar postscaler?
    Gostaria de usar uma freq de 500Hz.

    ResponderExcluir
  10. Gostei do post. Mas eu tentei trabalhar com os 10 bits do pwm, quero ter uma precisão maior. Meu programa ficou assim, mas não funcionou. Estou usando o 18f4550:

    void pwm1(int pwm1){
    int x;
    int y;

    //Setar a frequência por pr2
    pr2 = 312;
    // Parte para dar o valor do pwm
    x = pmw1/4;
    y = pwm%4;
    // Registrador dos 8 bits mais //importantes

    ccpr1l = x;
    // registrador dos 2 bits menos importantes
    ccp1con.f5 = y/2;
    ccp1con.f4 = y - (2*ccp1con.f5);

    //Setar como saída digital
    trisc.f2 = 0;

    // setar o prescaler no timer 2

    t2con.f2 = 0;
    t2con.f1 = 1;

    // Configurar o ccpqcon para ser pwm

    ccp1con.f3 = 1;
    ccp1con.f2 = 1;

    }

    Eu utilizei o micro c e rodei no proteus. E não tem resposta no osciloscópio. Me ajuda favor.

    ResponderExcluir

Postagens Relacionadas!!