Escrito originalmente por nacha4
perdon me olvide de aclarar que esta en un bucle infinito hasta que llega un byte al que es cuando se produce una interrupcion
gracias
En tu código he visto un par de cosas que realmente creo que no funcionan bien.
fijate lo siguiente
Codigo:
movf RCREG,w ;mueve entrada a W
movwf DATORX ;Mueve la entrada a DATORX
PIC movf DATORX,w
andlw 0x0F
subwf b"00000001",w ;Modificar para los siguientes pasos
Fijate, aquí supongo que lo que quieres hacer es comparar el nibble inferior si es igual a 1. Pero tu usas subwf. Esta instrucción espera como parámetro un file register, es decir una posición de memoria. Tu estas comparando con la posición de memoria.
En realidad debieras hacer un sublw ya que tu lo quieres comparar con una constante.
Saludos
Mmmm, veamos que veo ahi en tu código.
1) LUZ4 no lleva a ninguna parte. Lo agregué en tu código ya que sino no compilaba bien.
2) Si usas la declaracion de registros de microchip (esto lo haces cuando haces el include del
PIC16F628.inc) no necesitas declarar los registros STATUS, TRIS, etc.
3) Cambién tus STATUS,5 por STATUS,RPO, y así con otras instrucciones similares. Hacerlo de
esa manera aclara mucho el código.
4) Veo que no has hecho caso para nada a mi consejo anterior! sobre lo de hacer subwf
!!! Ahi sique en tu código.
5) Habiendo cambiado esa línea, incluso tu código así como lo tienes ejecutará 1 vez, ya que
NUNCA vuelves de la interrupcion! Al finalizar la rutina tu haces un "goto bucle" y en
realidad estás con el GIE apagado, esto es porque se apaga automáticamente al ingresar en la
interrupcion
6) No se hacee BCF PIR1,RCIF porque esto se hace "automáticamente" al leer el RCREG.
7) Si solo tienes una interrupción habilitada, no debiera generarse interrupcion por otra
causa. Esto implica que tu chequeo al principio por el FLAG RCIF, es innecesario.
8) Habiendo corregido estas cositas, te paso el código corregido y que a mi me funciona.
Codigo:
LIST P=16F628
Radix HEX
#Include <P16F628.inc>
DATORX equ 0x70 ;dato a recibido
DATOTX equ 0x71 ;dato a trasmitir
ORG 0
GOTO INICIO
ORG 4
GOTO RSI
INICIO bcf STATUS,RP0 ;banco 0
bcf STATUS,RP1
movlw .7
movwf CMCON
BSF STATUS,RP0 ;Banco 1
BCF STATUS,RP1
movlw b"11100010" ;RB1 enntrada resto salida modificar las entradas y salida
menos rb1,rb2
movwf TRISB ;EEESSSES
movlw b"11110000" ;EEEESSSS
movwf TRISA
;ESTA LINEA ESTA DE MAS Y NO LLEVA A NADA --> BORRARLA
movlw b"00100100" ;8bit dato, trasmision activa, modo asincronico
bcf STATUS,RP0
movlw b"11000000" ;Habilito las interrupciones en general
movwf INTCON
BSF STATUS,RP0
movlw b"00100000"
movwf PIE1
BCF STATUS,RP0 ;Banco cero
BSF STATUS,RP0
movlw b"00100100"
movwf TXSTA ;y alta velocidad
movlw d"25" ;se configura SPBRG de 9600 baudios
movwf SPBRG
BCF STATUS,RP0
movlw b"10010000" ;habilito el puerto serie en modo continuo
movwf RCSTA
BUCLE:
GOTO BUCLE ;bucle infinito
RSI
;Estas 2 líneas, tranquilamente podrían ser eliminadas
BTFSS PIR1,RCIF ;Comprueba si la interupcion es por recepcion
retfie ;Cambié el GOTO BUCLE por el RETFIE
;ESTA LINEA ESTA DE MAS Y NO LLEVA A NADA ya que se hace automáticamente --> BORRARLA
; BCF PIR1,RCIF ;se baja el Flag de interrupcion
movf RCREG,w ;mueve entrada a W
movwf DATORX ;Mueve la entrada a DATORX
andlw 0xF0 ;Comprueva si las 4 bit mas significativos
;ESTA LINEA ESTABA MAL... cambié subwf por sublw y eliminé el ,w ya que no es usado en dicha
instrucción
sublw b"00010000" ;Modificar para los siguientes pics
btfsc STATUS,Z
GOTO PIC
retfie ;Cambié el GOTO BUCLE por el RETFIE
PIC movf DATORX,w
andlw 0x0F
;ESTA LINEA ESTABA MAL... cambié subwf por sublw y eliminé el ,w ya que no es usado en dicha
instrucción sublw b"00000001" ;Modificar para los siguientes pasos
sublw b"00000001"
btfsc STATUS,Z
GOTO LUZ4
retfie ;Cambié el GOTO BUCLE por el RETFIE
LUZ4:
retfie ;Linea agregada por mi para que compile bien
end
Creo qeu tu error ocurrió porque has puesto la rutina de atención de interrupción pegada al
código normal y esto te confundió , seguramente pensabas que era un código normal y en
realidad estabas atendiendo una interrupción.
9) Me tomé la libertad de postearte otro código de como organizaría yo el texto de tu
software.
Moví tu rutina de interrupcion a la posicion 0x04. No es "pecado" hacer esto, para nada, es
tan bueno como ponerla en otro lugar. Además hacer un "goto" a una direccion asi sin
almacenar el estado del PLATH, STATUS, etc... te traerá muchos dolores de cabeza cuando uses
un pic mas grande. Esto está documentado en las datasheet donde se habla del "context saving"
cuando usas interrupciones.
Codigo:
LIST P=16F628
Radix HEX
#Include <P16F628.inc>
DATORX equ 0x70 ;dato a recibido
DATOTX equ 0x71 ;dato a trasmitir
ORG 0
goto INICIO
ORG 4
RSI:
movf RCREG,w ;mueve entrada a W
movwf DATORX ;Mueve la entrada a DATORX
andlw 0xF0 ;Comprueba si las 4 bit mas significativos
sublw b"00010000" ;Modificar para los siguientes pics
btfsc STATUS,Z
goto PIC
retfie
PIC
movf DATORX,w
andlw 0x0F
sublw b"00000001"
btfsc STATUS,Z
goto LUZ4
retfie
LUZ4:
retfie
INICIO
bcf STATUS,RP0 ;banco 0
bcf STATUS,RP1
movlw .7
movwf CMCON
BSF STATUS,RP0 ;Banco 1
BCF STATUS,RP1
movlw b"11100010" ;RB1 enntrada resto salida modificar las entradas y salida
menos rb1,rb2
movwf TRISB ;EEESSSES
movlw b"11110000" ;EEEESSSS
movwf TRISA
bcf STATUS,RP0
movlw b"11000000" ;Habilito las interrupciones en general
movwf INTCON
BSF STATUS,RP0
movlw b"00100000"
movwf PIE1
BCF STATUS,RP0 ;Banco cero
BSF STATUS,RP0
movlw b"00100100"
movwf TXSTA ;y alta velocidad
movlw d"25" ;se configura SPBRG de 9600 baudios
movwf SPBRG
BCF STATUS,RP0
movlw b"10010000" ;habilito el puerto serie en modo continuo
movwf RCSTA
BUCLE:
GOTO BUCLE ;bucle infinito
end
Espero se te haya aclarado el tema. Lo probé con el MPLAB 7.3 y me andubo muy bien.
Saludos
Escrito originalmente por nacha4
hola muchas gracias por el programa anda muy bien, tengo una duda porque envio el byte desde la PC con un programa en Visual Basic el Byte lo envia cada ves que hago un click a un boton pero no siempre lo recibe el pic por que puede ser?
para saber si llegaba el bit le agrege
LUZ4 bsf PORTA,1
clrf DATORX
retfie
No es necesario que borres lo que hay en DATORX ya que nunca lo usas y además el proximo byte que leas habrás sobreescrito su contenido.
Lo de que no te salga nada, es raro ya que lo tienes como salida y has apagado los comparadores... tal vez no llegue lo que tu crees que llega!
Lo de que llega o no llega..... digamos que ahí ya no puedo ser adivino. Tu problema también podria estar en el código en visual basic...
Con respecto a que no enciende el led, tal vez con el visual basic tu envias un "1" (el caracter ascii 1) y en el pic estas comparando por el 11h, es decir el 17d que es un caracter de control. Si quieres enviar el "1" en ascii, deberás comparar con el 49d
Escrito originalmente por nacha4
otra cosa que me pasa es como hago para que cada ves que entra un byte determinado cambie el estado de un puerto ej PORTA,0
Para eso antes debes guardar el estado previo del PORTA o bien, hacer
Codigo:
btfsc PORTA,0
goto _BORRAA0
_ENCIENDE0
bsf PORTA,0
retfie
_BORRAA0:
bcf PORTA,0
retfie
Saludos
Escrito originalmente por nacha4
me figura como que contestaste pero no aparece nada
Nacha4
Asi es, el maldito foro se comió mi post!
Ahi va de nuevo.
Aqui te puse un código que cambia levemente de tu codigo a su vez modificado por mi jeje. Este código leera los datos recibidos por la USART y hará titilar un LED ubicado en el PORTA<0> por cada dato recibido (ya sea bien o mal). Recibirá a 9600bps, con Cristal de 4Mhz.
Además permite manejar el error de overrun por cualquier eventualidad.
El error de framing se elimina al leer el dato del RCREG.
Quisiera además pedirte que postees como configuras los Configuration Bits a la hora de grabar tu microcontrolador. Es importante ya que esto podria hacer resetear a tu pic.
Codigo:
LIST P=16F628
Radix HEX
#Include <P16F628.inc>
DATORX equ 0x70 ;dato a recibido
FLAG_AUX equ 0x71 ;registro auxiliar para saber si debo prender o apagar el led
ORG 0
goto INICIO
ORG 4
RSI:
movf RCREG,w ;mueve entrada a W
movwf DATORX ;Mueve la entrada a DATORX
btfsc FLAG_AUX,0
goto APAGALED
ENCIENDELED:
bsf PORTA,0
bsf FLAG_AUX,0
goto CHEQUEO
APAGALED:
bcf PORTA,0
bcf FLAG_AUX,0
CHEQUEO:
retfie
INICIO
bcf STATUS,RP0 ;banco 0
bcf STATUS,RP1
movlw b"01000000" ;Habilito El PEIE
movwf INTCON
movlw .7
movwf CMCON
bsf STATUS,RP0 ;Banco 1
movlw b"11100010" ;RB1 enntrada resto salida modificar las entradas y salida menos rb1,rb2
movwf TRISB ;EEESSSES
movlw b"11110000" ;EEEESSSS
movwf TRISA
movlw b"00000100" ;No enciendo TX Usart porque ahora no se usará
movwf TXSTA ;BRGH = 1
movlw b"00100000"
movwf PIE1
bcf STATUS,RP0
movlw b"10000000" ;habilito el puerto serie en modo continuo
movwf RCSTA
movlw d"25" ;se configura SPBRG de 9600 baudios #4Mhz - BRGH=1
movwf SPBRG
clrf FLAG_AUX
bsf RCSTA,CREN ;Habilito recepcion de usart
bsf INTCON,GIE ;habilito interrupciones grales
BUCLE:
GOTO BUCLE ;bucle infinito
end
Luego comentame los resultados. Si esto funciona sería importante que cablees tambien todo lo relativo a TX para ver si la pc recibe algo.
Luego haremos un software de "eco" que retransmita lo que recibe.
Saludos
Yo te podría resolver el problema y el programa pero si lo hago no aprenderás nada.
Creo que debieras poner algo más de esfuerzo en entender porqué no funciona tu software!
Fijate esto que has puesto:
Codigo:
movf RCREG,w ;mueve entrada a W
movwf DATORX ;Mueve la entrada a DATORX
btfsc FLAG_AUX,1
GOTO enced
GOTO apag
Aqui haces lo siguiente
1) lees el dato del RCREG
2) lo guardas en DATORX
3) Verificas el estado del FLAG Auxiliar y en función de eso apagas o enciendes el LED yendo a las rutinas encend y apag. Las cuales a su vez tienen luego un RETFIE que hacen retornar de la subrutina
Es decir que NUNCA pasaran por la rutina de chequeo de si el nibble superior y/o in ferior son iguales a lo que tu comparas.
Debes primero, no haber insertado esas lineas en donde las insertaste, debes dejar que se complete toda la rutina de encendido y / o apagado del led, esas rutinas no deben tener un RETFIE sino que deben ir a la rutina que compara si el nibble inferior o superior son iguales a lo comparado. Recien ahí haces el RETFIE
No te hago yo el código porque quiero que pongas un poco de atención y dedicación en lo que haces y no te vendría mal "simular" el proceso
Postea tu resultados y veré de seguir ayudandote.
Saludos
Hola nacha4, acá que dejo el firmware completo, debería funcionar bien:
Codigo:
;---------------Encabezado--------------------------------------------------------------------------
LIST P = 16F628A
INCLUDE <P16F628A.INC>
;------------Configuración de bits------------------------------------------------------------------
__CONFIG _BODEN_OFF&_BOREN_OFF&_CP_OFF&_DATA_CP_OFF&_PWRTE_OFF&_WDT_OFF&_LVP_OFF&_MCLRE_OFF&_XT_OSC
; Frecuencia del cuarzo (oscilador del PIC) de 4 Mhz
; Transmición a 9600 Baud asíncrono (9600,8 ,N, 1) 8 bits datos, sin paridad y 1 bit de stop
;------------Definicion de la RAM-------------------------------------------------------------------
WWW EQU .32
ESTADO EQU .33
DATORX EQU .34
;---------------------------------------------------------------------------------------------------
ORG .0 ; vector de RESET
goto INICIO ;
ORG .4 ; vector de INTERRUPCION
goto RSI ;
;---------------------------------------------------------------------------------------------------
RSI
movwf WWW ;
swapf STATUS,W ; esto es necesario para no perder datos
movwf ESTADO ; cuando se produce la interrupccion
movf RCREG,w ; mueve entrada a W
movwf DATORX ; mueve la entrada a DATORX
andlw B"11110000"
sublw B"10010000" ; comprueba los mas significativos
btfss STATUS,Z
goto SALIR ; si los mas significativos no correspondes sale de la interrupcion
movf DATORX,W
andlw B"00001111"
movwf DATORX
incf DATORX,W
addwf PCL,F
nop
goto RUT_0
goto RUT_1
goto RUT_2
goto RUT_3
goto RUT_4
goto RUT_5
goto RUT_6
goto RUT_7
goto RUT_8
goto RUT_9
goto RUT_10
goto RUT_11
goto RUT_12
goto RUT_13
goto RUT_14
goto RUT_15
RUT_0
bsf PORTA,1 ;FUNCION A REALIZAR EN EL CASO DE RECIBIR "XXXX0000"
goto SALIR
RUT_1
;FUNCION A REALIZAR EN EL CASO DE RECIBIR "XXXX0001"
goto SALIR
RUT_2
;FUNCION A REALIZAR EN EL CASO DE RECIBIR "XXXX0010"
goto SALIR
RUT_3
;FUNCION A REALIZAR EN EL CASO DE RECIBIR "XXXX0011"
goto SALIR
RUT_4
;FUNCION A REALIZAR EN EL CASO DE RECIBIR "XXXX0100"
goto SALIR
RUT_5
;FUNCION A REALIZAR EN EL CASO DE RECIBIR "XXXX0101"
goto SALIR
RUT_6
;FUNCION A REALIZAR EN EL CASO DE RECIBIR "XXXX0110"
goto SALIR
RUT_7
;FUNCION A REALIZAR EN EL CASO DE RECIBIR "XXXX0111"
goto SALIR
RUT_8
;FUNCION A REALIZAR EN EL CASO DE RECIBIR "XXXX1000"
goto SALIR
RUT_9
;FUNCION A REALIZAR EN EL CASO DE RECIBIR "XXXX1001"
goto SALIR
RUT_10
;FUNCION A REALIZAR EN EL CASO DE RECIBIR "XXXX1010"
goto SALIR
RUT_11
;FUNCION A REALIZAR EN EL CASO DE RECIBIR "XXXX1011"
goto SALIR
RUT_12
;FUNCION A REALIZAR EN EL CASO DE RECIBIR "XXXX1100"
goto SALIR
RUT_13
;FUNCION A REALIZAR EN EL CASO DE RECIBIR "XXXX1101"
goto SALIR
RUT_14
;FUNCION A REALIZAR EN EL CASO DE RECIBIR "XXXX1110"
goto SALIR
RUT_15
;FUNCION A REALIZAR EN EL CASO DE RECIBIR "XXXX1111"
SALIR
swapf ESTADO,W ;
movwf STATUS ; esto es necesario para no perder datos
swapf WWW,F ; cuando se produce la interrupccion
swapf WWW,W ;
retfie
;---------------------------------------------------------------------------------------------------
INICIO
bcf STATUS,RP0 ; banco 0
bcf STATUS,RP1
clrf PORTA ; limpio el puerto A
clrf PORTB ; limpio el puerto B
movlw .7
movwf CMCON
bsf STATUS,RP0 ; banco 1
movlw B"11110000" ; EEEESSSS
movwf TRISA
movlw B"11100010" ; RB1 enntrada resto salida modificar las entradas y salida menos rb1,rb2
movwf TRISB ; EEESSSES
movlw B"00100000"
movwf PIE1
movlw B"00100100"
movwf TXSTA
movlw .25
movwf SPBRG
bcf STATUS,RP0
movlw B"11000000"
movwf INTCON
movlw B"10010000"
movwf RCSTA
goto $ ; bucle infinito
;---------------------------------------------------------------------------------------------------
END
Donde dice FUNCION A REALIZAR... le colocas la rutina que deseas para cada valor de los 4 bits menos significativos.
Para reconocer una transmisión valida e usado B"1001" para los 4 bits mas significativos.
Espero te sea de utilidad.
Una saludo y suerte.
Atte. CARLOS
Hola nacha4, el firmware que e posteado solo debes compilarlo con el MPLAB abrir el .hex con el programa quemador sin setear nada en este y programar el PIC, como puedes ver la configuración de los osciladores y demás ya esta incluida en el .asm
Este firmware es para un cuarzo de 4 MHz, para que funcione de manera correcta con uno de 20 MHz debes cambiar lo siguiente:
Codigo:
__CONFIG _BODEN_OFF&_BOREN_OFF&_CP_OFF&_DATA_CP_OFF&_PWRTE_OFF&_WDT_OFF&_LVP_OFF&_MCLRE_OFF&_HS_OSC
movlw .129
movwf SPBRG
Si tú PIC es un 16F628 en ves del 16F628A para el cual esta echo este programa solo debes cambiar esto:
Codigo:
LIST P = 16F628
INCLUDE <P16F628.INC>
Por la configuración del USART esa es la que actualmente tengo en uso en un proyecto y anda bien, y la interrupción simulándola en el MPLAB anda de manera correcta.
Cualquier duda solo pregunta.
Espero te sea de ayuda.
Un saludo
Atte. CARLOS