Autor Tema: PWM con 2 interrupciones PIC16f887  (Leído 6284 veces)

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

Desconectado Patri

  • PIC10
  • *
  • Mensajes: 11
PWM con 2 interrupciones PIC16f887
« en: 20 de Noviembre de 2012, 13:12:59 »
Muy buenas, soy novata en el foro y tras un par de dias mirando por aqui no encuentro solucion a mi problema. Os comento un poco el tema: consiste en generar una señal pwm con 10 anchos de pulsos (0,10,20,30,40,50%...) y 3 frecuencias (100,1k,5kHz), para encender una bombilla de luz incandescente de 20W y 12V. Seleccionandolo a traves de un switch que van al puerto B, para asi detectar la interrupcion por cambio del puerto B. Dependiendo del ancho de pulso y la frecuencia enciendo unos led indicadores.
En un principio lo realice solo con una interrupcion del puerto b, pero mi profesor me dijo que no estaba bien ya que no esperaba a que terminara un periodo. Asi que pense en utilizar 2 interrupciones la primera cuando cambiara el puerto b y la segunda cuando timer 2 fuese igual a PR2. Es aqui donde se complica la cosa, no se porque motivo no me deja borrar los flags de interrupcion (despues de leer el puerto b). Por lo que siempre esta entrando en el servicio de interrupcion, se enciende todo correctamente, pero esta todo el rato leyendo el puerto b, tratando la frecuencia y el ancho de pulso y encendiendo la bombilla.
Por otro lado debo realizar un programa de verificacion, para comprobar que el funcionamiento de los leds es correcto, que consiste en encender los leds un par de veces.
Les dejo el codigo por si le pueden echar un vistazo y ayudarme.
Muchas gracias por todo, espero sabeer pronto de ustedes.

Código: ASM
  1. ; Se selecciona el banco 3
  2.  bsf    STATUS,5                ; Pone a 1 el bit 5 (RP0) de STATUS y
  3.  bsf    STATUS,6                ; Pone a 1 el bit 6 (RP1) de STATUS
  4.  
  5.  clrf   ANSEL
  6.  clrf   ANSELH                 ; Se limpia este registro para activar las entradas
  7.                                 ; como digitales en el PORTB
  8. ; Se selecciona el banco 0
  9.  bcf    STATUS,5                ; Pone a 0 el bit 5 (RP0) de STATUS y
  10.  bcf    STATUS,6                ; Pone a 0 el bit 6 (RP1) de STATUS
  11.  
  12.  clrf   PORTB                   ; Limpia el puerto B  
  13.  clrf   PORTC
  14.  clrf INTCON
  15.  movlw  b'00000000'
  16.  movwf  PIR2
  17.  movlw  b'00001100'             ; Combinación para selecccionar modo PWM
  18.  movwf  CCP1CON                 ; Configura el PIC para trabajar en modo PWM da la señal PWM en la patilla RC2
  19.  
  20.  
  21. ; Se selecciona el banco 1 de la memoria de datos para acceder al registro TRIS
  22.  bsf    STATUS,5                ; Pone a 1 el bit 5 (RP0) de STATUS y
  23.  bcf    STATUS,6                ; Pone a 0 el bit 6 (RP1) de STATUS
  24.  
  25.  movlw  b'00000000'     ; W<-- (binario) puertas activadas como salidas (CCP1)
  26.  movwf  TRISC           ; W--> TRISC
  27.  movlw  b'00000000'     ; W<-- (binario) puertas activadas como salidas
  28.  movwf  TRISA           ; W--> TRISA
  29.  movlw  b'00111111'     ; W<-- (binario) puertas activadas como entradas
  30.  movwf  TRISB           ; W--> TRISB
  31.  movlw  b'00000000'     ; W<-- (binario) puertas activadas como salidas
  32.  movwf  TRISD           ; Para los LEDs de verificación
  33.  movlw  b'00000000'     ; W<-- (binario) puertas activadas como salidas
  34.  movwf  TRISE           ; W--> TRISE
  35.  movlw  b'00111111'     ; Deshabilita las interrupciones en los pin 0-6
  36.  movwf  IOCB  
  37.      
  38.          
  39.  call   lee_puertab            
  40.  call   TIMER_interrupcion      
  41.  
  42. ;---------------------------------------------------------------------------------
  43. principal
  44.  
  45.   btfss   INTCON,7              ; comprueba si bit 7 del registro INTCON es 0, si es 0 ejecuta la siguiente instruccion
  46.   call    lee_puertab    
  47.   goto principal
  48.  
  49. ;-------------------------------------------------------------------------------------
  50.  
  51.  
  52. ;***************************************************************************************
  53.  
  54. lee_puertab                     ; Lectura de los interruptores para el ancho del pulso
  55.  
  56. ; Se selecciona el banco 0
  57.  bcf    STATUS,5        
  58.  bcf    STATUS,6
  59.         movf    PORTB,W         ; W<--PUERTA B. Se introduce el valor binario de los interruptores
  60.         bcf             INTCON,0
  61.                 andlw   b'00001111'
  62.         addlw   0x05            ; Si el contenido de W es mayor que 10, al sumarle 5 se pone a uno el bit numero 4
  63.         movwf   AUX
  64.         btfsc   AUX,4           ; Si el bit 4 es un uno es porque en los interruptores se ha seleccionado un valor
  65.                                 ; en binario mayor de 10, que al sumarle 5 (en la inst.anterior) provoca que el
  66.                                 ; bit 4 se ponga a 1 (desbordamiento=numero mayor de 15)
  67.         movlw   b'00001111'     ; Pone como valor maximo 15 -5 = 10
  68.         addlw   0x0B            ; Complemento a 2 de 5, para restar 5
  69.         andlw   b'00001111'     ; Se toman los 4 bit menos significativos.
  70.                                 ;   En ellos está el valor de los interruptores en binario (max. 10)
  71.                                 ; (0=0%, 1=10%, 2=20%, ....10 =100%)
  72.         movwf   AUX             ; Para no perder el valor actual de W, se guarda su contenido en AUX
  73.         movwf   PORTD           ; Para activar los LEDs del ancho de pulso
  74.  
  75.         ;tratamiento de la frecuencia
  76.         swapf   PORTB,W         ; Se intercambian los 4 bit de mayor peso por los de menor peso del PORTB                          
  77.                 andlw   b'00000011'     ; Se toman los 2 bit de menor peso donde se tiene la frecuencia seleccio nada
  78.                                 ; de la siguiente forma: 1X (5 kHz=200us), 01 = (1 kHz=1ms) y 00 = (100 Hz=10 ms)
  79.         movwf   FRQ             ; Se guarda el valor de la freq. seleccionada en la variable auxiliar FRQ
  80.         call trata_frq          ; Se llama a la rutina que trata la frecuencia
  81.  
  82. ; Se selecciona el banco 0
  83.  bcf    STATUS,5        
  84.  bcf    STATUS,6
  85.                 movf PORTB,W
  86.         bcf INTCON,0
  87.         movf    AUX,w           ; Se recupera el valor que tenia W antes de tratar la frecuencia
  88.         call tabla
  89.         movwf   AUX_CCPR1L      ; Pag. 129 datasheet. Se selecciona el ancho del pulso
  90.         movlw  b'00000000'
  91.         movwf  PIR1             ;Limpia el flag de interrupcion cuando coinciden timer2 con pr2
  92.  
  93. ; Se selecciona el banco 1 de la memoria de datos para acceder al registro TRIS
  94.  bsf    STATUS,5                ; Pone a 1 el bit 5 (RP0) de STATUS y
  95.  bcf    STATUS,6                ; Pone a 0 el bit 6 (RP1) de STATUS
  96.  
  97.         movlw  b'00000010'
  98.         movwf  PIE1             ; Activa la interrupcion cuando coinciden timer2 con pr2
  99.         movlw  b'11000000'      ; Se habilitan las interrupciones
  100.         movwf  INTCON
  101.  
  102. return
  103.  
  104. ;***********************************************************************************
  105.  
  106.      
  107. ;--------------------------------------------------------------------------------------
  108. ;*************************** Rutina tratamiento de la frecuencia **********************
  109. ;--------------------------------------------------------------------------------------
  110. ; Como el PIC trabaja a 4MHz, el Timer2 evoluciona cada microsegundo pues los
  111. ; impulsos aplicados a TMR0 provienen de la señal de reloj interna (Fosc/4)
  112. ; f= 4Mhz, Tcm=periodo ciclo maquina, Tcm=4 Tosc , Tcm=4*1/f=4*1/4Mhz=1us.
  113. ; Temporizacion 200 us=4*Tcm*prescaler*(PR2 -1)
  114. ; 200=4*1*1*(PR2-1) --> PR2=49 --> se midio con osciloscopio y se observo suficiente precision
  115. ; (pag. 82 datasheet)
  116.  
  117. ; PWMperiodo=(PR2+1)*4*Tosc*(TMR2 prescale value)
  118.  
  119. trata_frq
  120.         movlw   b'00000000'     ; si '00' (100 Hz=10 ms)
  121.         xorwf   FRQ,W
  122.         btfsc   STATUS,Z
  123.         goto    ejec0.1k
  124.        
  125.  
  126. ejec0.1k        
  127.         movlw   b'00010110'     ; Se suma 22 al desplazamiento de la tabla
  128.         movwf   FRQ             ; Se pone en FRQ el desplazamiento a sumar en la tabla
  129.         ; Selección frecuencia
  130.         movlw   b'000000010'    ; preescaler=16
  131.         movwf   AUX_T2CON           ; Pag. 82 del datasheet
  132.         ; LED verificación
  133.         bcf     PORTD,6         ; Se pone a 0 el bit 6 PORTD
  134.         bcf     PORTD,5         ; Se pone a 0 el bit 6 PORTD
  135.         bsf     PORTD,4         ; Se pone a 1 el bit 6 PORTD
  136.        
  137. ; Se selecciona el banco 1 de la memoria de datos para acceder a los registros TRIS
  138.         bsf     STATUS,5                ; Pone a 1 el bit 5 (RP0) de STATUS y
  139.         bcf     STATUS,6                ; Pone a 0 el bit 6 (RP1) de STATUS
  140.        
  141.         movlw   b'10011011'     ; 155 para el registro PR2 -- valor óptimo testeado con osciloscopio
  142.         movwf   AUX_PR2
  143.  
  144. fin_frq
  145.  
  146.         return
  147. ;----------------------------------------------------------------------------------------------
  148. ;*****************************************************************************************
  149. ;-----------------------------------------------------------------------------------------
  150.  
  151. ;___________________________________________________________________________________________
  152. ;%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  153. tabla
  154.  addwf  FRQ,0
  155.  addwf  PCL,1           ; PCL contador de programa pg. 37
  156.  
  157.  
  158. ;tab01k
  159.  
  160.  retlw b'00000000'
  161.  retlw b'00001111'
  162.  retlw b'00011111'
  163.  retlw b'00101110'
  164.  retlw b'00111110'
  165.  retlw b'01001101'
  166.  retlw b'01011101'
  167.  retlw b'01101100'
  168.  retlw b'01111100'
  169.  retlw b'10001011'
  170.  retlw b'11111111'
  171.  
  172.  return
  173. ;___________________________________________________________________________________________
  174. ;%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  175.  
  176.  
  177. ;+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  178. ;--------------------------------PROGRAMA VERIFICACION--------------------------------------
  179.  
  180. cambia_prog
  181.          movlw  b'00000000'     ; Combinación para sdeselecccionar modo PWM
  182.          movwf  CCP1CON         ; Configura el PIC para dejar de trabajar en modo PWM
  183.                                            
  184.  
  185.         bcf     T2CON,TMR2ON    ; se desactiva el timer2
  186.         movwf AUX
  187.         movlw   .3
  188.         movwf   Nejecv
  189. bucle
  190.         call verificacion
  191.         decfsz  Nejecv, F        
  192.         goto    bucle
  193.        
  194.         movlw  b'00001100'     ; Combinación para selecccionar modo PWM
  195.         movwf  CCP1CON         ; Configura el PIC para trabajar en modo PWM
  196.                                ; da la señal PWM en la patilla RC2
  197.         movf    AUX,W
  198.     movwf   CCPR1L         ; se restaura el valor inicial de W
  199.     bsf     T2CON,TMR2ON
  200.  
  201. ; Se selecciona el banco 1 de la memoria de datos para acceder al registro TRIS
  202.  bsf    STATUS,5                ; Pone a 1 el bit 5 (RP0) de STATUS y
  203.  bcf    STATUS,6                ; Pone a 0 el bit 6 (RP1) de STATUS
  204.         movlw  b'00111111'
  205.         movwf  IOCB
  206.         movlw   b'10001000'     ; Activa interrupción global y la pone activa
  207.         movwf   INTCON
  208.         goto    $
  209.  
  210. verificacion
  211.  
  212.         movlw b'00000001'
  213.         movwf PORTD
  214.  
  215. desplazav  
  216.      
  217.         call PDelay      ; Delay 1000000 cycles (including call+return)
  218.         rlf PORTD,F
  219.         btfss PORTD,7
  220.         goto desplazav
  221.  
  222.         return
  223.        
  224. ;-------------------------------------------------------------
  225. PDelay  movlw     .14       ; numero de repeticiones (C)
  226.         movwf     PDel0     ;
  227. PLoop0  movlw     .18       ; numero de repeticiones (B)
  228.         movwf     PDel1     ;
  229. PLoop1  movlw     .120      ; numero de repeticiones (A)
  230.         movwf     PDel2     ;
  231. PLoop2  clrwdt              ; clear watchdog
  232.         decfsz    PDel2,F   ; fin del bucle? (A)
  233.         goto      PLoop2    ;
  234.         decfsz    PDel1,F   ; fin del bucle? (B)
  235.         goto      PLoop1    ;
  236.         decfsz    PDel0,F   ; fin del bucle? (C)
  237.         goto      PLoop0    ;
  238. PDelL1  goto PDelL2         ;
  239. PDelL2  clrwdt              ;
  240.         return              ;
  241. ;-------------------------------------------------------------
  242. ;+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  243.  
  244.  
  245.  
  246. ;------------------------------------------------------------------------------
  247. ;******************* RUTINA TRATAMIENTO DE LA INTERRUPCION ********************
  248. ;------------------------------------------------------------------------------
  249.  
  250. ServicioInterrupcion
  251.  
  252. ; Se selecciona el banco 1 de la memoria de datos para acceder al registro TRIS
  253.  bsf    STATUS,5                ; Pone a 1 el bit 5 (RP0) de STATUS y
  254.  bcf    STATUS,6                ; Pone a 0 el bit 6 (RP1) de STATUS
  255.  
  256.         btfsc   PIE1,1            ; comprueba si bit 1 del registro PIE es 1, si es 1 ejecuta la siguiente instruccion
  257.         call    TIMER_interrupcion     
  258.         call    PORTB_interrupcion               
  259.        
  260.  
  261.  
  262. PORTB_interrupcion
  263.  
  264.  
  265. ; Se selecciona el banco 0
  266. bcf    STATUS,5        
  267. bcf    STATUS,6
  268.  
  269.         movf    PORTB,W         ; Se lee el puerto B
  270.         movlw  b'00000000'
  271.         movwf  INTCON           ; Se limpia el flag de interrupcion
  272.  
  273. ; Se selecciona el banco 1 de la memoria de datos para acceder al registro TRIS
  274.  bsf    STATUS,5                ; Pone a 1 el bit 5 (RP0) de STATUS y
  275.  bcf    STATUS,6                ; Pone a 0 el bit 6 (RP1) de STATUS
  276.  
  277. ;       movlw  b'00000000'
  278. ;       movwf  IOCB             ; Se deshabilitan el puerto B como interrupciones
  279. ;       movlw  b'00000000'
  280. ;       movwf  PIE1             ;DesActiva la interrupcion cuando coinciden timer2 con pr2
  281.  
  282. goto principal
  283.  
  284. TIMER_interrupcion
  285.  
  286. ; Se selecciona el banco 1 de la memoria de datos para acceder al registro TRIS
  287.  bsf    STATUS,5                ; Pone a 1 el bit 5 (RP0) de STATUS y
  288.  bcf    STATUS,6                ; Pone a 0 el bit 6 (RP1) de STATUS
  289.  
  290.         movlw  b'00000000'     ; DesActiva interrupción
  291.         movwf  INTCON
  292.         movlw  b'00000000'
  293.         movwf  PIE1             ;DesActiva la interrupcion cuando coinciden timer2 con pr2     
  294.         movf   AUX_PR2,W
  295.         movwf  PR2
  296. ;       movlw  b'00111111'
  297. ;       movwf  IOCB
  298.        
  299. ; Se selecciona el banco 0
  300.  bcf    STATUS,5        
  301.  bcf    STATUS,6
  302.  
  303.        
  304. ;       bcf    PIR1,TMR2IF    ;limpia el flag de reconocimiento de TIMER2 = PR2
  305.         movf    AUX_T2CON,W
  306.         movwf   T2CON
  307.         bcf     T2CON,TMR2ON
  308.         movf    AUX_CCPR1L,w
  309.     movwf   CCPR1L          ; Pag. 129 datasheet. Se selecciona el ancho del pulso
  310.     bsf     T2CON,TMR2ON
  311.         bcf    PIR1,TMR2IF    ;limpia el flag de reconocimiento de TIMER2 = PR2
  312.  
  313.  
  314. ; Se selecciona el banco 0
  315. bcf    STATUS,5        
  316. bcf    STATUS,6
  317.  
  318.         movf    PORTB,W         ; Se lee el puerto B   
  319.         movlw  b'10001000'     ; Activa interrupción global y la pone activa
  320.         movwf  INTCON
  321.  
  322. goto principal
  323.  
  324. END                            ; Directiva final del programa
« Última modificación: 20 de Noviembre de 2012, 16:25:13 por Patri »

Desconectado AngelGris

  • Colaborador
  • PIC24H
  • *****
  • Mensajes: 2480
Re: PWM con 2 interrupciones PIC16f887
« Respuesta #1 en: 20 de Noviembre de 2012, 15:08:03 »
  Bienvenida al foro.

  Sería mejor que colocases tu código utilizando la opgión GeSHi del editor de mensajes. Ejemplo

Código: ASM
  1. movlw 10;
  2. movwf 0x06;

  Así se puede ver el código sin necesidad de bajar ningún archivo.

  Por otro lado, tal vez sería conveniente hacer la consulta en el foro de asembles.
De vez en cuando la vida
nos besa en la boca
y a colores se despliega
como un atlas

Desconectado Fer_TACA

  • Moderadores
  • DsPIC33
  • *****
  • Mensajes: 4154
Re: PWM con 2 interrupciones PIC16f887
« Respuesta #2 en: 20 de Noviembre de 2012, 15:09:54 »
Hola Patri,
En primer lugar bienvenida al foro. Ahora tu problema

ya tengo un poco oxidado el ASM pero creo que hay algo mal dentro de las rutinas de interrupcion. Cuando haces:
Código: [Seleccionar]
btfsc   PIE1,1        ; comprueba si bit 1 del registro PIE es 1, si es 1 ejecuta la siguiente instruccion
call    TIMER_interrupcion
call    PORTB_interrupcion

llamas a unas rutinas con el call, estas rutinas cuando finalizan me parece que debes de regresar con la instruccion "Return". Tu estas empleando "goto principal" con lo cual regresas al inicio del programa principal. Es decir ejecutas el primer salto con call TIMER_interrupcion se ejecutan las instrucciones allí colocadas pero el regreso en vez de ir a "call    PORTB_interrupcion" que seria la instruccion siguiente, lo que realizas es ir al inicio de programa nuevamente.
Dentro de la rutina "call    PORTB_interrupcion" tambien te pasa lo mismo y sobre todo:
al final la rutina de interrupcion vuelves a colocar un "goto principal" en vez de la instruccion de retorno de fin de interrupcion.

F.
Todos los días se aprende algo nuevo.

Desconectado Patri

  • PIC10
  • *
  • Mensajes: 11
Re: PWM con 2 interrupciones PIC16f887
« Respuesta #3 en: 20 de Noviembre de 2012, 16:31:00 »
Gracias por las recomendaciones ya cambie el codigo :D.
En cuanto a lo de hacerlo con call y no poner luego return es porque al entrar en el servicio de interrupcion solo pretendo identificar si la interrupcion es del puerto b o del timer2 dependiendo de eso llamo a TIMER_interrupcion o PORTB_interrupcion.
Por otro lado un problema que me esta surgiendo ahora es que al activar el timer2 se reinicia y sale del modo debug, no se porque podra  ser...
Una cosa que olvide decir es que simulando en PROTEUS funciona perfectamente.
Muchas gracias por todo.
Hola Patri,
En primer lugar bienvenida al foro. Ahora tu problema

ya tengo un poco oxidado el ASM pero creo que hay algo mal dentro de las rutinas de interrupcion. Cuando haces:
Código: [Seleccionar]
btfsc   PIE1,1        ; comprueba si bit 1 del registro PIE es 1, si es 1 ejecuta la siguiente instruccion
call    TIMER_interrupcion
call    PORTB_interrupcion

llamas a unas rutinas con el call, estas rutinas cuando finalizan me parece que debes de regresar con la instruccion "Return". Tu estas empleando "goto principal" con lo cual regresas al inicio del programa principal. Es decir ejecutas el primer salto con call TIMER_interrupcion se ejecutan las instrucciones allí colocadas pero el regreso en vez de ir a "call    PORTB_interrupcion" que seria la instruccion siguiente, lo que realizas es ir al inicio de programa nuevamente.
Dentro de la rutina "call    PORTB_interrupcion" tambien te pasa lo mismo y sobre todo:
al final la rutina de interrupcion vuelves a colocar un "goto principal" en vez de la instruccion de retorno de fin de interrupcion.

F.

Desconectado Fer_TACA

  • Moderadores
  • DsPIC33
  • *****
  • Mensajes: 4154
Re: PWM con 2 interrupciones PIC16f887
« Respuesta #4 en: 21 de Noviembre de 2012, 09:02:45 »
De todas formas sigo pensando que con las instrucciones goto_principal como retorno de las interrupciones no tee va a funcionar el programa.
Todos los días se aprende algo nuevo.

Desconectado tapi8

  • Colaborador
  • PIC24H
  • *****
  • Mensajes: 1506
Re: PWM con 2 interrupciones PIC16f887
« Respuesta #5 en: 21 de Noviembre de 2012, 14:00:02 »
Patri, haz caso de lo que te dice Fer_TACA, no puedes entrar en interrupcion o llamar a una subrutina y salir con un goto, ya que no vacias el STACK y entonces se llena y se desborda, hay que volver con RETURN, RETFIE O RETLW segun sea el caso.

Desconectado Patri

  • PIC10
  • *
  • Mensajes: 11
Re: PWM con 2 interrupciones PIC16f887
« Respuesta #6 en: 24 de Noviembre de 2012, 10:30:05 »
Ya lo puse como me decis, pero sigo sin poder borrar el flag TMR2IF. En cuanto enciendo el Timer 2 se activa el flag y no puedo borrarlo. Se produce la interrupcion por el timer, pero creo que no esta bien ya que no se resetea el Timer 2. Teneis idea de porque puede ser?
Muchas gracias por todo!!

Desconectado Patri

  • PIC10
  • *
  • Mensajes: 11
Re: PWM con 2 interrupciones PIC16f887
« Respuesta #7 en: 25 de Noviembre de 2012, 07:58:52 »
Hola siento ser tan pesada pero es que tengo el examen el martes y no logro encontrar el error. He cargado otros programas que tenia y me da el mismo error, es decir: al encender el timer 2 se carga con un valor aleatorio (cuando creo que deberia ser 0) y se enciende el flag de overflow del timer2 sin poder borrarlo de ninguna manera. El programa va perfectamente en el PROTEUS pero al montarlo y debuggearlo me da este error. Creo que puede ser un problema de configuracion del oscilador o algo. En la configuracion de bits tengo:
- FOSC: INTOSC
- WDTE: disabled
- PWRTE: disabled
- MCLRE: no se como ponerlo
- CP:disabled
- CPD: disabled
- BOREN: disabled
- IESO: disabled
- FCMEN: disabled
- LVP: RB3 digital I/O, HV on MCLR
- BOR4V:  set to 4v
- WRTE: off
La configuracion la he hecho en el mplab Configure no en el codigo. No se si esta correcta la configuracion, otra duda que me sale es que al tener HV en MCLR debo conectarlo directamente sin ninguna resistencia ni nada no?
Muchas gracias por todo. Espero que contesten rapido.

Desconectado tapi8

  • Colaborador
  • PIC24H
  • *****
  • Mensajes: 1506
Re: PWM con 2 interrupciones PIC16f887
« Respuesta #8 en: 25 de Noviembre de 2012, 08:18:23 »
Pon el programa como lo tienes ahora y te lo miro, espero que antes del martes  :lol: :lol: como esta ese primero que pones no puede funcionar.

 Haces cambios de bancos de RAM dentro de ls interrupcion, a lo mejor lo estas borrando en un banco que no es.

Desconectado Patri

  • PIC10
  • *
  • Mensajes: 11
Re: PWM con 2 interrupciones PIC16f887
« Respuesta #9 en: 25 de Noviembre de 2012, 08:23:17 »
Asi me ha quedado el programa ahora:
Código: ASM
  1. LIST P=16F887          ; MODELO DE PIC QUE ESTAMOS UTILIZANDO
  2.  INCLUDE <P16F887.INC>  ; Fichero de definición que proporciona el fabricante, donde se
  3.         LIST
  4.  
  5.  
  6. FRQ    EQU      0x52    ; Variable para trabajar con la frecuencia
  7. PDel0  EQU      0X53    ;
  8. PDel1  EQU      0X54    ;
  9. PDel2  EQU      0X55    ;
  10. AUX    EQU      0x58    ; Variable para trabajos auxilires
  11. AUX_T2CON EQU   0X59
  12. AUX_PR2 EQU     0X60
  13. AUX_CCPR1L EQU  0X61
  14.  
  15.  
  16. ORG    0x00            ; Dirección de comienzo del programa
  17. goto inicio
  18.  
  19. ORG    0x04          ; Vector de interrupción (pag. 216 datasheet)
  20. goto ServicioInterrupcion
  21.  
  22. inicio
  23. ;--------------------------------------------------------------------------------
  24. ; Inicialización de los valores para el correcto funcionamiento del PIC
  25.  
  26.  
  27. ; Se selecciona el banco 3
  28.  bsf    STATUS,5                ; Pone a 1 el bit 5 (RP0) de STATUS y
  29.  bsf    STATUS,6                ; Pone a 1 el bit 6 (RP1) de STATUS
  30.  
  31.  clrf   ANSEL
  32.  clrf   ANSELH                  ; Se limpia este registro para activar las entradas
  33.                                 ; como digitales en el PORTB
  34.  
  35. ; Se selecciona el banco 0
  36.  bcf    STATUS,5                ; Pone a 0 el bit 5 (RP0) de STATUS y
  37.  bcf    STATUS,6                ; Pone a 0 el bit 6 (RP1) de STATUS
  38.  
  39.  clrf   PORTB                   ; Limpia el puerto B  
  40.  clrf   PORTC                   ; Limpia el puerto C
  41. clrf    PORTD                   ;Limpia el puerto D
  42.  clrf   INTCON
  43. clrf    PIR2
  44. movlw  b'00001100'              ; Combinación para selecccionar modo PWM
  45.         movwf  CCP1CON          ; Configura el PIC para trabajar en modo PWM da la señal PWM en la patilla RC2
  46.  
  47. ; Se selecciona el banco 1 de la memoria de datos para acceder al registro TRIS
  48.  bsf    STATUS,5                ; Pone a 1 el bit 5 (RP0) de STATUS y
  49.  bcf    STATUS,6                ; Pone a 0 el bit 6 (RP1) de STATUS
  50.  
  51.  movlw  b'01000000'     ;configura el reloj interno a 1MHz
  52.  movwf  OSCCON
  53.  clrf  TRISC            ; puertas activadas como salidas
  54.  clrf  TRISA            ; puertas activadas como salidas
  55.  movlw  b'00111111'     ; W<-- (binario) puertas activadas como entradas
  56.  movwf  TRISB           ; W--> TRISB
  57.  clrf  TRISD            ; puertas activadas como salidas (LEDs de verificación)
  58.  clrf  TRISE            ; puertas activadas como salidas
  59.  bcf    OPTION_REG,7    ; se activa las resistancias pull-up del puerto b
  60.  movlw  b'00111111'
  61.  movwf  WPUB            ; pull up
  62.  movlw  b'00111111'     ; Habilita las interrupciones en los pin 0-6
  63.  movwf  IOCB  
  64.  
  65.  
  66. ; Se selecciona el banco 0
  67.  bcf    STATUS,5                ; Pone a 0 el bit 5 (RP0) de STATUS y
  68.  bcf    STATUS,6                ; Pone a 0 el bit 6 (RP1) de STATUS
  69.                      
  70.  clrf   PORTD
  71.  clrf   PORTC
  72.  movlw  b'00001100'             ; Combinación para selecccionar modo PWM
  73.  movwf  CCP1CON                 ; Configura el PIC para trabajar en modo PWM da la señal PWM en la patilla RC2    
  74.  call   lee_puertab            
  75.  call   TIMER_interrupcion      
  76.  
  77. ;---------------------------------------------------------------------------------
  78. principal
  79.  
  80.   btfss   INTCON,7              ; comprueba si bit 7 del registro INTCON es 0, si es 0 ejecuta la siguiente instruccion
  81.   call    lee_puertab    
  82.   goto principal
  83.  
  84. ;-------------------------------------------------------------------------------------
  85.  
  86.  
  87. ;***************************************************************************************
  88.  
  89. lee_puertab                     ; Lectura de los interruptores para el ancho del pulso
  90.  
  91. ; Se selecciona el banco 0
  92.  bcf    STATUS,5        
  93.  bcf    STATUS,6
  94.         movf    PORTB,W         ; W<--PUERTA B. Se introduce el valor binario de los interruptores
  95.         andlw   b'00001111'
  96.         addlw   0x05            ; Si el contenido de W es mayor que 10, al sumarle 5 se pone a uno el bit numero 4
  97.         movwf   AUX
  98.         btfsc   AUX,4           ; Si el bit 4 es un uno es porque en los interruptores se ha seleccionado un valor
  99.                                 ; en binario mayor de 10, que al sumarle 5 (en la inst.anterior) provoca que el
  100.                                 ; bit 4 se ponga a 1 (desbordamiento=numero mayor de 15)
  101.         movlw   b'00001111'     ; Pone como valor maximo 15 -5 = 10
  102.         addlw   0x0B            ; Complemento a 2 de 5, para restar 5
  103.         andlw   b'00001111'     ; Se toman los 4 bit menos significativos.
  104.                                 ;   En ellos está el valor de los interruptores en binario (max. 10)
  105.                                 ; (0=0%, 1=10%, 2=20%, ....10 =100%)
  106.         movwf   AUX             ; Para no perder el valor actual de W, se guarda su contenido en AUX
  107.         movwf   PORTD           ; Para activar los LEDs del ancho de pulso
  108.  
  109.         ;tratamiento de la frecuencia
  110.         swapf   PORTB,W         ; Se intercambian los 4 bit de mayor peso por los de menor peso del PORTB                          
  111.         andlw   b'00000011'     ; Se toman los 2 bit de menor peso donde se tiene la frecuencia seleccionada
  112.                                 ; de la siguiente forma: 1X (5 kHz=200us), 01 = (1 kHz=1ms) y 00 = (100 Hz=10 ms)
  113.  
  114.         movwf   FRQ             ; Se guarda el valor de la freq. seleccionada en la variable auxiliar FRQ
  115.         call trata_frq          ; Se llama a la rutina que trata la frecuencia
  116.  
  117. ; Se selecciona el banco 0
  118.  bcf    STATUS,5        
  119.  bcf    STATUS,6
  120.        
  121.         movf    AUX,w           ; Se recupera el valor que tenia W antes de tratar la frecuencia
  122.         call tabla
  123.         movwf   AUX_CCPR1L      ; Pag. 129 datasheet. Se selecciona el ancho del pulso
  124.         movlw  b'00000000'
  125.         movwf  PIR1             ;Limpia el flag de interrupcion cuando coinciden timer2 con pr2
  126.  
  127. ; Se selecciona el banco 1 de la memoria de datos para acceder al registro TRIS
  128.  bsf    STATUS,5                ; Pone a 1 el bit 5 (RP0) de STATUS y
  129.  bcf    STATUS,6                ; Pone a 0 el bit 6 (RP1) de STATUS
  130.  
  131.         movlw  b'00000010'
  132.         movwf  PIE1             ; Activa la interrupcion cuando coinciden timer2 con pr2
  133.         movlw  b'11000000'      ; Se habilitan las interrupciones
  134.         movwf  INTCON
  135.  
  136. return
  137.  
  138. ;***********************************************************************************
  139.  
  140.      
  141. ;--------------------------------------------------------------------------------------
  142. ;*************************** Rutina tratamiento de la frecuencia **********************
  143. ;--------------------------------------------------------------------------------------
  144. ; Como el PIC trabaja a 1MHz, el Timer2 evoluciona cada microsegundo pues los
  145. ; impulsos aplicados a TMR0 provienen de la señal de reloj interna (Fosc/4)
  146. ; f= 41Mhz, Tcm=periodo ciclo maquina, Tcm=4 Tosc , Tcm=4*1/f=4*1/4Mhz=1us.
  147. ; Temporizacion 200 us=4*Tcm*prescaler*(PR2 -1)
  148. ; 200=4*1*1*(PR2-1) --> PR2=49 --> se midio con osciloscopio y se observo suficiente precision
  149. ; (pag. 82 datasheet)
  150.  
  151. ; PWMperiodo=(PR2+1)*4*Tosc*(TMR2 prescale value)
  152.  
  153. trata_frq
  154.         movlw   b'00000000'     ; si '00' (100 Hz=10 ms)
  155.         xorwf   FRQ,W
  156.         btfsc   STATUS,Z
  157.         goto    ejec0.1k
  158.        
  159.         movlw   b'00000001'     ; si '01' (1 kHz=1ms)
  160.         xorwf   FRQ,W
  161.         btfsc   STATUS,Z
  162.         goto    ejec1k
  163.                
  164.  
  165. ejec5k  movlw   b'00000000'     ; Se suma 0 al desplazamiento de la tabla
  166.         movwf   FRQ             ; Se pone en FRQ el desplazamiento a sumar en la tabla
  167.        
  168.         ; Seleccion frecuencia
  169.         movlw   b'00000000'     ; preescaler=1
  170.         movwf   AUX_T2CON       ; Pag. 82 del datasheet
  171.         ; LED verificación
  172.         bsf     PORTD,6         ; Se pone a 1 el bit 6 PORTD
  173.         bcf     PORTD,5         ; Se pone a 0 el bit 5 PORTD
  174.         bcf     PORTD,4         ; Se pone a 0 el bit 4 PORTD
  175.        
  176.         ; Se selecciona el banco 1 de la memoria de datos para acceder al registro TRIS
  177.  
  178.         bsf     STATUS,5        ; Pone a 1 el bit 5 (RP0) de STATUS y
  179.         bcf     STATUS,6        ; Pone a 0 el bit 6 (RP1) de STATUS
  180.        
  181.         movlw   .46             ; 49 para el registro PR2 (46 valor comprobado con el osciloscopio)
  182.         movwf   AUX_PR2
  183.         goto fin_frq
  184.  
  185. ejec1k  movlw   b'00001011'     ; Se suma 11 al desplazamiento de la tabla
  186.         movwf   FRQ             ; Se pone en FRQ el desplazamiento a sumar en la tabla
  187.        
  188.         ; Selección frecuencia
  189.         movlw   b'00000000'     ; preescaler=1
  190.         movwf   AUX_T2CON       ; Pag. 82 del datasheet
  191.         ; LED verificación
  192.         bcf     PORTD,6         ; Se pone a 0 el bit 6 PORTD
  193.         bsf     PORTD,5         ; Se pone a 1 el bit 6 PORTD
  194.         bcf     PORTD,4         ; Se pone a 0 el bit 6 PORTD
  195.        
  196.         ; Se selecciona el banco 1 de la memoria de datos para acceder a los registros TRIS
  197.         bsf     STATUS,5        ; pone a 1 el bit 5 (RP0) de STATUS y
  198.         bcf     STATUS,6        ; pone a 0 el bit 6 (RP1) de STATUS
  199.        
  200.         movlw   .236            ; 249 para el registro PR2 (236 valor comprobado con el osciloscopio)
  201.         movwf   AUX_PR2    
  202.         goto fin_frq
  203.  
  204. ejec0.1k        
  205.         movlw   b'00010110'     ; Se suma 22 al desplazamiento de la tabla
  206.         movwf   FRQ             ; Se pone en FRQ el desplazamiento a sumar en la tabla
  207.         ; Selección frecuencia
  208.         movlw   b'00000011'     ; preescaler=16
  209.         movwf   AUX_T2CON       ; Pag. 82 del datasheet
  210.         ; LED verificación
  211.         bcf     PORTD,6         ; Se pone a 0 el bit 6 PORTD
  212.         bcf     PORTD,5         ; Se pone a 0 el bit 6 PORTD
  213.         bsf     PORTD,4         ; Se pone a 1 el bit 6 PORTD
  214.        
  215.         ; Se selecciona el banco 1 de la memoria de datos para acceder a los registros TRIS
  216.         bsf     STATUS,5        ; Pone a 1 el bit 5 (RP0) de STATUS y
  217.         bcf     STATUS,6        ; Pone a 0 el bit 6 (RP1) de STATUS
  218.        
  219.         movlw   .146            ; 155 para el registro PR2 (146 valor comprobado con el osciloscopio)
  220.         movwf   AUX_PR2
  221.  
  222. fin_frq
  223.  
  224.         return
  225. ;----------------------------------------------------------------------------------------------
  226. ;*****************************************************************************************
  227. ;-----------------------------------------------------------------------------------------
  228.  
  229. ;___________________________________________________________________________________________
  230. ;%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  231. tabla
  232.  addwf  FRQ,0
  233.  addwf  PCL,1           ; PCL contador de programa pg. 37
  234.  
  235.  retlw .0
  236.  retlw .5
  237.  retlw .9
  238.  retlw .14
  239.  retlw .18
  240.  retlw .23
  241.  retlw .28
  242.  retlw .33
  243.  retlw .38
  244.  retlw .42
  245.  retlw .47
  246.  
  247. ;tab1k
  248.  retlw .0
  249.  retlw .24
  250.  retlw .47
  251.  retlw .70
  252.  retlw .95
  253.  retlw .118
  254.  retlw .142
  255.  retlw .165
  256.  retlw .189
  257.  retlw .212
  258.  retlw .237
  259.  
  260. ;tab01k
  261.  
  262.  retlw .0
  263.  retlw .15
  264.  retlw .29
  265.  retlw .44
  266.  retlw .58
  267.  retlw .73
  268.  retlw .88
  269.  retlw .102
  270.  retlw .117
  271.  retlw .131
  272.  retlw .147
  273.  
  274.  return
  275.  
  276.  
  277. ;------------------------------------------------------------------------------
  278. ;******************* RUTINA TRATAMIENTO DE LA INTERRUPCION ********************
  279. ;------------------------------------------------------------------------------
  280.  
  281. ServicioInterrupcion
  282.  
  283. ; Se selecciona el banco 1 de la memoria de datos para acceder al registro TRIS
  284.  bsf    STATUS,5                ; Pone a 1 el bit 5 (RP0) de STATUS y
  285.  bcf    STATUS,6                ; Pone a 0 el bit 6 (RP1) de STATUS
  286.  
  287.         btfsc   PIE1,1            ; comprueba si bit 1 del registro PIE es 1, si es 1 ejecuta la siguiente instruccion
  288.         goto    TIMER_interrupcion     
  289.         goto    PORTB_interrupcion               
  290.        
  291.  
  292.  
  293. PORTB_interrupcion
  294.  
  295.  
  296. ; Se selecciona el banco 0
  297. bcf    STATUS,5        
  298. bcf    STATUS,6
  299.  
  300.         movf    PORTB,W         ; Se lee el puerto B
  301.         movlw  b'00000000'
  302.         movwf  INTCON           ; Se limpia el flag de interrupcion
  303.  
  304. ; Se selecciona el banco 1 de la memoria de datos para acceder al registro TRIS
  305.  bsf    STATUS,5                ; Pone a 1 el bit 5 (RP0) de STATUS y
  306.  bcf    STATUS,6                ; Pone a 0 el bit 6 (RP1) de STATUS
  307.  
  308. ;       movlw  b'00000000'
  309. ;       movwf  IOCB             ; Se deshabilitan el puerto B como interrupciones
  310. ;       movlw  b'00000000'
  311. ;       movwf  PIE1             ;DesActiva la interrupcion cuando coinciden timer2 con pr2
  312.  
  313. return
  314.  
  315. TIMER_interrupcion
  316.  
  317.        
  318. ; Se selecciona el banco 0
  319.  bcf    STATUS,5        
  320.  bcf    STATUS,6
  321.  
  322. clrf    T2CON
  323. clrf    TMR2
  324. clrf    INTCON
  325.  
  326. ; Se selecciona el banco 1 de la memoria de datos para acceder al registro TRIS
  327.  bsf    STATUS,5                ; Pone a 1 el bit 5 (RP0) de STATUS y
  328.  bcf    STATUS,6                ; Pone a 0 el bit 6 (RP1) de STATUS
  329.  
  330.         clrf  PIE1             ;DesActiva la interrupcion cuando coinciden timer2 con pr2      
  331.         movf   AUX_PR2,W
  332.         movwf  PR2
  333.        
  334. ; Se selecciona el banco 0
  335.  bcf    STATUS,5        
  336.  bcf    STATUS,6
  337.  
  338.        
  339.         clrf     PIR1     ;limpia el flag de reconocimiento de TIMER2 = PR2
  340.         bcf     PIR1,TMR2IF
  341.         movf    AUX_T2CON,W
  342.         movwf   T2CON
  343.         movf    AUX_CCPR1L,w
  344.         movwf   CCPR1L          ; Pag. 129 datasheet. Se selecciona el ancho del pulso
  345.         bcf     PIR1,TMR2IF
  346.         bsf     T2CON,TMR2ON    ; se activa el timer 2
  347.         clrf     PIR1     ;limpia el flag de reconocimiento de TIMER2 = PR
  348.         movf    PORTB,W         ; Se lee el puerto B   
  349.         movlw  b'10001000'      ; Activa interrupción global y la pone activa
  350.         movwf  INTCON
  351.  
  352. retfie
  353.  
  354. END                            ; Directiva final del programa
Muchas graciass!!!

Desconectado Fer_TACA

  • Moderadores
  • DsPIC33
  • *****
  • Mensajes: 4154
Re: PWM con 2 interrupciones PIC16f887
« Respuesta #10 en: 25 de Noviembre de 2012, 15:20:33 »
Hola Patri,
una cosa que sigo viendo y que me parece que no esta bien es que dentro de la rutina de interrupcion, haces un par de gotos:
goto    TIMER_interrupcion
goto    PORTB_interrupcion
Ahora bien dentro de la llamada del primero, has colocado una serie de instrucciones y acabas con "retfie". Esto está bien, pero en la parte del 2º goto estas terminando con un "return" que se supone que es el regreso de una llamada con un call. Si o que quieres es tambien es salir de la interrupcion deberia ser un "retfie".

F.
Todos los días se aprende algo nuevo.

Desconectado Patri

  • PIC10
  • *
  • Mensajes: 11
Re: PWM con 2 interrupciones PIC16f887
« Respuesta #11 en: 25 de Noviembre de 2012, 15:43:19 »
He puesto return porque no quiero que se habiliten las interrupcion hasta que termine de tratar la nueva frecuencia y ancho de pulso, entonces cuando termino de todo la habilito yo. No se si estara bien pero es lo unico que se me ha ocurrido... Y si no puedo poner goto en la interrupcion como podria hacerlo???
Tengo una pregunta, si configuro LVP: RB3 I/O digital, MCLR con HV ¿Como tengo que configurar el MCLRE? ¿Estoy utilizando el MCLR para el debbuger (es que si no lo conecto no me deja entrar en el modo debugger)?
Muchas gracias por las respuestas.

Desconectado Fer_TACA

  • Moderadores
  • DsPIC33
  • *****
  • Mensajes: 4154
Re: PWM con 2 interrupciones PIC16f887
« Respuesta #12 en: 25 de Noviembre de 2012, 16:09:24 »
Es que con es return no sabes a donde va ir el programa.
Si quieres seguir utilizandolo deberias de cambiar en goto por el call.
ya que tano con el goto como con el call vas a ejecutar esa parte del codigo pero desde luego con el return y goro wel programa te va air a cualquier parte en que tenga en ese momento la pila, si es que tiene alguno.


F.
Todos los días se aprende algo nuevo.

Desconectado tapi8

  • Colaborador
  • PIC24H
  • *****
  • Mensajes: 1506
Re: PWM con 2 interrupciones PIC16f887
« Respuesta #13 en: 25 de Noviembre de 2012, 17:07:16 »
Creo que no tienes claro como van las interrupciones, a una interrupcion no tienes que llamarla tu, tiene que saltar ella, ir al vector de interrupcion y ejacutarse, como eres tu quien la llamas el programa se queda clavado aqui:

Código: [Seleccionar]
call   TIMER_interrupcion     
 
;---------------------------------------------------------------------------------
principal
 
  btfss   INTCON,7         ; comprueba si bit 7 del registro INTCON es 0, si es 0 ejecuta la siguiente instruccion
  call    lee_puertab   
  goto principal

La interrupcion por TIMER2 no salta, Ademas no chequeas PIR1,TMR2IF sino que chequeas  btfsc   PIE1,1 este es un bit que tu seteas para activar TIMER2 pero no es el flag, no es que no se te borre, es que no se activa. 

Desconectado Patri

  • PIC10
  • *
  • Mensajes: 11
Re: PWM con 2 interrupciones PIC16f887
« Respuesta #14 en: 25 de Noviembre de 2012, 17:17:09 »
Es que tengo 2 motivos de interrupcion. La interrupcion se produce sola no? simplemente que despues veo si se produce por un motivo o por otro y voy a TIMER_interrupcion o PORTB_interrupcion, la verdad es que me sale bien de la interrupcion no se si sera por suerte...xD
No chequeo TMR2IF porque no me va bien, asi que intente buscar algo que estuviera relacionado y como para que se me produzca la interrupcion por el Timer tiene que estar activado el PIE1 pues he usado eso.