Ir ao conteúdo

Código para usar o PWM do PIC16F628A, como fazer?


Agricio

Posts recomendados

Postado

Pessoal da programação

Saudações a todos.

Como candidato a auxiliar de aprendiz em programação, tenho tentado faz muito tempo aproveitar a frequência PWM de 4,88Khz que o PIC16F628A fornece via portb3 (CCP1) no pino 9 do mesmo para fazer um circuito uP e down (direto e escalonado)

Esse PIC fornece 6 frequências diferentes de PWM e essa de 4,88KHz é ideal para o que preciso.

A finalidade é controlar a rotação de motores de alta potência (±2HP) de 90 volts da seguinte forma.

Segurando a tecla uP a rotação sobe lentamente até o máximo.

Apertando e soltando a tecla uP a rotação dá um aumento e para e assim gradativamente até o máximo.

O mesmo tem que acontecer do máximo até o mínimo.

Como eu não conseguí em BASIC pelo PSI eu me aventurei a fazer em C usando o MPLAB, mas só dá erro. (Ainda não aprendí a usar o MPLAB direito)

O código é esse:

#include < 16f628a.h >
#use delay(clock = 10000000)
#fuses nomclr, noprotect, nowdt, intrc_io, nobrownout

#use fast_io(ab)

#define tecla_up pin_a7 ;//
#define tecla_down pin_a6
#define saida_pwm pin_b3
#define para pin_a5

Long ciclo; //Define o tempo do ciclo ativo
Long ciclo_aux; //Varável ausiliar
Long loop; // tempo de resposta das teclas

void configura_micro()
{
setup_wdt(0);
setup_timer_2(rtcc_internal rtcc_div_64) ;
port_a_pullups(true);
port_b_pullups(true);
set_tris_a(11111111b)
set_tris_b(00000000b)
}
#int_timer2
void trata_t2()
{
ciclo_aux = ciclo;
while(ciclo_aux - -)
{
output_high(saida_pwm);
}
output_low(saida_pwm);
}
main(0)
{
configura_micro();
enable_interrupts(global : int_timer2);
ciclo = 5;
while(true)
{
if(loop = = 0)
{
if(!input(tecla_up))
{
ciclo + + ;
if(ciclo >= 1250) = 1250;
}
if(!input(tecla_down))
{
ciclo - -;
if(ciclo <= 5) ciclo = 5;
}
loop = 200; // aumentando ou diminuindo a
}
loop - -;
}

Agricio

Postado

Pode tentar adaptar esse aqui amigo:

#include <16F628a.h> //Microcontrolador utilizado
#fuses hs,nowdt,noprotect,put,brownout,mclr,nolvp,nocpd
#use delay(clock=8000000,RESTART_WDT)

// Constante para o uso dos botões
#define t_filtro 400
#define mim 0
#define max 10

// Variáveis globais
long int filtro1 = t_filtro; // Filtro do botão 1 (Incremento Vermelho)
long int filtro2 = t_filtro; // Filtro do botão 2 (Decremento Vermelho)
long int filtro3 = t_filtro; // Filtro do botão 3 (Incremento Verde)
long int filtro4 = t_filtro; // Filtro do botão 4 (Decremento Verde)
long int filtro5 = t_filtro; // Filtro do botão 5 (Incremento Azul)
long int filtro6 = t_filtro; // Filtro do botão 6 (Decremento Azul)
int flags = 0; // Flags de controle dos botões
int contador_red = 0; // Contador do perÃ*odo para o LED vermelho
int contador_green = 0; // Contador do perÃ*odo para o LED verde
int contador_blue = 0; // Contador do perÃ*odo para o LED azul
int pwm_red = 0; // Duty Cicle para o LED Vermelho
int pwm_green = 0; // Duty Cicle para o LED Verde
int pwm_blue = 0; // Duty Cicle para o LED Azul

// Definição dos flags de software
#bit botao_red_up_press = flags.0 // Marca se o botão 1 está pressionado
#bit botao_red_down_press = flags.1 // Marca se o botão 2 está pressionado
#bit botao_green_up_press = flags.2 // Marca se o botão 3 está pressionado
#bit botao_green_down_press = flags.3 // Marca se o botão 4 está pressionado
#bit botao_blue_up_press = flags.4 // Marca se o botão 5 está pressionado
#bit botao_blue_down_press = flags.5 // Marca se o botão 6 está pressionado

//Definição e inicialização dos port's
#use fast_io(a)
#use fast_io(
#byte porta = 0x05
#byte portb = 0x06

// Entradas para o microcontrolador
#bit botao1 = porta.2
#bit botao2 = porta.3
#bit botao3 = porta.0
#bit botao4 = porta.1
#bit botao5 = portb.4
#bit botao6 = portb.5

void main()
{
// Inicialização dos pinos de I/O
set_tris_a(0b11101111); //Configuração dos pinos de I/O para o PORTA
set_tris_b(0b11111000); //Configuração dos pinos de I/O para o PORTB

// Inicialização do TIMER0
setup_timer_0(RTCC_INTERNAL);
setup_wdt(WDT_2304MS);

// Inicialização do timer1
// Ele servirá para gerar o "passo" do PWM
setup_timer_1(T1_INTERNAL | T1_DIV_BY_1);

// Inicialização do TIMER2
// Ele deve estourar a cada 10ms para gerar um PWM de 100Hz Para efeito de visualização do LED,
// esta freqüência é suficiente para garantir o efeito de persistência da visão.
setup_timer_2(T2_DIV_BY_16,78,16);

// Inicialização das interrupções
enable_interrupts(INT_TIMER1); //Habilita a interrupção de overflow do timer1
enable_interrupts(INT_TIMER2); //Habilita a interrupção de overflow do timer2
enable_interrupts(GLOBAL); //Habilita as interrupções globais (GIE)
#priority timer1, timer2 // Define a prioridade das interrupções

// Limpeza dos PORTs
porta=0x00; //Limpa porta
portb=0x00; //Limpa portb

while(true) //Loop infinito que garante a funcionalidade do uC
{
RESTART_WDT(); // Limpa o Watch Dog timer

//Comandos para o PWM
// Assim que o valor do contador para um LEDs se equiparar ao estabelecido para o seu perÃ*odo,
// desligue o LED (nÃ*vel lógico 0)
if (contador_red >= pwm_red) output_low(pin_B0);
if (contador_green >= pwm_green) output_low(pin_B1);
if (contador_blue >= pwm_blue) output_low(pin_B2);

// Comandos para o botão 1 (RED_UP)
if (!botao1)
{
if (!botao_red_up_press)
{
if (filtro1 != 0) filtro1--;
else
{
botao_red_up_press = 1;
if (pwm_red != max) pwm_red++;
}
}
}
else
{
filtro1 = t_filtro;
botao_red_up_press = 0;
}


// Comandos para o botão 2 (RED_DOWN)
if (!botao2)
{
if (!botao_red_down_press)
{
if (filtro2 != 0) filtro2--;
else
{
botao_red_down_press = 1;
if (pwm_red != mim) pwm_red--;
}
}
}
else
{
filtro2 = t_filtro;
botao_red_down_press = 0;
}


// Comandos para o botão 3 (GREEN_UP)
if (!botao3)
{
if (!botao_green_up_press)
{
if (filtro3 != 0) filtro3--;
else
{
botao_green_up_press = 1;
if (pwm_green != max) pwm_green++;
}
}
}
else
{
filtro3 = t_filtro;
botao_green_up_press = 0;
}


// Comandos para o botão 4 (GREEN_DOWN)
if (!botao4)
{
if (!botao_green_down_press)
{
if (filtro4 != 0) filtro4--;
else
{
botao_green_down_press = 1;
if (pwm_green != mim) pwm_green--;
}
}
}
else
{
filtro4 = t_filtro;
botao_green_down_press = 0;
}


// Comandos para o botão 5 (BLUE_UP)
if (!botao5)
{
if (!botao_blue_up_press)
{
if (filtro5 != 0) filtro5--;
else
{
botao_blue_up_press = 1;
if (pwm_blue != max) pwm_blue++;
}
}
}
else
{
filtro5 = t_filtro;
botao_blue_up_press = 0;
}


// Comandos para o botão 6 (BLUE_DOWN)
if (!botao6)
{
if (!botao_blue_down_press)
{
if (filtro6 != 0) filtro6--;
else
{
botao_blue_down_press = 1;
if (pwm_blue != mim) pwm_blue--;
}
}
}
else
{
filtro6 = t_filtro;
botao_blue_down_press = 0;
}

} // Fim do while(true)
} // Fim do programa


// Aqui entra a configuração da função de interrupção do TIMER1 (quando ele "estoura").
#int_TIMER1
void TIMER1_isr()
{
contador_red++;
contador_green++;
contador_blue++;
set_timer1(63535); // O TIMER1 vai estourar a cada 1,0ms
}

//Aqui entra a configuração da função de interrupção do TIMER2 (quando ele "estoura").
#int_TIMER2
void TIMER2_isr()
{
if(pwm_red != 0) output_high(pin_B0); // LED RED
if(pwm_green != 0) output_high(pin_B1); // LED GREEN
if(pwm_blue != 0) output_high(pin_B2); // LED BLUE
contador_red = 0;
contador_green = 0;
contador_blue = 0;
set_timer1(63535); // O TIMER1 vai estourar a cada 1,0ms
}

Postado

Jorge, a diferença de:

 // Ele deve estourar a cada 10ms para gerar um PWM de 100Hz

para:

Esse PIC fornece 6 frequências diferentes de PWM e essa de 4,88KHz é ideal para o que preciso.

é muito grande e segundo o datasheet esse esse PIC nem fornece essa frequência de 100HZ

Veja aí a tabela:

PWM Frequency 1.22 kHz 4.88 kHz 19.53 kHz 78.12 kHz 156.3 kHz 208.3 kHz

Eu entendo só um pouquinho de BASIC pelo PSI. Aquele codigo que eu postei acima em C, já foi adaptação de outros códigos que encontrei e fui modificando até ficar aquilo lá.

Obrigado amigo

Postado

Se o problema é gerar um pwm com frequencia de 100hz é possivel sim. Já usei pra gerar até 50 Hz, a tabela mostra apenas exemplos de frequencias possiveis. Para conseguir a frequencia exata você tem que usar a fórmula que ele da no datasheet:

PWM period = [(PR2) + 1] ⋅ 4 ⋅ Tosc ⋅ TMR2 prescale

value

Como a Freq = 1/ periodo, você acha o periodo correspondente (10 ms para 100 Hz) e ajusta os parametros. Sugiro utilizar um cristal com frequencia bem baixa tipo 120 Khz ou algo próximo, e usar o prescale do Timer 2 no máximo que é 16 (Configuravel pelo seu registrador T2CON).

Espero ter ajudado.

Postado

Matheus

A frequência que eu preciso é de 4,88KHz e não 100Hz e pelo que eu entendí pelo datasheet a frequência PWM mínima gerada pelo PIC16F628 é de 1,22KHz. Me parece ser uma tabela já predefinida pelo fabricante.

Encontrei um manual do MIKROC em português e estou dando uma estudada. Parece que vou chegar lá.

Obrigado amigo

Postado

Agricio, na pagina 60 do datasheet você vai encontrar a fórmula que coloquei. Não existe frequencia minima estabelecida pelo fabricante, a frequencia depende do timer 2, e pode ser definida pelo ajustes do parametro da fórmula. Faz tempo que não uso o mikroc, mais o próprio help dele vem explicando a função pwm deles. Só que no caso o valor que eles configura dentro da função acho que é o "PR2" que vai na fórmula, os outros você tem que configurar separadamente, se não me engano.

Arquivado

Este tópico foi arquivado e está fechado para novas respostas.

Sobre o Clube do Hardware

No ar desde 1996, o Clube do Hardware é uma das maiores, mais antigas e mais respeitadas comunidades sobre tecnologia do Brasil. Leia mais

Direitos autorais

Não permitimos a cópia ou reprodução do conteúdo do nosso site, fórum, newsletters e redes sociais, mesmo citando-se a fonte. Leia mais

×
×
  • Criar novo...

LANÇAMENTO!

eletronica2025-popup.jpg


CLIQUE AQUI E BAIXE AGORA MESMO!