Microcontroladores PIC => Almacén del Assembler => Mensaje iniciado por: cidtepole en 26 de Mayo de 2009, 15:05:15
Título: pic16f877A se resetea de forma inesperada
Publicado por: cidtepole en 26 de Mayo de 2009, 15:05:15
Hola a todos envio un cordial saludo esperando que se encuentren bien. Soy nuevo en el foro y desde hace unos dias he estado involucrado en un proyecto que consiste en el control de un modem para comunicacion TCP/IP. El modem se configura por puerto serial y el microcontrolador por medio del modulo USART es el encargado de hacer estas configuraciones para que se pueda establecer una conexion TCP.
El proyecto es simple consiste en que el pic actue como host del modem donde este ultimo se monta como servidor y se conecta a una red de area local permitiendo al microcontrolador la capacidad de enviar datos sobre una red. El modem permite una comunicacion transparente TCP por su puerto serial despues de que se hayan realizado las configuraciones necesarias.
Una aplicacion cliente en una computadora envia comandos al pic para ejecutar ciertas tareas(como apagar un foco). Casi todo funciona excepto por algo raro que aun no le encuentro explicacion y es por eso que escribo en este foro.
Cuando yo envio un comando para apagar un foco lo hace bien. Si quiero que el modem suspenda la comunicacion y despues la vuelva a reiniciar lo hace bien. En el momento en que le mando un comando para que configure una nueva IP lo hace, pero aqui es donde surge el problema, ya que el pic de forma inesperada se resetea y mi aplicacion cliente ya no puede conectarse a la tarjeta modem del pic. Ya cheque el BROnw y esta en OFF, tambien el perro guardian esta en off. Ademas simulo el programa en PIC Simulator y corre a la perfeccion, tambien ya cheque el codigo y todo luce bien pero talvez yo ya este ciclado y no pueda dar con el error y es por eso que pido su ayuda y comentarios.
No quisiero perder la fe en los microcontroladores de microchip.
A continuacion muestro el codigo he indico en que parte se resetea al programa en letras de color rojo.
__CONFIG 0x1F39
LIST P=16F877A ;Se indica el modo de procesador
INCLUDE <P16f877A.inc> ;se incluye la definicion de los ;registros internos INCLUDE <configuracion.inc>
;#DEFINE retardo_rapido
cblock 0x20 tcpStatus ;estado iniSocket ==>001 ;estado cerrando Socket==>010 ;estado ejecutando comando ==>011 tcpServerFlags ; 7 6 5 4 3 2 1 0 <= tcpServerFlags bits ; | | | | | | | | ; | | | | | | | |___bandera que indica el estado del Socket abierto o cerrado====>0,abierto ; | | | | | | |____bandera que indica si se ejecuto un comando=============>1,ejecutado ; | | | | | |_____bandera que indica si se recivio respuesta del modem=======>2,contesto ; | | | | |______ Waiting for data===================================>3,conectado ; | | | |________Estado de la corriente===============================>4,corriente ; | | |__________ ===============================>5, ; | |___________ ===============================>6, ; |____________ ===============================>7, tareasServer ; 7 6 5 4 3 2 1 0 <= tareasServer bits ; | | | | | | | | ; | | | | | | | |___Ejecutar comando================================>0,comando ; | | | | | | |____Borrar buffer =================================>1,borrar ; | | | | | |_____Encender Rele 1 =================================>2,toglear ; | | | | |______ Encender Rele 2 =================================>3, ; | | | |________Encender Rele 3 ==================================>4, ; | | |__________ ==================================>5, ; | |___________ ==================================>6, ; |____________ ==================================>7, ; Variables para comunicacion errorFlags indiceTx indiceRx char indiceCarga indiceBufferRX ; Almacen temporal usado por el manejador de interrupcion tempW tempStatus tempPclath tempFsr ;Variable animacion luces distancia cont_Ciclos ;Variables auxiliares hold toglearRele endc
;======================================= ; Punteros de los Buffers ;======================================= bufferRX equ 0xA0 ;Buffer de Recepcion de datos bufferCMD equ 0x50 ;Buffer para almacenar un comando AT bufferTemp equ 0x20 ;Buffer para almacenar comandos AT
comando equ 0x00 borrar equ 0x01 toglear equ 0x02 ;********************************************************************** ; Vector de Reset ;********************************************************************** ORG 0x00 ; Inicio en el Vector de Reset goto Inicio ; Va a la primera instruccion del ; programa
;********************************************************************** ; Vector de interrupcion ;********************************************************************** ORG 0x04 ; Inicio en el Vector de Reset goto ISR ; Va a la primera instruccion del ; programa
;********************************************************************************************** ; MAIN ;********************************************************************************************** Inicio iniUSART
banco1 ;Configuramos los puertos clrf TRISB ;Puerto B como salida movlw 0xB movwf TRISA ;Puerto A pines A5-A0 salida A0,A1,A3 banco0
;//////////////////////////////////////////////////////////////////////////////////////// ; Configuramos el ADC A0,A1,A3 como estradas ; analogicas A2,A4 y A5 como digital ;//////////////////////////////////////////////////////////////////////////////////////// bsf STATUS,RP0 ; Seleccionamos el Banco1 para configurar el ADC movlw 0x84 movwf ADCON1 ;Configuramos el ADC bcf STATUS,RP0 ; Seleccionamos el Banco0 movlw 0x41 movwf ADCON0
;//////////////////////////////////////////////////////////////////////////////////////// ; Inicializamos variables ;//////////////////////////////////////////////////////////////////////////////////////// clrf indiceTx ;Inicializamos el indice para el posicionamiento de los caracteres que se envian clrf indiceRx ;y reciven en RAM clrf toglearRele movlw 0x04 ;Inicializamos variable que indica el estado del Servidor (Default) movwf tcpStatus clrf tcpServerFlags call animacion clrf PORTB
movlw 0x02 ;Cambio al estado de posible cierre de Socket movwf tcpStatus
;//////////////////////////////////////////////////////////////////////////////////////// ; Ciclar y monitorear ;//////////////////////////////////////////////////////////////////////////////////////// loopMain btfsc tareasServer,comando call ejecutar btfsc tareasServer,borrar call clrBuffer btfsc tareasServer,toglear call toggle call ReadA_D btfsc tcpServerFlags,abierto ;Ciclar y checar si por algun motivo se cierra el socket goto loopMain goto openSocket
;********************************************************************** ; Interrupcion ;********************************************************************** ISR movwf tempW ; Salvar W movf STATUS,W ; Almacenar STATUS en W movwf tempStatus ; Salvar STATUS movf PCLATH,W ; Almacenar PCLATH en W movwf tempPclath ; Salvar PCLATH clrf PCLATH ; Select program memory page 0 movf FSR,W ; Store FSR in W movwf tempFsr ; Save FSR value banco0 ; Test for received data interrupt btfsc PIR1,RCIF ; Test bit 5 bsf STATUS,RP0 ; Bank 1 if RCIF set btfss PIE1,RCIE ; Test if interrupt is enabled goto IntExit ; Go if not enabled banco0
; Test for overrun and framing errors. ; Bit 1 (OERR) of the RCSTA register detects overrun ; Bit 2 (FERR) of the RCSTA register detects framing error btfsc RCSTA,OERR ; Test for overrun error goto OverErr ; Error handler btfsc RCSTA,FERR ; Test for framing error goto FrameErr ; Error handler ;//////////////////////////////////////////////////////////////////////////////////////// ; En este punto no se detecto ningun error ; Received data is in the USART RCREG register movf RCREG,w ; Recivo caracter y lo cargo en el registro de trabajo call AddChar ;//////////////////////////////////////////////////////////////////////////////////////// ; Clear error flags clrf errorFlags goto IntExit OverErr ; Error responses to be made by main code bsf errorFlags,0 ; Bit 0 is overrun error ; Reset system bcf RCSTA,CREN ; Clear continuous receive bit bsf RCSTA,CREN ; Set to re-enable reception goto IntExit FrameErr bsf errorFlags,1 ; Bit 1 is framing error movf RCREG,W ; Read and throw away bad data
;interrupt handler exit IntExit banco0 movf tempFsr,w ; Recupera valor del FSR movwf FSR ; Restaurar en registro movf tempPclath,w ; Recover PCLATH value movwf PCLATH ; Restore in register movf tempStatus,W ; Recover STATUS movwf STATUS ; Restore in register swapf tempW,F ; Swap file register in itself swapf tempW,W ; Restore in register retfie
;********************************************************************** ; Tablas ;********************************************************************** tabla ADDWF PCL,F ; se incrementa el contador de programa DT "AT#LTCPSTART=1",0X0D,0X0A
tabla2 ADDWF PCL,F ; se incrementa el contador de programa DT "Pulso recivido",0X0D,0X0A
tabla3 ADDWF PCL,F ; se incrementa el contador de programa DT "Foco Encendido",0X0D,0X0A
tabla4 ADDWF PCL,F ; se incrementa el contador de programa DT "CMD",0X0D,0X0A
tabla5 ADDWF PCL,F ; se incrementa el contador de programa DT "Foco Apagado",0X0D,0X0A
eco ADDWF PCL,F ; se incrementa el contador de programa DT "eco",0X0D,0X0A
ATW ADDWF PCL,F ; se incrementa el contador de programa DT "AT&W",0X0D,0X0A
IPconfig ADDWF PCL,F ; se incrementa el contador de programa DT "AT#IPADDR=",0X22
GWconfig ADDWF PCL,F ; se incrementa el contador de programa DT "AT#IPGATEWAY=",0X22
NMconfig ADDWF PCL,F ; se incrementa el contador de programa DT "AT#IPNETMASK=",0X22
agregar movf indiceRx,W addlw bufferRX ;Puntero del Buffer +indice movwf FSR movf char,W movwf INDF ;Guardamos el caracter en el buffer incf indiceRx,F goto fin
;//////////////////////////////////////////////////////////////////////////////////////// ; CARRY RETURN ;//////////////////////////////////////////////////////////////////////////////////////// CarrieReturn movf indiceRx,W addlw bufferRX-1;Puntero del Buffer +indice movwf FSR movf INDF,W ;Checo si el caracter es la letra K xorlw 0x4B btfss STATUS,Z goto agregar decf FSR,F ;Nos posicionamos en el caracter indice-1 movf INDF,W ;Checo si el caracter es la letra O xorlw 0x4F btfss STATUS,Z goto agregar
movlw 0x01 xorwf tcpStatus,W ;Estoy en el estado de apertura de Socket btfss STATUS,Z ;no voy al sigiente OK goto OKclosed bsf tcpServerFlags,abierto ;Si estoy en el estado de apertura movlw 0x05 ;realizo las tareas necesarias movwf PORTB ;indico que se puede establecer una conexion bsf tcpServerFlags,contesto ;el modem si contesto call clrBuffer ;Limpio el Buffer goto fin
OKclosed movlw 0x02 xorwf tcpStatus,W btfss STATUS,Z ;Estoy en el estado de cierre de Socket goto OKcomando movlw 0x04 movwf PORTB bcf tcpServerFlags,conectado bcf tcpServerFlags,abierto goto fin
OKcomando movlw 0x03 xorwf tcpStatus,W btfss STATUS,Z ;Estoy en el estado de ejecucion de comando goto $+3 bsf tcpServerFlags,ejecutado bsf tcpServerFlags,contesto ;call clrBuffer goto fin
;//////////////////////////////////////////////////////////////////////////////////////// ; ON_OFFRele ;//////////////////////////////////////////////////////////////////////////////////////// ON_OFFRele movf indiceRx,W addlw bufferRX-1;Puntero del Buffer +indice movwf FSR movlw 0x31 ;Checamos si llego un '1' xorwf INDF,W btfsc STATUS,Z goto uno movlw 0x32 ;Checamos si llego un '2' xorwf INDF,W btfsc STATUS,Z goto dos movlw 0x33 ;Checamos si llego un '3' xorwf INDF,W btfsc STATUS,Z goto tres goto agregar uno movlw 0x04 movwf toglearRele bsf tareasServer,toglear goto fin dos movlw 0x10 movwf toglearRele bsf tareasServer,toglear goto fin tres movlw 0x20 movwf toglearRele bsf tareasServer,toglear goto fin
;//////////////////////////////////////////////////////////////////////////////////////// ; ERROR ;//////////////////////////////////////////////////////////////////////////////////////// E btfsc tcpServerFlags,abierto goto agregar bsf tareasServer,borrar bsf tcpServerFlags,contesto goto fin
;//////////////////////////////////////////////////////////////////////////////////////// ; ECO ;//////////////////////////////////////////////////////////////////////////////////////// ECO movf indiceRx,W addlw bufferRX-1;Puntero del Buffer +indice movwf FSR movf INDF,W ;Checo si el caracter es la letra c xorlw 0x63 btfss STATUS,Z goto agregar decf FSR,F ;Nos posicionamos en el caracter indice-1 movf INDF,W ;Checo si el caracter es la letra o xorlw 0x6F ; btfss STATUS,Z goto agregar
clrf indiceTx movf indiceTx,W call eco ;Se carga el caracter que se va enviar call SerialSend;Se envia el caracter incf indiceTx,F ;Se incrementa el indice del siguiente caracter que va hacer enviado movlw 0x05 xorwf indiceTx,W btfss STATUS,Z goto $-7 call clrBuffer goto fin
;//////////////////////////////////////////////////////////////////////////////////////// ; WaitingFordata ;//////////////////////////////////////////////////////////////////////////////////////// WaitingFordata movf indiceRx,W addlw bufferRX-1;Puntero del Buffer +indice movwf FSR movf INDF,W ;Checo si el caracter es la letra c xorlw 0x74 btfss STATUS,Z goto agregar decf FSR,F ;Nos posicionamos en el caracter indice-1 movf INDF,W ;Checo si el caracter es la letra o xorlw 0x61 ; btfss STATUS,Z goto agregar
bsf tcpServerFlags,conectado bsf tareasServer,borrar goto fin
;//////////////////////////////////////////////////////////////////////////////////////// ; CMD ;//////////////////////////////////////////////////////////////////////////////////////// CMD movf indiceRx,W addlw bufferRX-1;Puntero del Buffer +indice movwf FSR movlw 0x4D ;Checamos si llego una 'M' xorwf INDF,W btfss STATUS,Z goto agregar decf FSR,F ;Nos posicionamos en el caracter indice-2 movlw 0x43 xorwf INDF,W btfss STATUS,Z goto agregar
clrf indiceTx movf indiceTx,W call tabla4 ;Se carga el caracter que se va enviar call SerialSend;Se envia el caracter incf indiceTx,F ;Se incrementa el indice del siguiente caracter que va hacer enviado movlw 0x05 xorwf indiceTx,W btfss STATUS,Z goto $-7
movlw 0x02 ;me cambio al estado de cerrando socket movwf tcpStatus bsf tareasServer,comando fin return
;********************************************************************** ; Abrir Socket ;********************************************************************** iniSocket movlw 0x01 ;Cambio al estado de apertura movwf tcpStatus clrf indiceTx movf indiceTx,W call tabla ;Se carga el caracter que se va enviar call SerialSend ;Se envia el caracter incf indiceTx,F ;Se incrementa el indice del siguiente caracter que va hacer enviado movlw 0x0F xorwf indiceTx,W btfss STATUS,Z goto $-7 return
;********************************************************************** ; Transmitir Datos ;********************************************************************** SerialSend banco0 ; Select bank 0 btfss PIR1,TXIF; Checar si el transmisor esta ocupado goto $-1 ; esperar hasta que se desocupe movwf TXREG ; y despues transmitir el dato return
;********************************************************************** ; Imprime mensaje en el puerto serie ;********************************************************************** printF clrf indiceTx movf indiceTx,W call tabla2 ;Se carga el caracter que se va enviar call SerialSend;Se envia el caracter incf indiceTx,F ;Se incrementa el indice del siguiente caracter que va hacer enviado movlw 0x10 xorwf indiceTx,W btfss STATUS,Z goto $-7 return
;********************************************************************** ; Cambiar el estado de los reles ;********************************************************************** toggle btfsc toglearRele,2 call puertob1
btfsc tcpServerFlags,abierto ; Antes de ejecutar los comandos para configurar la IP, GATEWAY y NETMASK goto $-1 ; aseguramos que el Socket se cierre o se desconecte el cliente
movlw 0x03 ; Me cambio al estado de ejecutando movwf tcpStatus
;//////////////////////////////////////////////////////////////////////////////////////// ; Formamos el comando a partir de los caractes en la ; tabla IPconfig y los datos que llegaron en el buffer de ; recepcion(bufferRX) ;//////////////////////////////////////////////////////////////////////////////////////// clrf indiceCarga clrf indiceBufferRX ; movlw bufferCMD ; Apuntamos a la primera posicion del Buffer donde se va alojar la instruccion ; movwf FSR ; que se va a ejecutar ;cicloLoadCMD1 ; movf indiceCarga,W ; Cargamos el n-esimo caracter en el registro W ; call IPconfig ; movwf INDF ; W==>bufferCMD ; xorlw 0x22 ; btfsc STATUS,Z ; Si el caracter son comillas pasar al siguiente ciclo ; goto cicloLoad2 ; incf FSR,F ; bufferCMD++ ; incf indiceCarga,F ; indiceCarga++ ; goto cicloLoadCMD1
cicloLoad2 ;incf indiceCarga,F ; indiceCarga++ movlw bufferRX addwf indiceBufferRX,W ; bufferRX+indiceBufferRX movwf FSR ; Apuntamos a bufferRX+indiceBufferRX movf INDF,W ; Lo que hay en bufferRX+indiceBufferRX lo cargo al regitro de trabajo movwf hold ; y lo paso a hold movlw 'X' xorwf hold,W btfsc STATUS,Z ; Checo si en hold se cargo 'X' y si es asi cargo el resto de los caracteres goto loadRest ; a bufferCMD si no, sigo copiando los caracteres al buffer de envio movlw bufferCMD addwf indiceCarga,W movwf FSR ; Apuntamos a bufferCMD+indiceCarga movf hold,W movwf INDF ; hold==>bufferCMD+indiceCarga incf indiceBufferRX,F incf indiceCarga,F ; indiceCarga++ goto cicloLoad2
btfsc tcpServerFlags,corriente ;Checamos el estado apagado(0)/encendido(1) goto encendido goto apagado
apagado ;Se inicia en el estado de foco apagado btfsc ADRESH,1; ;Si el bit 1 de ADRESH es '1' indica que el dato del ADC es mayor a 2V goto mensaje_on ;y se envia un mensaje btfss ADRESH,0; ;Si el bit 0 de ADRESH es '0' indica que el dato del ADC es menor a 2V goto salir_read ;por lo tanto no se cambia de estado y se sale de la rutina movlw 0x9A ;Se carga al registro de trabajo con el valor 154 banco1 subwf ADRESL,W ; ;154-ADRESL==>W banco0 btfsc STATUS,C ;Si fue negativo el resultado C=1 y por lo tanto 154<ADRESL goto mensaje_on ;y si 154<ADRESL el valor del ADC es mayor a 2V goto salir_read
mensaje_on bcf STATUS,C bsf tcpServerFlags,corriente clrf indiceTx movf indiceTx,W call tabla3 ;Se carga el caracter que se va enviar call SerialSend ;Se envia el caracter incf indiceTx,F ;Se incrementa el indice del siguiente caracter que va hacer enviado movlw 0x10 xorwf indiceTx,W btfss STATUS,Z goto $-7 goto salir_read
mensaje_off bcf tcpServerFlags,corriente clrf indiceTx movf indiceTx,W call tabla5 ;Se carga el caracter que se va enviar call SerialSend ;Se envia el caracter incf indiceTx,F ;Se incrementa el indice del siguiente caracter que va hacer enviado movlw 0x0E xorwf indiceTx,W btfss STATUS,Z goto $-7
Título: Re: pic16f877A se resetea de forma inesperada
Publicado por: sander en 27 de Mayo de 2009, 00:27:58
Saludos cidtepole, bienvenido al foro, por lo que comentas puede que tengas un problema con las interrupciones, he revisado rapidamente el codigo y note que cuando guardas y recuperas algunos registros en la interrupcion haces lo siguiente para el STATUS
Código: ASM
movf STATUS,W ; Almacenar STATUS en W
movwf tempStatus ; Salvar STATUS
;Al recuperar
movf tempStatus,W ; Recover STATUS
movwf STATUS ; Restore in register
El problema con la instruccion movf es que afecta a la bandera Z , por lo que existe el riesgo que guardes un valor incorrecto para la bandera Z, si te fijas haces comparaciones de la bandera Z en la rutina que marcaste con rojo, entonces al salir de la interrupcion estas comparaciones pueden estar dandote resultados erroneos. sustiye esa forma de guardar y recuperar por la siguiente:
Código: ASM
swapf STATUS,W ; Almacenar STATUS en W
movwf tempStatus ; Salvar STATUS
;Al recuperar
swapf tempStatus,W ; Recover STATUS
movwf STATUS ; Restore in register
La instruccion swapf no afecta banderas.
Saludos
Título: Re: pic16f877A se resetea de forma inesperada
Publicado por: cidtepole en 27 de Mayo de 2009, 15:45:10
Gracias Sander por tu ayuda. Ya hice el cambio pero sigo con el mismo problema. Encontre tmb un error en mi codigo en una direccion y ya lo corregi; habia pensado ilusionado que eso era todo el problema pero no, sigo con lo mismo. El error estaba en las ultimas tres lineas marcadas en rojo:
en lugar de tcpServerFlags debi haber utilizado bcf tareasServer,comando, pero como te digo el problema persiste y aun no doy con la solucion. Saludos y espero mas comentarios.
Título: Re: pic16f877A se resetea de forma inesperada
Publicado por: cidtepole en 27 de Mayo de 2009, 20:18:27
Pues fijense que hice una aplicacion en C# donde simulo el modem y envio las respuestas a traves del puerto serie para el pic. Y que creen que paso. :shock: el programa no se resetea y tmb corre a la perfeccion. No se porque con el moden se resetea en ese punto.