Tengo un problema con una comunicacion entre el PIC y el PC. El programa que tengo se encarga de enviar via serie la conversion de los canales ADC con caracter de cabecera y de fin previa peticion del pc. El pc le envia 3 bytes, una cabecera el dato (orden de conversion) y un checksum que es la suma de los dos anteriores.Haciendo pruebas veo que llega bien todo, que lo mete bien en el buffer y que luego lo lee bien. El problema es a la hora de contestar, que comprobando que el registro TXREG es escrito y que TXSTA esta bien configurado a la hora de transmitir del pic no sale nada de nada. La placa esta bien y el pic tambien poque he probado el mismo programa pero enviando a saco sin peticion alguna del pc y si que envia.
Posteo el codigo por si algun alma caritativa le quiere echar un vistazo y darme algun consejo.
Codigo:
list p=16f873 ;list directive to define processor
#include <p16f873.inc> ;processor specific definitions
errorlevel -302 ;suppress "not in bank 0" message
__CONFIG _CP_OFF & _WDT_OFF & _BODEN_OFF & _PWRTE_ON & _XT_OSC & _LVP_ON & _DEBUG_OFF & _CPD_OFF
RxDATO equ 0x20
rflgs equ 0x21
rdat equ 0x22
cksum equ 0x23
Bufferdata equ 0x24
RxEndPtr equ 0x25
RxStartPtr equ 0x26
Flags equ 0x27
STX equ 0x4A
TX_BUF_LEN equ .80 ;Longitud del buffer circular de transmision
RX_BUF_LEN equ TX_BUF_LEN ;Longitud del buffer circular de recepcion
;Definiciones de bit del byte Flags
TxBuflleno equ 0 ;Bit que indica que el buffer de transmision esta lleno
TxBufvacio equ 1 ;Bit que indica que el buffer de transmision esta vacio
RxBuflleno equ 2 ;Bit que indica que el buffer de recepcion esta lleno
RxBufvacio equ 3 ;Bit que indica que el buffer de recepcion esta vacio
CRrecibido equ 4 ;Bit que indica que se ha recibido un retorno de carro
int equ 5 ;Bit que indica si se ha producido una interrupcion por recepcion
;Definiciones de bit del byte rflgs
pakerr equ 0 ;error de paquete
newpac equ 1 ;paquete completado
newData equ 2 ;nuevo dato recibido
newtype equ 4 ;tipo recibido
newseq equ 5 ;seq recibida
newlen equ 6 ;len recibido
newSTX equ 7 ;cabecera recibida
CBLOCK 0x70
WREG_TEMP ;Almacenamiento de W durante la interrupcion
STATUS_TEMP
PCLATH_TEMP
FSR_TEMP
FLAGS
ENDC
;Buffer de transmision
CBLOCK 0x2F
TxBuffer:TX_BUF_LEN
ENDC
;Buffer de recepcion
CBLOCK 0xAF
RxBuffer:RX_BUF_LEN
ENDC
org 0x0000 ;Vector de Reset
goto Inicio
org 0x0004 ;Salva vector de interrupción
isr
movwf WREG_TEMP
movf STATUS,W
clrf STATUS
movwf STATUS_TEMP
movf PCLATH,W
movwf PCLATH_TEMP
clrf PCLATH
movf FSR,W
movwf FSR_TEMP
btfss PIR1,RCIF ;¿Interrupcion por recepcion?
goto finisr ;NO.salir
bcf PIR1,RCIF ;Limpiar flag de recepcion
movf RCREG,W
movwf rdat ;Guardamos dato recibido en la variable RxDato
; movwf PORTB
bsf FLAGS,int
; bsf PORTB,0
;Coge los datos recibidos y los mete en el buffer de recepcion, previa comprobacion de la trama
GetData
;======================= 1º Comprobar si ETX es correcto ===============================
pacrec1 btfsc rflgs,newSTX ;STX recibido ya? si no,saltar siguiente
goto pacrec2 ;Sí,
movlw STX ;No.Es el STX correcto?
subwf rdat,w
btfss STATUS,Z ;Si sí,saltar siguiente
goto finisr ;No.Salir de la interrupcion,se deshecha toda la trama
bsf rflgs,newSTX ;Sí.setear flag de cabecera recibida
movf rdat,w ;Metemos el STX en el checksum
addwf cksum,f ;Añadirlo al checksum
goto finisr
;====================== 2º Meter el dato en el buffer ========================
pacrec2 btfsc rflgs,newData ;Datos de canales recibidos ya?
goto pacrec3 ;Sí,ir a comprobar el checksum
bsf rflgs,newData ;No.Setear flag de datos recibidos
addwf cksum,f ;Sumar el dato al checksum
goto PutRxBuffer ;Meterlo en el buffer de recepción
;===================== 3º Comprobar Checksum =================================
pacrec3 movf rdat,w ;Metemos el dato recibido en w
subwf cksum,w ;Comprobar si el checksum recibido es correcto
btfss STATUS,Z ;Si no son iguales.Saltar instruccion
goto finisr ;Salimos de la interrupcion
bsf rflgs,newpac ;seteamos flag de paquete completo recibido
goto finisr
PutRxBuffer
bcf STATUS,RP0 ;banco 0 de memoria
BANKISEL RxBuffer
movwf Bufferdata ;guarda el contenido de w en la variable bufferdata
movf RxEndPtr,w ;cogemos Endpointer
movwf FSR ;y lo cargamos en FSR
movf Bufferdata,w ;cogemos el contenido de bufferdata
movwf INDF ;y lo metemos en la posicion del buffer apuntada por endpointer.
;Comprobamos si el puntero del buffer necesita apuntar al inicio del buffer
movlw LOW RxBuffer+RX_BUF_LEN-1 ;Cogemos la ultima posicion del buffer
xorwf RxEndPtr,w ;y lo comparamos con endpointer
movlw LOW RxBuffer ;Cargamos primera direccion del buffer
btfss STATUS,Z ;Comprobamos si el puntero apunta a la ultima direccion
incf RxEndPtr,w ;Si no, entonces incrementamos el puntero
movwf RxEndPtr ;Almacenamos nuevo valor del endpointer
finisr
movf FSR_TEMP,W
movwf FSR
movf PCLATH_TEMP,W
movwf PCLATH
movf STATUS_TEMP,W
movwf STATUS
swapf WREG_TEMP,F
swapf WREG_TEMP,W
retfie
;****************Lectura de los datos****************
Lectura
Banksel ADRESH
movf ADRESH,W
return
;********************************************************************************************
;Tx_Dato: Transmite vía serie el dato presente en el reg. W
Tx_Dato btfss PIR1,TXIF
goto Tx_Dato
bcf PIR1,TXIF ;Restaura el flag del transmisor
movwf TXREG ;Almacena el byte a transmitir
bsf STATUS,RP0
Tx_Dato_Wait btfss TXSTA,TRMT ;Byte transmitido ??
goto Tx_Dato_Wait ;No, esperar
bcf STATUS,RP0
; bsf PORTB,1
return ;Si
;*******************************************************************************************
;Programa principal
Inicio clrwdt
clrf PORTC
bsf STATUS,RP0 ;Selecciona banco 1
movlw b"00000000"
movwf ADCON1 ;RA0-RA3 analógicas, Vref=Vcc, alineación izq.
movlw b"11111111"
movwf TRISA ;Puerta A entrada
movlw b"00000000"
movwf TRISB ;Puerta B salida
movlw b"10111111"
movwf TRISC ;RC7/Rx entrada, RC6/Tx salida
movlw b"11001111"
movwf OPTION_REG ;Preescaler de 128 asociado al WDT
movlw b"00100100"
movwf TXSTA ;TX en On, modo asíncrono con 8 bits y alta velocidad
movlw .25
movwf SPBRG ;9600 baudios con Fosc=4MHz
movlw 0xC0
movwf INTCON
bsf PIE1,RCIE ;Habilita interrupcion en recepcion
bcf STATUS,RP0 ;Selecciona banco 0
bsf RCSTA,SPEN ;USART en On
bsf RCSTA,CREN ;Recepcion continua
;El ADC trabaja a Fosc/8
movlw b"01000001"
movwf ADCON0 ;ADC en On
movlw 0x00
movwf PORTB
clrf rflgs
clrf cksum
clrf Flags
;================== Inicialización del buffer de recepción ======================
InitRxBuffer
bcf STATUS,RP0
movlw LOW RxBuffer ;Coge la dirección del buffer de recepción
movwf RxStartPtr ;y la depositamos en el puntero de inicio
movwf RxEndPtr ;y la depositamos en el puntero de fin
bcf Flags,RxBufvacio
bcf Flags,RxBuflleno
Loop
btfss rflgs,newpac ;Esperamos a que toda la trama haya llegado bien
goto Loop
call GetRxBuffer
movwf RxDATO
movlw 0x4C
subwf RxDATO,W ;Comprobamos que el dato recibido correponde con la orden de conversion
btfss STATUS,Z ;Si Z=1 salta ya que son iguales
goto Loop ;Espera a que la recepcion sea correcta es decir solo convierte una vez a peticion del PC.
btfss FLAGS,int ;Conversion por disparo
goto Loop ;El flag int dice si se ha producido interrupcion, es decir si se ha pedido desde el PC que convierta.
;Si si convierte y envia.Si no se queda esperando a dicha orden
movlw 0x4A
call Tx_Dato
movf TXREG,W
bcf STATUS,RP0
movwf PORTB
clrwdt
bcf PIR1,ADIF ;Restaura el flag del conversor
movlw b"01000001"
movwf ADCON0
nop
bsf ADCON0,GO ;Inicia conversión del canal 0
ADC0_Wait btfss PIR1,ADIF ;Fin de conversión ??
goto ADC0_Wait ;No, esperar
call Lectura ;Lee el valor de la conversión
call Tx_Dato ;Salida por RS232
bcf PIR1,ADIF ;Restaura el flag del conversor
movlw b"01001001"
movwf ADCON0
nop
bsf ADCON0,GO ;Inicia conversión del canal 1
ADC1_Wait btfss PIR1,ADIF ;Fin de conversión ??
goto ADC1_Wait ;No, esperar
call Lectura ;Lee el valor de la conversión
call Tx_Dato ;Salida por RS232
bcf PIR1,ADIF ;Restaura el flag del conversor
movlw b"01010001"
movwf ADCON0
nop
bsf ADCON0,GO ;Inicia conversión del canal 2
ADC2_Wait btfss PIR1,ADIF ;Fin de conversión ??;
goto ADC2_Wait ;No, esperar
call Lectura ;Lee el valor de la conversión
call Tx_Dato ;Salida por RS232
bcf PIR1,ADIF ;Restaura el flag del conversor
movlw b"01011001"
movwf ADCON0
nop
bsf ADCON0,GO ;Inicia conversión del canal 3
ADC3_Wait btfss PIR1,ADIF ;Fin de conversión ??
goto ADC3_Wait ;No, esperar
call Lectura ;Lee el valor de la conversión
call Tx_Dato ;Salida por RS232
movlw 0x0D
call Tx_Dato ;Transmite CR (Retorno de carro)
bcf FLAGS,int
clrf rflgs
goto Loop
;------------------ Quita y devuelve en w el byte que hay en el inicio del buffer------------
GetRxBuffer
bcf STATUS,RP0
btfsc Flags,RxBufvacio ;Comprueba si el buffer de recepcion esta vacio
nop ;Aqui iria una llamada a un rutina de tratamiento de error
bsf STATUS,RP0
bcf PIE1,RCIE ;Deshabilitar interrupcion por recepcion
bcf STATUS,RP0
BANKISEL RxBuffer ;Bit del banco para direccionamiento indirecto
movf RxStartPtr,w ;Cogemos StartPointer
movwf FSR ;y lo depositamos en FSR
;Comprobamos si el puntero del buffer necesita apuntar al comienzo del buffer de memoria
movlw LOW RxBuffer+RX_BUF_LEN-1 ;Cogemos la ultima posicion del buffer de memoria
xorwf RxStartPtr,w ;y la comparamos con el puntero de inicio
movlw LOW RxBuffer ;Cargamos primera direccion de buffer
btfss STATUS,Z ;Comprobamos si el puntero esta en la ultima direccion del buffer
incf RxStartPtr,W ;Si no, incrementar puntero
movwf RxStartPtr ;almacenar nuevo valor del puntero
bcf Flags,RxBuflleno ;el buffer no puede estar vacio
movf INDF,W ;Cogemos el dato del buffer
bsf STATUS,RP0
bsf PIE1,RCIE ;Habilitamos interrupcion por recepcion
bcf STATUS,RP0
return
end ;Fin del programa fuente
Saludos y gracias de antemano.