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).
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 * 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.
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 T2CON6 - 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%
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.
ResponderExcluirOlá, 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.
ResponderExcluirOlá, criarei um post falando sobre isto.
ExcluirJovem, Porque o PR2 deve ser maior que o CCPR1L ? Seria pelo PWM trabalhar com 10 bits ? Grato.
ExcluirSempre 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' Cara, manjei da parada. rsrs Muito grato mesmo. Abraço.
ExcluirAmigo.... como fica a configuração para o 18f4550?
ResponderExcluiré a mesma coisa...
ExcluirOla . Como devo configurar o registrador do pwm para teabalhar com 10bits. Pois quero capturar o sinal do conversor ad (10bits) e colocar no Pwm
ResponderExcluirtem que salvar os 8 bits mais significativos do conversor AD para o CCPR1L.
ExcluirO 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;
Obrigado pela dica.
ResponderExcluirOk 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
Esse dois bits são insignificantes, mas se quiser colocar, faça isso:
ExcluirCCP1CON.B5 = ADRESL.B7;
CCP1CON.B4 = ADRESL.B6;
:-a
ResponderExcluirPPergunta :
ResponderExcluirDutyCycle = (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?
Isso mesmo!!!
ExcluirEstou tentando utilizar esse algoritmo no PIC18F46K80 e não está funcionando, sabe me dizer porque?
ResponderExcluirÉ possivel termos dois sinais de pwm no PIC 16f877?ou seja, CCP1=10Khz e CCP2= 6Khz
ResponderExcluirComo ter baixa frequencia de pwm no pic? posso usar postscaler?
ResponderExcluirGostaria de usar uma freq de 500Hz.
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:
ResponderExcluirvoid 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.
Estou usando no mp lab xc8 e não consigo atingir um Duty de 100%
ResponderExcluirDeclaro pr2 = 255
E ccpr1L =255
Mas ele atinge 98.8% de Duty
Seria alguma coisa na configuração Inicial(PLLDIV, CPUDIV,USBDIV, FOSC)...