Buenas este es mi primer post y espero ir no muy a saco con la pregunta.
Veamos estoy intentando comunicar un pic16f873a con el PC, el pc le envia una trama de 4 bytes al micro para que empiece a capturar por el ADC y este cuando acaba le responde al pc con una trama de 7 bytes.El programa de comunicacion esta hecho en visualbasic y va bien pq midiendo directamente en el puerto del pc con el oscilo se ven los bytes perfectamente y ademas he metido un sniffer del puerto serie que me saca perfectos tb los 4 bytes de la trama.El problema es,que el micro solo recibe el primer byte, de los otros ni se inmuta.he usado interrupciones, he salvado los registros usados antes de la int,velocidad 9600( lo tipico) lo he repasado mil veces, para que no haya overrun me he creado dos buffers, uno de recepcion y otro de transmision , no se que puede pasar y ya me estoy volviendo loco, aqui os pego el codigo bien comentado por si alguien le echa un vistazo y encuentra algo raro,Gracias
**********************************************************
;Zona de datos
__CONFIG _CP_OFF & _WDT_OFF & _PWRTE_ON & _XT_OSC
LIST P=16F873
INCLUDE <P16F873.INC>
RxBuf EQU 20H
TxBuf EQU 2AH
STX EQU 4AH
ETX EQU 4BH
ord1 EQU 4CH
ord2 EQU 4DH
ord3 EQU 4EH
ord4 EQU 4FH
ord5 EQU 50H
Canal EQU 51H
ord EQU 52H
RxPunt EQU 53H
TxPunt EQU 54H
STATUS_TEMP EQU 55H ;Almacenamiento de STATUS durante la interrupcion
WREG_TEMP EQU 56H ;Almacenamiento de W durante la interrupcion
FSR_TEMP EQU 57H ;Almacenamiento de FSR durante la interrupcion
;Zona de codigos
ORG 0
goto Inicio
ORG 4
goto INT_SER
Inicio
clrf PORTA
clrf PORTB
clrf PORTC
bsf STATUS,RP0 ;Cambio al banco 1
bcf STATUS,RP1
clrf TRISB ;Puerto B como salida
clrf TRISA ;Puerto A como salida
movlw b"00101111"
movwf TRISA ;RA0,RA1,RA2,RA3 y RA5 entradas analogicas
movlw b"10011111" ;RC7/Rx entrada,
movwf TRISC ;RC6/Tx salida y RC5 Salida.
movlw b"00100100" ;Configuracion USART
movwf TXSTA ;y activacion de transmision
movlw .25 ;9600 baudios
movwf SPBRG
movlw b"11000000"
movwf INTCON ;Habilitamos todas las interrupciones
movlw b"00000001" ;justificacion del resultado de la conv a la izq. es decir en ADRESH
movwf ADCON1
bsf PIE1,RCIE ;Habilitacion interrupcion RX
bsf PIE1,TXIE ;Habilitacion interrupcion TX
bcf STATUS,RP0 ;Vuelta al banco 0
movlw b"01000001" ;seleccion Tad, canales para
movwf ADCON0 ;conversion y A/D=ON
movlw b"10010000" ;Configuracion de la usart
movwf RCSTA ;para recepcion continua
movlw .32 ;inicializacion de los punteros del buffer
movwf RxPunt
movlw .42
movwf TxPunt
Principal
movlw .0 ;
subwf ord,W ;Comprobamos la orden de conversion,si ord es <> de 0 salta a comprobar si es otra orden
btfsc STATUS,Z ;Si Z=0,salta ya que no son iguales
goto Principal ;En todo momento esta a la espera de que salta la int por recepcion
conv_01
movlw .5
subwf ord,W ;Comprobamos si es la orden 5
btfsc STATUS,Z ;Si no son iguales se va a comprobar otra orden
goto ord_05 ;Si son iguales se va a ejecutar la orden de conversion 5
conv_02
movlw .1 ;Comprobamos si es la orden 1
subwf ord,W
btfsc STATUS,Z ;Si no son iguales se va a comprobar otra ordem
goto ord_01 ;Si son iguales se va a ejecutar esa orden
conv_03
movlw .2 ;Comprobamos si es la orden 2 de conversion
subwf ord,W
btfsc STATUS,Z ;Si no son iguales se va a comprobar otra orden
goto ord_02 ;Si lo son ejecuta la orden de conversion 2
conv_04
movlw .3
subwf ord,W
btfsc STATUS,Z
goto ord_03
conv_05
movlw .4
subwf ord,W
btfsc STATUS,Z
goto ord_04
conv_06
movlw .5
subwf ord,W
btfss STATUS,W
goto Principal
ord_05
movlw TxBuf+1 ;Adquirimos la señal de los 4 canales
movwf FSR
movlw .1 ;y los resultados de la conversion los vamos metiendo
movwf Canal ;en su respectiva posicion del buffer de transmision
call Conversion
movf ADRESH,W
movwf INDF
incf FSR,F
movlw .2
movwf Canal
call Conversion
movf ADRESH,W
movwf INDF
incf FSR,F
movlw .3
movwf Canal
call Conversion
movf ADRESH,W
movwf INDF
incf FSR,F
movlw .4
movwf Canal
call Conversion
movf ADRESH,W
movwf INDF
goto prc_tra
ord_01
movlw TxBuf+1
movwf FSR
movlw .1
movwf Canal
call Conversion
movf ADRESH,W
movwf INDF
incf FSR,F
movlw .0
movwf INDF
incf FSR,F
movlw .0
movwf INDF
incf FSR,F
movlw .0
movwf INDF
goto prc_tra
ord_02
movlw TxBuf+1
movwf FSR
movlw .0
movwf INDF
incf FSR,F
movlw .2
movwf Canal
call Conversion
movf ADRESH,W
movwf INDF
incf FSR,F
movlw .0
movwf INDF
incf FSR,F
movlw .0
movwf INDF
incf FSR,F
movlw .0
movwf INDF
goto prc_tra
ord_03
movlw TxBuf+1
movwf FSR
movlw .0
movwf INDF
incf FSR,F
movlw .0
movwf INDF
incf FSR,F
movlw .3
movwf Canal
call Conversion
movf ADRESH,W
movwf INDF
incf FSR,F
movlw .0
movwf INDF
goto prc_tra
ord_04 ;Como solo queremos adquirir el canal 4
movlw TxBuf+1 ;El segundo (el primero sera STX) byte correspondiente al primer canal
movwf FSR
movlw .0 ;lo rellenamos con 0, y asi sucesivamente hasta el cuarto
movwf INDF
incf FSR,F
movlw .0
movwf INDF
incf FSR,F
movlw .0
movwf INDF
incf FSR,F
movlw .4 ;Este canal si que lo vamos a adquirir
movwf Canal ;Seleccionamos canal del ADC
call Conversion ;y el resultado lo metemos en la 5ºpos del buffer que correponde con la
movf ADRESH,W ; 5º pos en la trama a enviar al pc
movwf INDF
prc_tra ;preparamos trama a enviar al PC
clrf ord
movlw STX ;Ponemos byte STX en primera pos del buffer de transmision
movwf TxBuf
addwf TxBuf+1,W ;Calculamos el checksum que equivale a la suma del resultado
addwf TxBuf+2,W ; de la conversion de todos los canales
addwf TxBuf+3,W
addwf TxBuf+4,W
movwf TxBuf+5 ;y el byte checksum lo metemos en la quinta pos. del buffer
movlw ETX
movwf TxBuf+6 ;el byte de fin de trama ETX lo metemos en la 6º posicion del buffer
movf TxPunt,W ;El puntero del buffer que ha sido inicializado al a primera posicion del buffer
movwf FSR ;va señalando en cada momento el byte que es enviado
movf INDF,W ;asi hasta que ha recorrido todo el buffer de transmision
movwf TXREG
incf TxPunt,F
goto Principal
;Subrutina de conversion
Conversion
bcf STATUS,RP0
bcf STATUS,RP1 ;Cambio a la banco 0
movlw b"01000001" ;Valor por defecto para que despues podamos hacer la iorwf
movwf ADCON0
rlf Canal,F
rlf Canal,F
rlf Canal,W
iorwf ADCON0,F
rrf Canal,F
rrf Canal,F
bcf PIR1,ADIF ;Restaurar flag de peticion de int.del conversor
nop
nop
bsf ADCON0,GO ;Iniciamos conversion
espera
btfss PIR1,ADIF ;¿Ha terminado?
goto espera ;No.esperar
return
INT_SER
movwf WREG_TEMP ;Salvamos el estado actual de los registros criticos para recuperarlos luego
swapf STATUS,W
movwf STATUS_TEMP
movf FSR,W
movwf FSR_TEMP
btfss PIR1,RCIF ;¿Interrupcion por recepcion?
goto TRANSM ;No,se va a transmision
Recep bcf PIR1,RCIF ;Repone flag de peticion de interrupcion por recep.
movf RxPunt,W ;
movwf FSR
movf RCREG,W ;pasamos el dato recibido al registro de trabajo
movwf INDF ;guardamos el dato en el buffer de recepcion,en la direccion apuntada por FSR)direccionamiento indirecto)
; movwf PORTB
incf RxPunt,F ;apuntamos a la siguiente poiscion del buffer de recepcion
movlw RxBuf+4
subwf RxPunt,W
btfss STATUS,Z ;Comparamos si ha llegado toda la trama.Osea comparar si a donde apunta FSR es igual a la cuarta posicion
;del buffer
goto FISER ;Si no ha llegado toda la trama it a final de la interrupcion
;Si si que ha llegado,analiza la trama
Analizar
movlw .32
movwf RxPunt ;Ponemos el puntero de recepcion en su posicion inicial
movlw STX ;Pone primer caracter de trama
subwf RxBuf,W ;Comprobamos STX
btfss STATUS,Z
goto FISER ;sino son iguales se va a final de la int.
movlw ETX
; movwf PORTB
subwf RxBuf+3,W ;Comprobamos ETX
btfss STATUS,Z
goto FISER ;Si STX y ETX coinciden con el sus respectivos patrones y estan en la posicion correcta de la trama
movf RxBuf,W ; que se ha ido metiendo en el buffer de recpecion, pasamos a calcular el checksum y a comprobar si coincide tambien
addwf RxBuf+1,W ;Se calcula el checksum, que es la suma de ETX mas la orden de conversion
subwf RxBuf+2,W
btfss STATUS,Z ;Comprobamos chk
goto FISER ;Si el checksum no coincide salimos de la int.
;si la trama que ha llegado es correcta comprobamos cual de las 4 ordenes se ha recibido
RECEP1 movlw ord1 ;si es la orden 1 la recibida , quiere decir que solo vamos a adquirir del canal 1
subwf RxBuf+1,W
btfss STATUS,Z
goto RECEP3 ;Sino es la orden 1 la recibida pues pasamos a ver si es otra orden
movlw .1 ;si si que es,la guarda en la variable ord.Entonces en la rutina principal vera que ord es <> de 0 y
movwf ord ;se ira a la rutina de conversion llamando al canal 1( 0 en el pic)
goto FISER
RECEP3
movlw ord2
subwf RxBuf+1,W
btfss STATUS,Z ;Comprobamos si la orden recibida es la 2
goto RECEP4
movlw .2 ;en caso afirmativo guardamos el valor de la orden den converscion en la variable ord
movwf ord
goto FISER
RECEP4
movlw ord3 ;Comprobamos si la orden recibida es la 3
subwf RxBuf+1,W
btfss STATUS,Z
goto RECEP5
movlw .3
movwf ord ;En caso afirmativo guarda el valor en la variable ord
goto FISER
RECEP5
movlw ord4 ;Comprobamos si la orden recibida es la 4
subwf RxBuf+1,W
btfss STATUS,Z
goto RECEP6
movlw .4
movwf ord
goto FISER
RECEP6
movlw ord5 ;comprobramos si la orden recibida es la 5
subwf RxBuf+1,W
btfss STATUS,Z
goto FISER
movlw .5 ;en caso afiramtivo la guardamos en la variable ord
movwf ord
goto FISER
TRANSM
bcf PIR1,TXIF ;Restaura flag de transmision
movlw TxBuf+7
subwf TxPunt,W ;Si el puntero de transmision apunta a la posicion 7 del buffer (la ultima es la 6) es que se ha enviado toda la trama
btfsc STATUS,Z ;Comprobamos si se han transmitido todos los bytes
goto subFISER ;En caso afirmativo salimos de la rutina de transm.
movlw TxPunt
movwf FSR
movf INDF,W
movwf TXREG
incf TxPunt
goto FISER
subFISER
movlw .42 ;Antes de salir de la interrupcion por tranmision,despues de haber mandado toda la trama al PC
movwf TxPunt ;inicializamos el buffer de transmision a la primera posicion del buffer de transmision
FISER
movf FSR_TEMP,W
movwf FSR
swapf STATUS_TEMP,W
movwf STATUS
swapf WREG_TEMP,F ;Prepara W para ser restaurado.
swapf WREG_TEMP,W ;Restaura W sin afectar al bit Z de Status.
retfie ;fin interrupcion canal serie.
END
***************************************************
Gracias de antemano