Generar señal pwm en pic18f4550

soy nuevo en el tema de los micro y muy poco se sobre el tema... estoy buscando información de como genera un señal pwm con el pic 16f877a con dos pulsadores uno que incremente la señal y otro que disminuya.
Mira los ejemplos que adjunto, uno es sencillo con sólo los push buttons y el otro con una pantalla.
La pantalla la usé únicamente para mostrar el valor del ciclo activo.
El programa fue probado con un LED y se realizó para controlar el brillo en 20 pasos.
Puedes modificarlo para otros pasos cambiando el factor de división basado en 512.

Suerte.
 

Adjuntos

  • 16F877A PWM con Push Buttons.rar
    65.6 KB · Visitas: 86
D@rkbytes.
Quisiera saber como modificar tu programa para con el pulsador de incremento, sin soltar, encienda el led pero poco a poco, y con el decremento, sin soltar, se vaya apagando poco a poco.
Cuando pruebo tu circuito y conecto un led a la salida, el led enciende y se apaga tan rápido, pero el pulso del pwm aparece en el osciloscopio un momento y luego se va. ¿Qué tengo que modificar?

Gracias por tu aporte. :)
 
Última edición por un moderador:
D@rkbytes.
Quisiera saber como modificar tu programa para con el pulsador de incremento, sin soltar, encienda el led pero poco a poco, y con el decremento, sin soltar, se vaya apagando poco a poco.
Cuando pruebo tu circuito y conecto un led a la salida, el led enciende y se apaga tan rápido, pero el pulso del pwm aparece en el osciloscopio un momento y luego se va. ¿Qué tengo que modificar?

Gracias por tu aporte. :)
Eso es normal en la simulación porque trabajar con PWM consume muchos recursos en ISIS.
Si pruebas el circuito físicamente verás que funciona bien en 20 pasos y en el osciloscopio no se pierde la señal.
En esos ejemplos el ciclo activo está inicialmente a la mitad para que el LED tenga media iluminación.

Si quieres que el LED empiece apagado y tenga una iluminación uniforme conforme se va incrementando el ciclo activo, está es la modificación.
Si no quieres usar la pantalla, tan sólo elimina las instrucciones para ella.
Código:
#include <16f877a.h>
#use delay(crystal = 4MHz)
#include <lcd.c>

void main(void){
int16 duty = 0;

   setup_ccp1(ccp_pwm);                   // Módulo CCP1 en modo PWM
   setup_timer_2(T2_DIV_BY_1,127,1);      // Configurar el TMR2
   lcd_init();                            // Inicializar la pantalla
   lcd_putc("\fPWM con Push Btn\nValor:"); // 
   
   while(true){

      if(!input(pin_a1)){
      delay_ms(50);
      duty -=1;                           // Decrementar el ciclo activo
      if(duty > 512){duty = 0;}           // No permitir que de <0 pase a 65535
      }
      
      if(!input(pin_a0)){
      delay_ms(50);
      duty +=1;                           // Incrementar el ciclo activo
      if(duty > 512){duty = 512;}         // No permitir que suba a más de 512
      }
      lcd_gotoxy(8,2);                    // Ir a la posición 8 de la línea 2 
      printf(lcd_putc,"%04lu",duty);      // Mostrar el valor del ciclo activo
      
      set_pwm1_duty(duty);                // Establecer el ciclo ativo del PWM
   }
}
Suerte.
 
Buenos días. Estoy realizando un proyecto y debo variar el ciclo de trabajo con una frecuencia fija por medio del PIC18F4550 y mostrar en LCD los datos de la variación.
Hasta ahora pude realizar lo de la configuración del puerto serial con unos archivos que me brindaron en pdf.

No sé que más puedo hacer, porque lo compilo en proteus y no me hace nada .
PHP:
#include <18f4550.h>
#fuses HSPLL,NOWDT,NOPROTECT,
#fuses NOLVP,NODEBUG, NOBROWNOUT
#fuses USBDIV,PLL5,CPUDIV1,VREGEN,
#fuses PUT,MCLR
#use delay(clock = 48M)
#define use_portd_lcd_TRUE
#include <lcd.c>
#include "sfr_4550.h"
#include <stdlib.h>
//#include "usb_bootlloader.h"
#use rs232(BAUD=1200,XMIT=PIN_C6,RCV=PIN_C7,BITS=8,PARITY=n)

#define enter 0x0d
#define null 0x00
#bit led1=latb.0
#bit led2=latb.1
//pr2=74
//frecuencia =10khz
int x; //ccpr1l
int porcentaje;
int1 Datos_listos;
int8 i,opcion,dato,pwm; // indice del buffer
char buffer[5];
int16 valor;
void main(){
trisb=0b00000000;
trisc=0b11111011;
 lcd_init(); //Configuración de LCD
 setup_timer_2(t2_div_by_16,74,1); //Configuración de Timer
 setup_ccp1(ccp_pwm); //Configuración PWM
 set_pwm1_duty(x);
 //Configuración de Puertos
//Configuración de USB

  x=porcentaje*(74+1)/100; //Inicialización de Variables
  i = 0; // índice o puntero igual a cero
   Datos_listos = 0; // buffer lleno

 while(true){
 // Lectura de datos por el puerto Serial
  if( kbhit() ){ // hay datos recibidos?
 dato = getc();
  if(dato == enter){
 buffer[i] = null;

 Datos_listos = 1;
 }

 else{
 buffer[i] = dato;
 i++;
 putc(dato); // envía el dato de nuevo (eco).
 }
 }
 //Reconocimiento de opciones y Valores
 if (Datos_Listos == 1){
 // lee opiones y valores enviados por el usuario
 pwm = Buffer[0];
 porcentaje = atoi(buffer+1);

 Datos_listos = 0;

 i = 0;
 } 
 //Aquí se escribe el código de cada ejercicio
if (x>70){
led1=1;
}
else {
led1=0;
 }
 if(x<30){
 led2=1;
 }else{
 led2=0;
 }
 
 
 // finwhile
 }
}//Fin Main
 
Hasta ahora pude realizar lo de la configuración del puerto serial con unos archivos que me brindaron en pdf.
A 48 MHz. del oscilador principal, 1200 Bps es un baudrate muy bajo.
Con esa frecuencia puedes usar un baurate más alto, que será más conveniente.
Para configurar el módulo EUSART, lo puedes hacer de forma muy sencilla:
Por ejemplo, para configurarlo a 9600 Bps. (Por defecto):
#use RS232 (UART1)
Con tan sólo declarar eso, ya tendrás configurado el módulo EUSART a; 9600 Bps, 8 Bits, Sin paridad, y 1 Bit de parada.

Se usarán los pines Tx y Rx correspondientes al módulo, sin necesidad de declararlos.
Para otros baudrates, sería así:
#use RS232 (UART1, BAUD = XXXX)
Y puedes agregar opciones extra, que encontrarás en el documento de ayuda del compilador.

La palabra de configuración para que el oscilador principal funcione a 48 MHz, no es correcta.
Para que funcione a 48 MHz, puedes también configurarlo de forma sencilla. (Sin declarar tantos FUSES)
#fuses NOFCMEN
#use delay(crystal = 4MHz, clock = 48MHz)
Con esas declaraciones el oscilador funcionará a 48 MHz, usando un cristal de 4 MHz.
No sé que más puedo hacer, porque lo compilo en proteus y no me hace nada .
Revisa bien tu programa y verás por qué no funciona. (Parte referente al PWM)
Asignas un valor para el registro PR2, de 74. (Ciclo activo al 100 % Frec. = 10 KHz. Fosc = 48 MHz.)
Pero usas la variable "x" para asignar el ciclo activo, la cual tiene un valor de 0, ya que no está inicializada.
La variable "x" toma un valor después, en: (x=porcentaje*(74+1)/100; //Inicialización de Variables)
Por lo tanto, el módulo CCP1, no mostrará señal de salida alguna, aunque esté configurado.

Algo más:
No es necesario que uses un archivo con los registros FSR declarados, ya que PIC C Compiler tiene instrucciones nativas con las que puedes controlar los puertos y otras funciones del PIC.
Lo que te hace falta es estudiar más el compilador y tener en cuenta la sucesión de eventos.

Nota:
Simular a 48 MHz, produce una carga excesiva para el simulador.
Para simular, usa frecuencias bajas. Con 1MHz, 4 MHz u 8 MHz. Te irá bien la simulación.
Puedes crear rutinas para el modo de simulación y modo físico, que puedes separar y ejecutar por medio de sentencias. (Por ejemplo: #IFDEF)
 
Última edición:
Saludos.

Prueba ahora así...
Código:
#include <18F4550.h>
#device adc=8
#fuses hs,nowdt,noprotect,nolvp
#use delay(clock=20000000)
#use fast_io(A)
#use fast_io(B)
#use fast_io(C)

unsigned int8 velocidad;


void inicializar()
{
   setup_ccp2(CCP_PWM);
   setup_timer_2(T2_DIV_BY_4, 127, 1);

   set_tris_c(0xFD);
   set_tris_a(0x01);
   setup_adc(adc_clock_internal);
   delay_us(12);
   setup_adc_ports(AN0);
   set_adc_channel(0);

   velocidad=0;
}

void main(){
   inicializar();
   
   while(true){

   velocidad=read_adc();
   delay_us(12);

   set_pwm2_duty(velocidad/2);
   }
}
Suerte.
que debo cambiar en ese codigo para que funcione a 10 bits ???
 
Cambiar #device adc = 8
Por #device adc = 10

Usar una variable de 16 bits; int16 para la lectura del ADC y cambiar la configuración del Timer 2.
 
Atrás
Arriba