Hola;
He estado revisando el programa y no veo porqué no funciona.
Si hay un error grave en usart_bufer() y, es que la defines con veinte elementos que son nombrados del 0 al 19, y tu escribes en el 20, este ultimo elemento no pertenece al vector y al escribir en el estas sobre escribiendo posiblemente una variable del sistema o tuya misma, normalmente esto produce cuelgues y cosas raras.
Lo mismo te pasa en la lectura de la variable en la rutina de interrupciones, en este caso como es lectura no afecta, pero también te sales del vector.
Otro tema es que se recomienda poner la rutina de interrupciones después de todas las demás rutinas.
He simplificado la rutina de interrupciones ya que haces operaciones redundantes.
El uso de Hserget ya borra la bandera de interrupciones de la usart cuando el bufer del módulo queda vacío.
Aunque Gosub/Return ya quedaron obsoletos en este lenguaje, la estructura del programa está correcta.
Por otro lado el uso de Gosub/Return ahorra memoria de stack que en esta familia de microcontroladores es de solo 8 niveles.
Para el bucle For:
Cada vez que se ejecuta un bucle For de nuevo, su variable asociada se hace 0 de forma automática.
Define CONF_WORD = 0x3f01
'Pic 16f628A opcion servos con relé
Define CLOCK_FREQUENCY = 4
'Define SIMULATION_WAITMS_VALUE = 1
Define SEROUT_DELAYUS = 0
'Definición de puertos
Symbol servo1 = PORTA.2
Symbol servo2 = PORTA.3
Symbol servo3 = PORTA.1
Symbol servo4 = PORTA.0
'Symbol bot_desv1 = PORTA.1
'Symbol bot_desv2 = PORTA.3
'Symbol bot_desv3 = PORTA.7
'Symbol bot_desv4 = PORTA.5
Symbol control1 = PORTB.7
Symbol control2 = PORTB.6
Symbol control3 = PORTB.4
Symbol control4 = PORTB.3
Symbol tx_485_enable = PORTB.5
'Definicion entradas-salidas
AllDigital 'todos los pines digitales
TRISA = %11100000
TRISB = %11011010
Dim fin_transmision As Byte
Dim bytes_bufer As Byte
Dim usart_imagen(20) As Byte
Dim usart_bufer(20) As Byte
Dim n As Byte
Dim n_usart As Byte
Dim nombre As Byte
fin_transmision = "!"
bytes_bufer = 0
n_usart = 0
Gosub usart_activa_rx
WaitMs 500 'pausa para estabilizar la entrada
'------------------------------------INICIO DEL PUERTO SERIE, TIMER E INTERRUPCONES------------------
Hseropen 9600 'Velocidad del puerto serie e inicializa los comandos de bajo nivel que controlan la USART
INTCON.PEIE = 1 'bit de habilitacion de interrupciones de perifericos(USART), para que funcione la implementación P. SERIE
PIE1.RCIE = 1 'Activa la interrupcion de la USART en modo rx
Enable
INTCON.GIE = 1 'habilita todas las interrupciones globales
'--------------------------------------Inicio Programa--------------------------------------------------
Gosub clear_bufer 'Borra el BUFER IMAGEN y por lo tanto tambien al USART, OBLIGATORIO POR LO MENOS UNA VEZ
WaitMs 500
main:
If control1 = 1 Then
WaitMs 100
While control1 = 1
Wend
servo1 = 1
WaitMs 1000
servo1 = 0
WaitMs 1000
Endif
If control2 = 1 Then
WaitMs 100
While control2 = 1
Wend
servo2 = 1
WaitMs 1000
servo2 = 0
WaitMs 1000
Endif
If control3 = 1 Then
WaitMs 100
While control3 = 1
Wend
servo3 = 1
WaitMs 1000
servo3 = 0
WaitMs 1000
Endif
If control4 = 1 Then
WaitMs 100
While control4 = 1
Wend
servo4 = 1
WaitMs 1000
servo4 = 0
WaitMs 1000
Endif
Goto main
End
'Subrutinas -----------------------------------------------
usart_activa_rx:
WaitMs 100
tx_485_enable = 0
WaitMs 50
Return
usart_activa_tx:
WaitMs 100
tx_485_enable = 1
WaitMs 50
Return
clear_bufer:
For n = 0 To 1 'desbloquea el puerto serie fisico en caso de bloqueo por exceso de entrada de datos
PIE1.RCIE = 0 'deshabilita la interrupcion del modulo serie
RCSTA.CREN = 0 'protocolo de desbloqueo puerto serie
RCSTA.CREN = 1 'protocolo de desbloqueo puerto serie
RCSTA.OERR = 0 'protocolo de desbloqueo puerto serie
Next n
Gosub clearbufer 'borra el bufer por soft de los datos recibidos por el puerto serie
PIR1.RCIF = 0 'borra el flag de salto de la usart
PIE1.RCIE = 1 'activa la interrupcion de la USART en modo rx
Return
clearbufer: 'BORRA E INICIALIZA EL BUFER IMAGEN DEL PUERTO SERIE
Dim c_serial As Byte
For c_serial = 0 To 19 'pasa por cada uno de los bytes del bufer (de 0 a 19 = 20 elementos)
usart_bufer(c_serial) = 0 'borra bytes del bufer apuntador,
'que nos indica si esa posición del bufer tiene datos
Next c_serial 'repite hasta el total del bufer
c_serial = 0 '(Cada vez que se ejecuta el For, c_serial se hace 0 de forma automática)
Return
On Interrupt 'Comienzan las rutinas de las interrupciones (desactiva todas las interrupciones).
Save System 'Guarda los valores del sistema
Hserget usart_bufer(n_usart)
If usart_bufer(n_usart) > 0 and n_usart < 20 Then ' (para n_usart de 0 a 19 = 20 elementos)
nombre = usart_bufer(n_usart)
n_usart = n_usart + 1
Endif
Resume '(Activa las interrupciones de nuevo)