Autor Tema: Principiante necesita ayuda con PWM (PIC 16F628A)  (Leído 5384 veces)

0 Usuarios y 1 Visitante están viendo este tema.

Desconectado gacanepa

  • PIC10
  • *
  • Mensajes: 4
Principiante necesita ayuda con PWM (PIC 16F628A)
« en: 25 de Julio de 2011, 08:45:24 »
Estimados,
Recurro a ustedes esperando que alguien tenga a bien echarle una mirada al código que les adjunto a continuación. Se trata de un proyecto para controlar el ancho de pulso de salida mediante PWM, utilizando el PIC 16F628A. El código está (creo yo) bastante comentado para que se entienda paso a paso lo que trato de hacer. La simulación con Proteus resultó exitosa, por lo que casi daba por sentado que después de programar el PIC e insertarlo en el circuito todo iba a salir andando (en el esquemático no se ve, pero a la salida, en lugar del osciloscopio, tengo un LED -obvio, con una resistencia limitadora- para detectar la variación del ancho de pulso a partir de los cambios en su luminosidad).
Tengo la certeza de que el microcontrolador está en buen estado y lo mismo el programador PICKit2 ya que después probé con un circuito más simple (LED parpadeante) y todo funcionó a la perfección.
Otro detalle: el programa está escrito en .asm, y el .hex lo cargo desde MPLAB luego de compilar el original.
Espero que alguien pueda aportar algo. Los saludo cordialmente desde Villa Mercedes, San Luis, Argentina!
Código: [Seleccionar]
;************************************************************************************************
;                                                                                               *
;                                  Microcontrolador PIC16F628A                                  *
;                                            ____ ____                                          *
;                             VREF/AN2/RA2 -| 1  - 18 |- RA1/AN1                                *
;                       LED - CPM1/AN3/RA3 -| 2    17 |- RA0/AN0                                *
;                           CMP2/T0CKI/RA4 -| 3    16 |- RA7/OSC1/CLKIN                         *
;                             VPP/MCLR/RA5 -| 4    15 |- RA6/OSC2/CLKOUT                        *
;                                      VSS -| 5    14 |- VDD                                    *
;                                  INT/RB0 -| 6    13 |- RB7/T1OSC1/ICSPDAT                     *
;                                DT/RX/RB1 -| 7    12 |- RB6/T1OSCO/T1CLKI/ICSPCLK              *
;                                CK/TX/RB2 -| 8    11 |- RB5                                    *
;                                 CCP1/RB3 -|_9____10_|- RB4/PGM                                *
;                                                                                               *
;                                                                                               *
;************************************************************************************************

list p=16f628a
radix hex
include "p16f628a.inc"

__config        _CP_OFF & _DATA_CP_OFF & _LVP_OFF & _BODEN_OFF & _MCLRE_ON & _PWRTE_ON & _WDT_OFF & _INTOSC_OSC_NOCLKOUT

org 00h ;Al resetear el PIC se va a la subrutina de INICIO (goto INICIO)

AuxTotal EQU 021h ;Variable auxiliar en la que se almacenará el valor máximo de Duty Cycle permitido.

goto INICIO

org 4 ;Dirección a donde se dirigen las interrupciones
goto ISR_PB

CONF_PUERTOS
clrf PORTB ;Inicializo el puerto B
bsf STATUS,RP0 ;Paso al banco 1, donde se encuentra el registro TRISB
movlw b'10100000' ;Cargo el dato binario en W para luego trasladarlo a TRISB
movwf TRISB
bcf STATUS,RP0 ;Vuelvo al banco 0, para trabajar con el registro INTCON,
;el que contiene los bits de banderas y de habilitación de
;todas las fuentes de interrupción con excepción del
;módulo comparador.
bcf INTCON,RBIF ;RBIF es el bit correspondiente a la bandera de interrupción
;por cambios en el puerto B. Al ponerlo en 0, indicará que
;al momento de ejecutarse el programa ninguno de los bits
;RB<7:4> (PORTB bits 4 al 7 inclusive) ha cambiado de estado.
bsf INTCON,RBIE ;RBIE es el bit que habilita/deshabilita las interrupciones
;por cambios en el puerto B.
return ;Regresa de la subrutina actual y continúa ejecutando la
;instrucción siguiente a call CONF_PUERTOS.

CONF_CCP1
movlw 0FCh ;Período de la señal (aprox. 4 ms), se copia a W para luego trasladar
;al registro PR2 (en el banco 1).
;PWM Period=[(PR2)+1]*4*Tosc*PrescaladorTMR2
bsf STATUS,RP0
movwf PR2
bcf STATUS,RP0 ;Se vuelve al banco 0.
movlw 7Eh ;Duty cycle inicial (50%), se carga en W para luego trasladar
;al registro CCPR1L, encargado de controlar el ciclo de trabajo
;(junto al registro CCP1CON).
;PWM Duty Cycle=(CCPR1L:CCP1CON<5:4>)*Tosc*PrescaladorTMR2
movwf CCPR1L
bsf STATUS,RP0 ;Paso al banco 1
bcf TRISB,3 ;Inicializo RB3 como salida
bcf STATUS,RP0 ;Vuelvo al banco 0.
movlw b'00111100' ;Termino de configurar el Duty Cycle y configuro el registro
;CCP1 para trabajar como PWM.
movwf CCP1CON
movlw b'00000111' ;Se inicializa el Timer 2 y se pone un Prescalador = 16,
;al copiar el dato binario en el registro T2CON.
movwf T2CON
return ;Regresa de la subrutina actual y continúa ejecutando la
;instrucción siguiente a CALL CONF_CCP1.

ISR_PB
btfss PORTB,7 ;RB7=1? Si es así, salta una instrucción y pasa a la siguiente.
goto SIGUE
movlw 0FCh
xorwf CCPR1L,0 ;Se realiza la operación lógica XOR entre el contenido del
;W (al que se le cargó en el paso anterior el valor 252d).
;El resultado se guarda en W.
btfss STATUS,Z ;El resultado de la operación es 0? En tal caso, no aumenta más.
;De otra manera, aumenta el ciclo de trabajo en 2 unidades.
goto INCREMENTA
goto SALIR


SIGUE
btfss PORTB,5 ;RB5=1? Si es así, salta una instrucción y pasa a la siguiente.
goto SALIR
movlw b'00000000'
xorwf CCPR1L,0 ;Se realiza la operación lógica XOR entre el contenido del
;W (al que se le cargó en el paso anterior el valor 252d).
;El resultado se guarda en W.
btfss STATUS,Z ;El resultado de la operación es 0? En tal caso, no disminuye más.
goto DECREMENTA ;De otra manera, disminuye el ciclo de trabajo en 2 unidades.
goto SALIR

INCREMENTA
incf CCPR1L,f
incf CCPR1L,f
goto SALIR

DECREMENTA
decf CCPR1L,f
decf CCPR1L,f

SALIR
bcf INTCON,RBIF
retfie

INICIO
call CONF_PUERTOS
call CONF_CCP1
bsf INTCON,GIE
goto $ ;$ hace referencia a la dirección actual. goto $ implica un bucle infinito.

END
« Última modificación: 25 de Julio de 2011, 09:24:03 por gacanepa »