TODOPIC
Microcontroladores PIC => Almacén del Assembler => Mensaje iniciado por: fjam_rock en 21 de Septiembre de 2016, 09:47:57
-
Hola a todos,
estoy intentando recibir MIDI en un PIC 16f874. Tengo un código simple que al recibir un dato por la puerta serial, se traslada al puerto B para visualización y se activa un led. Para empezar lo estoy haciendo sin loop, sólo que lea un dato y avise. El problema es que al simular en Proteus veo un valor que no coincide con el que envío.
Para simular en proteus estoy usando un emulador de puerto serial que crea dos puertos virtuales. Además uso el programa Serial Midi Converter, que hace la conversión de midi a serie. Esta información la leo en el módulo COMPIM de Proteus.
Acá dejo el código que estoy usando:
cblock 0x20
d1
d2
d3
; TOROB
TEMP
endc
ORG 0x00
goto MAIN
ORG 0x04
goto INT
MAIN
;INICIALIZACION
;BANK 1
BSF STATUS, RP0
CLRF TRISB
;CLRF TRISD
BSF TRISC,7 ;ENTRADA SERIAL
BCF TRISC,0
BCF TRISC,1
BCF TRISC,2
MOVLW 0X09 ;SET BAUD RATE (20M/64(9+1)=31250)
MOVWF SPBRG
BCF TXSTA,SYNC ;ASYNCHRONOUS
BCF TXSTA,BRGH
BSF INTCON,GIE ;SE HABILITAN INTERRUPCIONES
BSF INTCON,PEIE
BSF PIE1,RCIE ;SE HABILITA INTERRUPCION DE RX
;BANK 0
BCF STATUS, RP0
BSF RCSTA,SPEN ;SE HABILITA PUERTO SERIAL
BSF RCSTA,CREN ;SE HABILITA RECEPCION
CLRF PORTB
; CALL DELAY
LOOP
BCF PORTC,0
BCF PORTC,1
; CALL DELAY
GOTO LOOP
INT
BSF PORTC,0 ;SI SE RECIBE DATO SE ACTIVA PORTC,0
; BSF PORTC,1
BTFSC RCSTA,1 ;SE REVISA OVERRUN ERROR
GOTO ERR
GOTO NORM
ERR BSF PORTC,2 ;SE INDICA ERROR EN PORTC,2
BCF RCSTA,1 ;RESET OERR
NORM
MOVF RCREG,W ;SE CARGA DATO RECIBIDO EN W
MOVWF PORTB ;SE TRASPASA DATO RECIBIDO A PORTB
; BCF PORTC,1
BCF RCSTA,CREN ;SE DESHABILITA RECEPCION
; BCF PORTC,0
; BCF PORTC,2
RETFIE
Ojalá alguien haya simulado esto antes y me pueda ayudar.
Saludos
-
Errores que veo en el programa:
- Activas las interrupciones y luego haces el setup de los modulos, siempre configura todo primero, activa la interrupcion del modulo en el PIE, limpia el flag luego activar el PIE, y luego al final de todas las configuraciones activa las interrupciones globales y de perifericos. Si no me equivoco cuando activas la interrupcion del PIE se pone a 1 el flag, lo cual tenes que leer y descartar el dato de RCREG
- A la rutina de interrupcion le falta lo de guardar y reponer W, STATUS, PCLATH. Esto esta en el datasheet, Sin nada en el loop no es problema, pero con algo dentro significa que si lo vas a tener.
- Si queres limpiar el bit OERR no podes borrar el bit solo ese , tenes que desactivr la recepcion y activarla:
Overrun bit OERR has to be cleared in software. This is done by resetting the receive logic (CREN is cleared and then set).
-
Hola,
gracias por responder. Algunos comentarios sobre lo que dices:
- Activas las interrupciones y luego haces el setup de los modulos, siempre configura todo primero, activa la interrupcion del modulo en el PIE, limpia el flag luego activar el PIE, y luego al final de todas las configuraciones activa las interrupciones globales y de perifericos. Si no me equivoco cuando activas la interrupcion del PIE se pone a 1 el flag, lo cual tenes que leer y descartar el dato de RCREG
A qué te refieres con limpiar el flag? Si es a RCIF, ese bit es de sólo lectura y se resetea al vaciar el valor de RCREG. Voy a intentar lo que dices de cambiar el orden.
- A la rutina de interrupcion le falta lo de guardar y reponer W, STATUS, PCLATH. Esto esta en el datasheet, Sin nada en el loop no es problema, pero con algo dentro significa que si lo vas a tener.
No entiendo a qué te refieres...
- Si queres limpiar el bit OERR no podes borrar el bit solo ese , tenes que desactivr la recepcion y activarla:
Overrun bit OERR has to be cleared in software. This is done by resetting the receive logic (CREN is cleared and then set).
OK
Saludos
-
A qué te refieres con limpiar el flag? Si es a RCIF, ese bit es de sólo lectura y se resetea al vaciar el valor de RCREG. Voy a intentar lo que dices de cambiar el orden.
Si pero te decia que lo limpies (leyendo RCREG por mas que no tenga nada) DESPUES de activar el bit de PIE y ANTES de activar la interrupcion global y de perifericos,
No entiendo a qué te refieres...
Busca en el datasheet W_TEMP, ahi esta explicado que es y por que se debe hacer. (Aunque aca no te va a afectar en nada )
O leerte en esta parte ( donde dice: Rutina de Servicio de Interrupciones):
http://www.todopic.com.ar/foros/index.php?topic=24720.msg201405#msg201405
-
Hola,
hice lo que me dices y sigo recibiendo datos sin sentido :(
-
Tu programa esta bien, no tiene nada de malo. Si corregiste eso no veo problemas, a no ser que sea un problema de Proteus. En proteus podes seleccionar correctamente 31250 de baud rate ?
Si no usa un valor mas conocido como: 19200
En el cual necesitas, para el cristal de 20Mhz:
BGRH = 1
SPBGR = 64
-------------
Es lo unico que se me ocurre..
-
Tu programa esta bien, no tiene nada de malo. Si corregiste eso no veo problemas, a no ser que sea un problema de Proteus. En proteus podes seleccionar correctamente 31250 de baud rate ?
Si no usa un valor mas conocido como: 19200
En el cual necesitas, para el cristal de 20Mhz:
BGRH = 1
SPBGR = 64
-------------
Es lo unico que se me ocurre..
Hola,
Proteus no tiene esa velocidad de transmisión, por eso uso el Serial Midi Converter.
Como no resulta, ahora estoy probando transmisión desde un módulo serial con la velocidad que me indicas. Aún sigo con problemas, pero estoy intentando aislarlos. Hice algunas modificaciones y ahora recibo un solo dato a 19200 baudios y después de eso espero un segundo para encender un led y terminar la rutina. El resultado que tengo es que recibo un valor sin sentido pero el led final nunca se enciende... eso quiere decir que hay algún problema después de la recepción, pero no se me ocurre qué.
Acá dejo el código nuevo:
#INCLUDE <P16F874A.INC>
__CONFIG _CP_OFF &_HS_OSC &_PWRTE_OFF &_BODEN_OFF &_WDT_OFF &_LVP_OFF &_WRT_OFF ;relacionado con la palabra de configuracion del micro.
cblock 0x20
d1
d2
d3
; TOROB
TEMP
endc
ORG 0x00
goto MAIN
ORG 0x04
goto INT
MAIN
;INICIALIZACION
;BANK 0
BCF STATUS, RP0
BCF STATUS, RP1
BSF RCSTA,SPEN ;SE HABILITA PUERTO SERIAL
BSF RCSTA,CREN ;SE HABILITA RECEPCION
CLRF PORTB ;PORTB=0
;BANK 1
BSF STATUS, RP0
CLRF TRISB ;PUERTO B SALIDA
;CLRF TRISD
BSF TRISC,7 ;ENTRADA SERIAL
BCF TRISC,0 ;BIT DE MONITOREO RECEPCION
;BCF TRISC,1
BCF TRISC,2 ;BIT DE MONITOREO DE ERROR
BSF TXSTA,BRGH ;1=HIGH 0=LOW
MOVLW .64 ;BAUD RATE DE PRUEBA=19200
;MOVLW 0X09 ;SET BAUD RATE (20M/64(9+1)=31250)
MOVWF SPBRG
BCF TXSTA,SYNC ;ASYNCHRONOUS
BSF PIE1,RCIE ;SE HABILITA INTERRUPCION DE RX
;;BANK 0
BCF STATUS,RP0
MOVF RCREG,W ;RESET DE FLAG
MOVF RCREG,W ;RESET DE FLAG
MOVF RCREG,W ;RESET DE FLAG
;BANK 1
BSF STATUS,RP0
BSF INTCON,GIE ;SE HABILITAN INTERRUPCIONES
BSF INTCON,PEIE
;BANK0
BCF STATUS,RP0
; CALL DELAY
BCF PORTC,0 ;BIT DE MONITOREO RX = 0
BCF PORTC,1 ;BIT DE FIN
LOOP
NOP
; CALL DELAY
GOTO LOOP
INT
; BSF PORTC,0 ;SI SE RECIBE DATO SE ACTIVA PORTC,0
BTFSC RCSTA,1 ;SE REVISA OVERRUN ERROR
GOTO ERR
GOTO NORM
ERR BSF PORTC,2 ;SE INDICA ERROR EN PORTC,2
btfss PIR1,RCIF ;espera al proximo caracter
goto ERR
btfsc RCSTA,OERR
call BORR_ERR ;Error de Sobreescritura
btfsc RCSTA,FERR
call BORR_ERR ;Error de Trama
bcf PIR1,RCIF ;borra el flag de interrupcion por caracter recibido
GOTO BCK
BORR_ERR
bcf RCSTA,CREN ;deshabilita recepcion usart
movf RCREG,W
movf RCREG,W
movf RCREG,W
bsf RCSTA,CREN ;habilita recepcion usart
return
NORM
MOVF RCREG,W ;SE CARGA DATO RECIBIDO EN W
MOVWF PORTB ;SE TRASPASA DATO RECIBIDO A PORTB
BSF PORTC,0 ;SI SE RECIBE DATO SE ACTIVA PORTC,0
; BCF PORTC,1
CALL DELAY
BCF RCSTA,CREN ;SE DESHABILITA RECEPCION
; BCF PORTC,0
; BCF PORTC,2
BSF PORTC,1
BCK RETFIE
DELAY
; Delay = 1 seconds
; Clock frequency = 20 MHz
; Actual delay = 1 seconds = 5000000 cycles
; Error = 0 %
;5000000 cycles
movlw 0x2D
movwf d1
movlw 0xE7
movwf d2
movlw 0x0B
movwf d3
Delay_0
decfsz d1, f
goto $+2
decfsz d2, f
goto $+2
decfsz d3, f
goto Delay_0
RETURN
END
Saludos
-
ya encontré el error.
Lo del led que no encendía era que no quité el comentario a la habilitación de ese bit como salida (BCF TRISC,1).
Respecto a la comunicación serial, era un error en Proteus. No cambié la velocidad de transmisión en COMPIM :oops:
Ahora estoy intentando la comunicación con midi, algo similar debe ocurrir...
Saludos