Otro pwm con pic que no sale

Que tal compañeros del foro, ya despues de un buen rato investiganto por aqui y en otros lados donde apareza "diseño de pwm con pic". Y encuentro bastante pero no puedo dar con algo que me de una solucion y el problema es que tambien yo programo en ensamblador y la mayoria de la infromacion es de programas en c, aunque es mas sencillo no entiendo bien, pero bueno, llendo al grano.

Necesito generar una onda pwm con pic variable de 1 Hz a 1 KHz y que el ciclo o duty sea siempre un septimo del periodo, algo como esto:

http://img181.imageshack.us/my.php?image=ciclopwmtb7.jpg

Despues de dos meses, aprendiendo a programar en ensamblador pude hacer algo que se le asemeja, pero el ciclo de servicio aparece de un octavo, y la frecuencia no es la que necesito

###########################################################

List p=16F877A ;Tipo de procesador
include "P16F877A.INC" ;Definiciones de registros internos

__CONFIG _CP_OFF & _WDT_OFF & _PWRTE_ON & _XT_OSC

Periodo equ 0x20 ;Variable para el periodo
Duty_H equ 0x21
Duty_L equ 0x22 ;Variable para la anchura de pulso
resta equ 0x0c


org 0x00 ;Vector de Reset
goto Inicio

org 0x05 ;Salva el vector de interrupción

;Programa principal

Inicio clrf PORTA
clrf PORTB
clrf PORTC
bsf STATUS,RP0 ;Selecciona banco 1
clrf ADCON1 ;Puerta A analógica, justificación izda.
clrf TRISB ;Puerta B se configura como salida
movlw b'00000001'
movwf TRISA ;RA0 entrada
movlw b'11111011'
movwf TRISC ;RC2/CCP1 salida
movlw b'11001101'
movwf OPTION_REG ;Preescaler de 128 asociado al WDT
bcf STATUS,RP0 ;Selecciona banco 0

;Se activa el ADC y se selecciona el canal RA0/AN0. Frecuencia de trabajo Fosc/32

Loop clrwdt
movlw b'10000001'
movwf ADCON0 ;ADC en On, seleciona canal AN0

bcf PIR1,ADIF ;Restaura el flag del conversor AD
nop
bsf ADCON0,GO ;Inicia la conversión

ADC_0 btfss PIR1,ADIF ;Fin de conversión ?
goto ADC_0 ;Todavía no

movf ADRESH,w
movwf Periodo ;Registra valor actual para el periodo
movwf resta
movwf Duty_H ;Salva parte alta de la conversión
bsf STATUS,RP0 ;Selecciona página 1
bcf STATUS,C
rrf ADRESL,F
rrf ADRESL,F
bcf STATUS,C
rrf ADRESL,W
bcf STATUS,RP0 ;Selecciona página 0
andlw b'00110000'
movwf Duty_L ;Salva parte baja de la conversión


;El módulo CCP1 se configura en modo PWM con salida por RC2/CCP1. Los bits LSB se obtienen
;de la variable Duty_L

movlw b'00001100'
iorwf Duty_L,W
movwf CCP1CON ;Modo PWM para el módulo CCP1

;El periodo se determina según el valor de la variable "Periodo". Este se carga sobre el
;registro PR2.

movf Periodo,W
bsf STATUS,RP0 ;Selecciona página 1
movwf PR2
bcf STATUS,RP0 ;Selecciona página 0

;La anchura del pulso o "Duty" se determina según el valor con que se cargue el registro
;CCPR1L concatenado con los bits 4 y 5 de CCP1CON. Dichos valores se obtiene de las varia-
;bles Duty_H y Duty_L respectivamente.

clrw
bcf STATUS,C
rrf Duty_H,F
bcf STATUS,C
rrf Duty_H,F
bcf STATUS,C ; Ciclo de servicio dividido entre 4

rrf resta,F
bcf STATUS,C
rrf resta,F
bcf STATUS,C
rrf resta,F ; Ciclo de servicio dividido entre 8
bcf STATUS,C
movf resta,W
subwf Duty_H,F ; Resta del resultado entre 4 menos resultado de /8
bcf STATUS,C
rrf Duty_H,W
movwf CCPR1L


;Trabajando con un preescaler 1:1 y a una frecuancia de 4MHz, el TMR2 evoluciona cada 1 uS.

movlw b'00000110'
movwf T2CON ;TMR2 en On
goto Loop

end ;Fin del programa fuente

############################################################

Mi compañero hizo este otro en C que se acerca mas pero la frecuencia de salida es inestable, no se puede leer la frecuencia ya aca en la practica

###########################################################

#include <16f877A.h>
#device ADC=8
#fuses NOPROTECT,NOCPD,NOLVP,NOWDT,XT
#use fast_io (A)
#use fast_io (B)
#byte resultado=0x20
#byte PORTB=0x06
#use delay(clock=4000000)

main()
{
set_tris_a(0x01);
set_tris_b(0x00);
setup_adc(adc_clock_div_32);
setup_adc_ports(AN0);
while(1)
{
set_adc_channel(0);
resultado = read_adc();
bit_set(PORTB,0);
delay_ms(resultado);
bit_clear(PORTB,0);
delay_ms(resultado);
delay_ms(resultado);
delay_ms(resultado);
delay_ms(resultado);
delay_ms(resultado);
delay_ms(resultado);
}
}
###########################################################

No hemos parado de investigar y buscar en varios sitios por algun empujoncillo que nos ayude a terminar esto, cualquier comentario o aportacion sera bien recibido, muchas gracias. :D
 

Adjuntos

  • pwm3_186.asm
    2.7 KB · Visitas: 23
Xavier dijo:
...
rrf resta,F ; Ciclo de servicio dividido entre 8
...
subwf Duty_H,F ; Resta del resultado entre 4 menos resultado de /8
...
Hola:
Creo que el problema está en que la división por 7 nunca la vas a poder
hacer con rrf. Hay que hacer una pequeña rutinita para dividir por 7.
Dejame que haga unas pruebas yo, y luego te paso el tramo de código para
que lo pruebes en tu programa.

Si querés intentarlo vos, la rutina tiene que restarle el nro 7 al valor inicial, luego 7 a lo
que te queda, y así hasta que el resultado te de menor que 7 (resto de la división).
La cantidad de restas que hiciste es el valor que buscás (cociente); eso metelo en CCPR1L,
teniendo en cuenta los bits 4 y 5, como dijiste.

Saludos!
 
Que tal Alejandro, me interesa mucho saber como realizar al division por que yo ya me habia resignado y deje de hacerlo en asm creyendo que una division de ese tipo era imposible de hacer en este lenguaje, despues de que me di cuenta de que 1/4 - 1/8 no es un septimo, me deje llevar por el resultado que era proximo para darme cuenta de que en realidad era 1/8 ops: , asi que un compañero me ofrecio su ayuda para hacer el programa en C, ya solo falta pulir la parte del rango de frecuencia, cuando se termine lo publico, de todas maneras quisiera hacerlo tambien en ensamblador, para terminar mi programa, te agradeceria mucho que me explicaras como hacer la division, gracias por tu tiempo :D
 
Xavier dijo:
... te agradeceria mucho que me explicaras como hacer la division, gracias por tu tiempo :D
La explicación ya la dí en el post anterior. Si se te hace difícil el assembler aguantame un poquito. Estoy buscando porque creo que ya tengo la rutina hecha. Lo que no se es dónde.

Saludos!
 
Atrás
Arriba