Recursos del PIC- Comunicación serie entre dos PICs con la USART
Comunicar dos pic’s entre si vía serie RS-232 haciendo uso del modulo USART (Universal Synchronous / Asynchronous Receiver Transmiter.)
MICROCONTROLADORES
Biblioman
11/2/20096 min leer
En este ejemplo vamos a ver como comunicar dos pic’s entre si vía serie RS-232 haciendo uso del modulo USART (Universal Synchronous / Asynchronous Receiver Transmiter.), que incorporan la mayoría de los PIC’s de la gama media / alta. Con este modulo hardware se puede implementar una comunicación serie del tipo sincrona ó asíncrona.
Sincrona: necesita una conexión adicional para la señal de reloj. Una Usart hace de Master y la otra de esclava. La comunicación es del tipo halfduplex (bidireccional por turnos). Se emplea cuando se quiere comunicar un PIC con otro dispositivo electrónico, como una memoria EEPROM externa.
Asincrona: no se necesita una conexión para la señal de reloj, los relojes del transmisor y del receptor son independientes, aunque deben de tener la misma frecuencia, la sincronización entre ambos se hace añadiendo unos bits adicionales (bit de inicio y bit de parada) al byte de datos, que puede estar formado por 8 ó 9 bits. La comunicación puede llegar a ser hasta dúplex completo (bidireccional simultanea). Este tipo de conexión es la que se utiliza normalmente para comunicar un PIC con un Ordenador ó para comunicar dos PIC’S entre sí, es la más usada y es la que vamos a ver a continuación como ejemplo.
Ya hemos visto como CCS gestiona una comunicación serie a través de la directiva
#users232 (lista de parámetros)
Esta directiva se puede poner en cualquier parte del programa pero siempre después de:
#usedelay(Frecuencia)
Si nuestro PIC no tiene USART como es el caso del PIC 16f84A, CCS nos implementa la comunicación serie por software y de forma totalmente transparente para el programador. Sin embargo el utilizar un PIC con USART nos permite disponer de una serie de funcionalidades adicionales, como el empleo de interrupciones para controlar el envío y recepción de datos serie.
Si queremos realizar una comunicación serie utilizando la USART del Pic, las conexiones tendrán que ser a la fuerza las siguientes: RC6/TX/CK para la transmisión de datos y RC7/RX/DT para la recepción de datos, según se muestra en la figura de abajo.
Los registros del PIC implicados en este recurso son los siguientes:
PIR1 –> Registro para señalizaciones ó banderas.
RCSTA –> Registro para el control de la parte receptora de la USART
TXREG –> Registro de datos de transmisión
SPBRG –> Registro para el control del generador de frecuencia, encargado de generar la frecuencia en baudios para realizar la transmisión.
TXSTA –> Registro para el control de la parte de transmisión de la USART
PIE1 –> Habilitación de interrupciones
RCREG --> Registro de datos de recepción
El circuito del ejemplo será es el siguiente:
El pic U1 hará de pic transmisor de datos, se encargará de comprobar si se pulsa alguna tecla en el teclado y en el caso de que así sea, mandará el valor del carácter (1 byte) de la tecla pulsada, correspondiente al código del teclado. El segundo PIC implementará en su código una interrupción por recepción de datos serie en la USART, recibirá el carácter procedente de U1 y visualizará su valor en un display de siete segmentos de cátodo común.
Código del programa
Al haber dos pic’s tendremos que hacer dos programas independientes, uno para el transmisor y otro para el receptor.
Transmisor:
/*--------------------------------------------------------*
| Comunicación entre dos PIC's por USART. Transmisor |
| autor: biblioman |
*--------------------------------------------------------*/
#include <16F877.h>
#FUSES NOWDT, XT, NOPUT, NOPROTECT, NOBROWNOUT, NOLVP, NOCPD, NOWRT, NODEBUG
#use delay (clock = 4000000)
#include "kbd_2.c"
#use rs232(uart1, baud=9600)//usart1 -->ajuste de XMIT y RCV para la USART 1
void main() {
char c;
kbd_init(); //inizializo drivers teclado
while(true)
{
c = kbd_getc();
if(c != 0 )//si se ha pulsado una tecla
{
putc(c);//Envía el caracter vía serie por la USART del PIC
}
}
}
Comentario
En la parte del código del transmisor incluimos una librería nueva:
#include "kbd_2.c"
Esta librería es una modificación de KBDD.c que incluye CCS en la carpeta Drivers, creada en la instalación del programa. La que viene por defecto controla un teclado de 4 (filas) X 3 (Columnas). La modificación que he hecho permite controlar un teclado de 4 X 4.
Viendo el código original es fácil hacer las modificaciones pertinentes para poder controlar un teclado personalizado.
Solo son necesarias dos funciones para utilizar esta librería que son:
kbd_init(); //inicializa el drivers del teclado.
kbd_getc();//devuelve el código ASCII de la tecla pulsada, si no se pulsa ninguna devuelve 0.
El uso de estas librerías tiene un problema y es que tienen copyright, si vemos el comentario en el encabezado, nos encontramos con esto:
Que nos viene a decir, entre otras cosas, que podemos crear programas derivados de este software y distribuir el código objeto generado al compilar pero no se puede distribuir el código fuente. Por lo que este es el motivo de no mostrar la modificación hecha sobre esta librería.
Para que os funcione el ejemplo al completo tendréis que modificar la librería para que sea capaz de controlar el teclado 4X4 ó modificar el circuito para tener un teclado de 4X3.
Otra novedad de este ejemplo son los parámetros de configuración de la directiva:
#use rs232(uart1, baud=9600)//usart1 -->ajuste de XMIT y RCV para la USART 1
En el caso de utilizar la USART del pic, CCS nos permite configurar fácilmente el bit de transmisión (XMIT) y el bit de recepción (RCV) dentro de la directiva #use rs232, el “1” es porque hay PIC,s que tienen más de una USART.
Luego el programa entra en un bucle infinito para ir chequeando en cada momento si se ha pulsado alguna tecla. Si detecta que se ha pulsado alguna tecla, envía el valor de la tecla pulsada por el canal serie por medio de la finción putc().
Receptor:
/*--------------------------------------------------------*
| Comunicación entre dos PIC's por USART. Receptor |
| autor: biblioman |
*--------------------------------------------------------*/
#include <16F877.h>
#FUSES NOWDT, XT, NOPUT, NOPROTECT, NOBROWNOUT, NOLVP, NOCPD, NOWRT, NODEBUG
#use delay (clock = 4000000)
#byte puerto_D = 0x08
#use rs232(uart1, baud=9600)
char dato;
#int_rda
void rd_isr(void)//función de interrupción por recepción de datos USART
{
dato= getc();
switch(dato)//visualizo el caracter recibido en el display
{
case '0':
puerto_D = 0x3F;
break;
case '1':
puerto_D = 0x06;
break;
case '2':
puerto_D = 0x5B;
break;
case '3':
puerto_D = 0x4F;
break;
case '4':
puerto_D = 0x66;
break;
case '5':
puerto_D = 0x6D;
break;
case '6':
puerto_D = 0x7D;
break;
case '7':
puerto_D = 0x07;
break;
case '8':
puerto_D = 0x7F;
break;
case '9':
puerto_D = 0x6F;
break;
case 'A':
puerto_D = 0xF7;
break;
case 'B':
puerto_D = 0x7C;
break;
case 'C':
puerto_D = 0x58;
break;
case 'D':
puerto_D = 0x5E;
break;
case 'E':
puerto_D = 0x79;
break;
case 'F':
puerto_D = 0x71;
break;
default:
break;
}
}
void main()
{
enable_interrupts(global);//Habilito interrupción USART
enable_interrupts(int_rda);
set_tris_d( 0x00 ); // Puerto D como salida.
puerto_D =0x00; //inicializo puerto D
while(true){
//Código principal
}
}
Comentario
En la parte del código del receptor se utiliza el recurso de interrupción por recepción de datos de la USART. Si utilizamos el asistente para crear el proyecto del receptor, tendremos que marcar la opción que se muestra en la figura de abajo.
Cuando se produce la interrupción se obtiene el carácter recibido por medio de la función getc(), después por medio de la sentencia switch se obtiene la salida para el display en el puerto D en función del valor recibido.
Como siempre podemos ejecutar el programa paso a paso con Proteus y ver como CCS configura los diferentes registros del PIC implicados en la comunicación serie.
En la figura de arriba se muestra por medio de la ventana Watch Windows como se pone a 1 el bit RCIF (flag de interrupción por recepción de datos en la USART) del registro PIR1 en el momento que se entra en la función de interrupción.
Nota: Realmente en este ejemplo la comunicación es unidireccional (simplex), ya que el PIC U2 no transmite datos solo recibe los datos procedente de U1, por lo que la conexión que une la patilla de transmisión de U2 con la de recepción de U1 se podría suprimir en el circuito.
Aquí tenéis un pequeño video del programa funcionando: