Comunicación RS232
Prueba de conexión serie entre un PIC y una PC
Circuito convertidor serie-paralelo para el port serie de la PC

por Eduardo J. Carletti

Presento aquí la prueba de laboratorio de un circuito realizado específicamente para experimentar, de manera básica, con la comunicación entre un microcontrolador PIC 16F628A y el puerto serie de una PC (estándar RS-232). El circuito tiene, además del microcontrolador, un integrado convertidor de niveles RS232 a TTL que es reemplazo del conocido MAX232, pero cuesta más barato en el mercado argentino. Se trata del HIN232CP de Intersil.

Integrado HIN232CP: Los circuitos con letra T son "Transmitters", que trasladan nivel TTL/CMOS en su entrada a nivel RS232 en su salida. Los circuitos con letra R son "Receivers", que trasladan señales RS232 en su entrada (que pueden ser de hasta +30/-30 V) a nivel TTL/CMOS en su salida.

Aquí voy a hacer una pequeña disgresión sobre por qué utilizo el PIC 16F628A en esta ocasión y en gran parte de los proyectos que encaro y encararé, excepto cuando las prestaciones de este microcontrolador no sean suficientes para la función requerida. La razón principal es que es pata a pata compatible con el más antiguo pero ya clásico PIC 16F84A. Y es compatible en sus programas, con la única salvedad de que la memoria RAM se encuenta en otra dirección. Transformar un programa hecho para el PIC 16F84A para utilizarlo en este microcontrolador es una cosa de segundos. Y hay miles de ejemplos en Internet y en libros y revistas para el 16F84A, porque hace años que se diseña sobre él, como procesador básico.

Distribución de patas (con sus funciones) del PIC 16F628A.

El PIC 16F84A puede estar muy bien como elección para comenzar, pero la única razón que va quedando para hacerlo es que la mayoría de los ejemplos de programa y de circuito que se encuentran por allí están realizados sobre él. En base a lo dicho en el párrafo anterior, entonces el PIC 16F628A es igual de elegible, ya que es un reemplazo prácticamente directo de nuestro famoso microcontrolador "de batalla". ¿Pero por qué cambiar, si ambos están disponibles en el mercado? Por una razón muy simple: el PIC 16F628A tiene más memoria de programa (el doble), más RAM, más EEPROM, más modos de uso, más timers, y más prestaciones, incluyendo la que aprovechamos en este diseño, el puerto serie implementado por hardware... y el PIC 16F628A, por lo menos en Argentina, cuesta menos... ¿Por qué no cambiar, entonces?

COMPARACIÓN
 16F84A16F628A
Memoria programa1K2K
Memoria datos68 bytes224 bytes
EEPROM64 bytes128 bytes
Timers13
PWM-1
Reg. comparación/captura-
Comparadores-2
Referencias de voltaje-1
Oscilador interno reloj-37 KHz / 4 MHz
Patas usables E/S1316
Programación a bajo voltaje-

Ahora volvamos al circuito de esta prueba

El microcontrolador se comunica utilizando su puerto serie. He programado este puerto a una velocidad de 9600 baudios, un formato de dato de 8 bits, sin paridad, un bit de parada, y sin ningún control de flujo. El programa en el microcontrolador se inicia enviando un mensaje a la PC que dice Hola amigo. Luego la rutina principal de este pequeño programa espera a recibir un caracter, lo devuelve como eco hacia la PC, y luego lo exhibe a través de sus puertos, donde tenemos conectados LEDs indicadores. Esto nos permite comprobar la recepción de los caracteres ASCII desde la PC, cuyo código veremos sobre los LEDs. También hace que nuestro circuito cumpla la función de transformar la salida serie de la PC en una salida de 8 bits en paralelo.

A continuación se puede observar los circuitos que he utilizado:

Circuito del interfaz de comunicación RS232 entre un PIC y una PC

Módulo adaptador USB - TTL


Algún lector observador habrá notado que no se utiliza el Puerto A completo (1 byte) para manejar los LEDs que exhiben el caracter que se ha recibido desde la PC. Los bits 4 y 5 del Puerto A no se utilizan, y a cambio los LEDs que corresponden a estos bits se conectan al Puerto B. ¿Por qué complicarse así? ¿No es mejor escribir un byte completo en un puerto, sin tener que manejar dos bits por separado en otro puerto, que para peor tiene dos bits afectados a la comunicación serie?

Paciencia, todo tiene su explicación: Tal como se ha configurado el microcontrolador, el Puerto A tiene, efectivamente, ocho bits de ancho, pero por características de circuito no se pueden utilizar los ocho como salida. El bit 5 solamente se puede utilizar como entrada, y el bit 4 tiene un circuito de salida de drenaje abierto, es decir, cuando está en alto no entrega corriente, de manera que no encendería el LED con el circuito que estamos utilizando. Antes que ponerme a hacer algunos malabarismos con el circuito, preferí solucionar esto por programa y "sacar" los dos bits faltantes a través del Puerto B, bits 4 y 5. El "costo" de esta solución son tres o cuatro líneas de programa, nada más.

Montaje del circuito de conexión serie entre un PIC 16F628A y una PC

Detalle de montaje del circuito de conexión serie


Programa


;*******************************************************************
; INTERFAZ SERIE RS232 - ECO Y DISPLAY EN LEDS
; CONVERTIDOR SERIE RS232 - PARALELO 8 BITS
;*******************************************************************

        LIST P=16F628, R=DEC    ; Usar el PIC16F628 y sistema decimal

        #include "P16F628A.INC"  ; Incluye datos de PIC16F628A

	—CONFIG   _CP_OFF & _WDT_OFF & _LVP_OFF & _PWRTE_ON & _INTRC_OSC_NOCLKOUT & _MCLRE_OFF

;*******************************************************************
; CONFIGURACION
;*******************************************************************

; El PIC es configurado para usar todas las entradas y salidas 
; posibles = 16. Por eso no se usa el oscilador con cristal externo, 
; lo que deja libres las patas 15 y 16 para usar como bits de puerto. 
; Se define el clock interno a 4 MHz. No se usa el master reset 
; (pata 4), que queda convertida en el Puerto A, bit 5 (entrada).

;*******************************************************************
; VARIABLES
;*******************************************************************

contador	EQU	0x28	; variable
dato_serie	EQU	0x29	; dato serie desde la PC

;*******************************************************************

        ORG    0x000            ; El programa empieza en 0x000 

;*******************************************************************
; Inhibe comparadores
;*******************************************************************

	movlw 7
	movwf CMCON		; CMCON=7 inhibir los comparadores
 
;*******************************************************************
; Inicializar Puertos
;*******************************************************************
 
	movlw b'00000000'       ; valor inicial portA
        movwf PORTA
        movlw b'00000000'       ; valor inicial portB
        movwf PORTB

        bsf STATUS,RP0          ; Pág 1 RAM

        movlw b'00000000'
        movwf TRISA		; salidas (para mostrar el dato en LEDS)
				; de estas salidas, no usaremos
				; PORTA 4, que tiene salida open drain, y 
				; PORTA 5, que sólo puede ser entrada

        movlw b'11001011'	; RB0 entrada
				; RB1 (RX) = entrada
				; RB2 (TX) = salida
				; RB3 = entrada 
				; RB2 = salida del bit 4 del dato a LEDS
				; RB5 = salida del bit 5 del dato a LEDS
				; RB6 y RB7 = entradas
        movwf TRISB

;*******************************************************************
; BAUD RATE para la comunicación RS232
; y otras definiciones para USART
;*******************************************************************
; Baud Rate = 9600, Sin Paridad, 1 Bit parada
;
        movlw 0x19              ; 0x19=9600 bps (0x0C=19200 bps)
        movwf SPBRG
        movlw b'00100100'       ; 
        movwf TXSTA             ; habilita la transmisión Async

        bcf STATUS,RP0          ; RAM PAGE 0

        movlw b'10010000'       ; habilita de recepción Async
        movwf RCSTA

;*******************************************************************
; TIEMPO DE ESTABILIZACION
;*******************************************************************

        clrf contador
estab	decfsz contador,F
        goto estab

        movf RCREG,W
        movf RCREG,W
        movf RCREG,W            ; vacía el buffer de recepción

	call Bienvenida        	; envía mensaje de bienvenida

;*******************************************************************
; LAZO PRINCIPAL
;*******************************************************************

loop    
	clrw
	btfss PIR1,RCIF         ; (5) se fija si hay dato RS232
	goto loop		; no, no llegó
	call recibeRS232	; sí, hay
	movwf dato_serie	; guarda dato (para uso de cualquier rutina)
	call enviaRS232		; envía el eco a la PC
	call muestra		; muestra el caracter recibido en LEDS
	goto loop

;*******************************************************************
; RECIBE CARACTER SERIE - RS232 - DESDE LA PC
;*******************************************************************

recibeRS232
        movf RCREG,W            ; guarda dato recibido en acumulador 
        return

;*******************************************************************
; ENVIA CARACTER SERIE - RS232 - A LA PC Y ESPERA A QUE HAYA SALIDO
;*******************************************************************

enviaRS232
	movwf TXREG             ; envío el dato en acunulador w
	bsf STATUS,RP0		; Pág 1 RAM
Espere 	btfss TXSTA,TRMT        ; transmision completa si es alto
       	goto Espere
       	bcf STATUS,RP0          ; Pág 0 RAM
       	return

;*******************************************************************
; MUESTRA DATO
;*******************************************************************

muestra
	movf dato_serie,w	; recupera el dato guardado
	movwf PORTA		; exhibe el dato en LEDS en PORTA
	btfss dato_serie,4	; pero, como el PORTA tiene el bit 4 que es
	bcf PORTB,4		; open drain, nos conviene poner
	btfsc dato_serie,4	; el bit 4 del dato en otra salida;
	bsf PORTB,4		; lo hacemos en el bit 4 del PORTB.
	btfss dato_serie,5	; y , como el PORTA tiene el bit 5 que es
	bcf PORTB,5		; sólo usable como entrada, tenemos que poner
	btfsc dato_serie,5	; el bit 5 del dato en alguna salida;
	bsf PORTB,5		; lo hacemos en el bit 5 del PORTB.
	return

;*******************************************************************
; MENSAJES
;*******************************************************************

Bienvenida
	; los primeros caracteres 0x00 son 
	; para estabilización del circuito
	movlw 	0x00
	call	enviaRS232
	movlw 	0x00
	call	enviaRS232
	movlw 	0x00
	call	enviaRS232
	movlw 	0x00
	call	enviaRS232
	movlw 	0x00
	call	enviaRS232
	call	msgCR
	movlw 	'H'
	call	enviaRS232
	movlw 	'o'
	call	enviaRS232
	movlw 	'l'
	call	enviaRS232
	movlw 	'a'
	call	enviaRS232
	movlw 	' '
	call	enviaRS232
	movlw 	'a'
	call	enviaRS232
	movlw 	'm'
	call	enviaRS232
	movlw 	'i'
	call	enviaRS232
	movlw 	'g'
	call	enviaRS232
	movlw 	'o'
	call	enviaRS232
msgCR
	movlw 	0x0D
	call	enviaRS232
	movlw 	0x0A
	goto	enviaRS232

        END

Bajar el programa en formato ASM (puede usar el botón derecho de su mouse)

Bajar el programa en formato HEX (puede usar el botón derecho de su mouse)

Por las dudas, el archivo incluido P16f628a.inc (puede usar el botón derecho de su mouse)

Programa a utilizar en la PC

Para establecer la comunicación serie desde la PC, se debe utilizar un programa de Terminal. Sugerimos uno simple que puede bajar desde AQUÍ (en este caso se llama PARALLAX SERIAL TERMINAL (PST.exe, no necesita instalación), o cualquier otra aplicación de terminal serie básica que usted desee. Cópielo en una carpeta o en su escritorio y cree un ícono de acceso directo en su escritorio o donde usted desee.

Programa PARALLAX SERIAL TERMINAL (PST.exe)

Los valores que se utilizan en esta comunicación son:
  • Bits por segundo = 9600
  • Bits de datos = 8
  • Paridad = Ninguna
  • Bits de parada = 1
  • Control de flujo = Ninguno

Con PST.exe sólo deberá definir los Bits por segundo (además de conectarse al puerto COM, ver el Breve Manual de uso.


A partir de Windows 7 y 8 el programa HyperTerminal no está disponible.
Utilice un programa de terminal como el que sugerimos arriba

Uso del programa "HyperTerminal" para la comunicación desde la PC

Para establecer la comunicación serie desde la PC, se debe utilizar el programa HyperTerminal que viene con el sistema operativo Windows, o cualquier otra aplicación de terminal básica que usted desee.

Aquí se puede ver una explicación de Microsoft sobre cómo utilizar el programa HyperTerminal.

En la configuración de la conexión, usted debe indicar que se va a conectar "Directo a COM", indicando cuál es el puerto COM de la PC que va a utilizar en esta comunicación (generalmente es el COM1... pero cada PC es un mundo aparte).

Esto se define en la sección "Configurar".

  • Bits por segundo = 9600
  • Bits de datos = 8
  • Paridad = Ninguna
  • Bits de parada = 1
  • Control de flujo = Ninguno

Ver las imágenes. (A la izquierda, las propiedades de la conexión nombrada por mí como "robots", a la derecha, la pantallita "Configurar" del puerto elegido en esta conexión, el COM1).


Algunas cosas que observé

  • El uso de los bits de puerto adicionales del PIC 16F628A —luego de convertir por configuración las líneas para el cristal del oscilador de reloj y la de Master Clear en bits del Puerto A— me causó, al principio, algunos problemas. En concreto, el de los bits 4 y 5 del Puerto A, tema ya explicado arriba. Esto demuestra que se debe leer bien la hoja de datos y nunca dar nada por sobreentendido. La conclusión es que si se utiliza el puerto serie interno del PIC 16F628A (que ocupa dos bits en el Puerto B) no hay disponible, lamentablemente, un puerto completo para manejar un byte entero de salida. No sé si es muy importante, pero en la programación se hace un poco más engorroso "sacar" un byte entero.
  • Por lo dicho en el punto anterior, si se desea utilizar de algún modo un byte de salida en paralelo que no sea para exhibirlo en LEDs, se debe implementar un pulso de aviso (strobe) que anuncie que el dato es válido, ya que este byte de salida se actualiza por partes.
  • El programa es básico y no tiene ninguna comprobación de confirmaciones en el protocolo de comunicación, así que si se envían datos a mucha velocidad desde la PC se pueden perder datos e incluso puede quedar "colgado" el PIC, situación que a mí no se me ha presentado... pero puede pasar.
  • Según todas las teorías, usando esta configuración en la que se genera internamente un pulso de reloj de 4 MHZ sin cristal, podría haber algún problema de corrimiento de la frecuencia del reloj y, por ende, de la velocidad de transferencia del puerto serie del PIC (baudios). Sin embargo, no he notado dificultades de comunicación.
  • No es difícil implementar esta comunicación por interrupción, tarea que encararé en una próxima prueba. No quise hacerlo aquí para no complicar un ejemplo que, a mi entender, debe ser básico.