electrónica general y aplicadafing.uncu.edu.ar/catedras/electronica/archivos/proyectos... ·...
TRANSCRIPT
Guía de comunicación serie. Electrónica General y Aplicada. Facultad de Ingeniería UNCuyo
Electrónica General y Aplicada
Guía de Comunicación Serie para el Trabajo Integrador
Introducción
En el proyecto integrador se solicita a los grupos que realicen un automatismo basado en microcontrolador (µC). Éste
puede ser por ejemplo el control de nivel de un tanque, el control de un ascensor, una alarma etc.
Para esto se debe trazar el esquema de conexiones del µC con el sistema a controlar, hacer un programa en un lenguaje
de alto nivel (BASIC, C etc), que se compilará (traducción al lenguaje del µC) y se grabará en el µC.
Este programa debe comprobar las entradas del µC (analógicas o digitales) y activar/desactivar salidas de acuerdo con
un algoritmo y/o una lógica de funcionamiento. Por ejemplo para automatizar un ascensor el programa debe comprobar las entradas conectadas a pulsadores y detectores
de posición, y activar/desactivar las salidas conectadas a los transistores o relés que comandan la marcha del motor en
ambos sentidos.
Esto se puede esquematizar en forma genérica como muestra la figura 1, y consiste en un automatismo no supervisado.
En la industria y en muchos otros ámbitos se procura que los automatismos puedan ser supervisados desde un sistema
central, como una aplicación en una PC (ejemplo un software SCADA, un sistema de tarifación en locutorios etc). Esto se estudiará en las unidades 8 y 9.
Un automatismo supervisado permite que al controlador se le pueda solicitar información, ajustar parámetros e incluso
dar órdenes directas (operación remota). En el automatismo del ascensor, el supervisor podría, por ejemplo:
1. preguntar al µC la cantidad de veces que se accionó el motor, para estadísticas de uso y/o para programar tareas
de mantenimiento.
2. modificar el tiempo durante el cual las puertas deben permanecer abiertas.
3. bloquear un piso determinado (que el ascensor no se pueda detener en ese piso aunque el usuario lo solicite).
4. llevar el ascensor a un piso determinado (operación remota).
5. preguntar en qué piso está el ascensor
6. activar/desactivar el automatismo.
La tarea de supervisión implica entonces el intercambio de información entre el supervisor y el controlador. Podemos reconocer en estos ejemplos que 1 y 5 son solicitudes de información del supervisor que deben ser respondidas
por el controlador, 2 es un parámetro o consigna numérica (tiempo de apertura de puerta) que el supervisor pasa al
controlador, 3 y 4 se pueden considerar también consignas numéricas (piso a bloquear o piso de destino) que el supervisor debe pasar al controlador, mientras que 6 es un cambio de estado o consigna que no requiere parámetros.
Este intercambio se realiza a través de un canal de comunicación serie entre ambos equipos. Ambos equipos deben
disponer entonces de un hardware de comunicación serie compatible, y deben acordar el formato de la información.
El formato de la información se denomina protocolo de comunicación. Como se estudiará en la unidad 8 existe una gran
variedad de protocolos industriales, cada uno con características que lo hacen más o menos apropiado para distintas
aplicaciones.
Desde el año 2009, con el objetivo de integrar la mayor parte de los contenidos de la asignatura en el Trabajo Especial,
procuramos que los grupos deban realizar automatismos supervisados, es decir que incluyan la comunicación entre el µC y la PC.
µC proceso salidas
entradas
µC Rx
proceso PC Tx
Rx
salidas
Tx entradas supervisor controlador
Figura 1. Automatismo no supervisado
Figura 2. Automatismo supervisado
Guía de comunicación serie. Electrónica General y Aplicada. Facultad de Ingeniería UNCuyo
Comunicación entre PC y microcontrolador.
Para implementar el canal de comunicación serie conectaremos un puerto serie de la PC (puerto COM) con un puerto
serie del µC (interfaz UART). Las PC domésticas actuales – portátiles y de escritorio – no disponen de conectores de
estos puertos, por lo que en ese caso utilizaremos un adaptador USB/serie (provisto por la cátedra), que crea un puerto
COM virtual. Si fuera necesario se realizará además la adaptación de niveles eléctricos, como se explicará más adelante.
Como se muestra en la figura 2, los mensajes de la PC al µC van del transmisor (Tx) de la PC al receptor (Rx) del µC, y
los mensajes del µC a la PC van del Tx del µC al Rx de la PC.
Estructura de mensajes.
Como protocolo de comunicación emplearemos un formato de mensajes propio muy sencillo, con las funciones
mínimas para pasar las consignas y solicitudes necesarias, y que sea fácil de interpretar por el µC.
El formato de los mensajes será similar para todos los proyectos. Luego dependiendo de la aplicación cambiarán algunos
elementos.
Mensaje Solicitud (PC µC) Un mensaje tipo solicitud de información tendrá una estructura que comprende la siguiente secuencia de caracteres.
Carácter que indica el inicio de mensaje. Se usará el carácter “:” (ASCII 58)
Número de controlador destinatario. Se usará un dígito de “0” a “9” (ASCII de 48 a 57). Este número es
necesario porque el supervisor podría estar supervisando a muchos controladores a través del mismo canal o
bus, como se verá en la unidad 8. Cada controlador tendrá una “dirección” entre “1” y “9”. La dirección “0” se
reserva para los mensajes que el supervisor quiera enviar simultáneamente a todos los controladores (mensaje de
difusión o broadcasting), por ejemplo para inicializarlos.
Nombre del parámetro o valor solicitado. Se usará una letra, por ejemplo “P” para piso, “T” para tiempo etc. Si
hubiera más de un parámetro similar, por ejemplo más de un tiempo, podrá haber un segundo carácter (letra o
número), por ejemplo “TA”, “T1”, “T2” etc.
Carácter de final. Se usará el carácter denominado “retorno de carro” o CR en inglés (ASCII 13). Es un carácter
no imprimible, que en un teclado se produce cuando se toca la tecla “Enter” o “Intro”.
Así, en el ejemplo del ascensor, para que el supervisor consulte al controlador 3 en qué piso se encuentra el ascensor, el
mensaje podría ser la sucesión de caracteres:
Que en ASCII (expresado en decimal) será
Y expresado en hexadecimal
Mensaje respuesta a solicitud (µC PC) En respuesta al mensaje visto anteriormente, el controlador deberá transmitir un mensaje similar, pero que incluya la
información solicitada, que en el ejemplo anterior sería el valor numérico que corresponde al piso en el que se encuentra
el ascensor. Así, si se encontrara en el piso 14, la respuesta sería:
Es decir, la primera parte idéntica “:3P” y luego los caracteres “1” y “4”. O expresada en ASCII decimal
Mensaje Consigna numérica (PC µC)
Un mensaje tipo consigna numérica será en la primera parte similar al mensaje solicitud, pero agregando el valor
numérico de la consigna, quedando así:
Carácter de inicio “:”
Número de controlador destinatario.
Parámetro o valor a modificar (“P”, “T”, “X” etc).
Valor numérico del parámetro, expresado como cadena decimal.
Carácter de final. Se usará el carácter denominado “retorno de carro” o CR en inglés (ASCII 13). Es un carácter
no imprimible, que en un teclado se produce cuando se toca la tecla “Enter” o “Intro”.
Así, en el ejemplo del ascensor, para que el supervisor le ordene al controlador 3 que el tiempo de apertura de la puerta
“:” “3” “P” <enter>
58 51 80 13
3A 33 50 0D
“:” “3” “P” “1” “4” <enter>
58 51 80 49 52 13
Guía de comunicación serie. Electrónica General y Aplicada. Facultad de Ingeniería UNCuyo
sea 3200 milisegundos, el mensaje podría ser la sucesión de caracteres:
Que en ASCII (expresado en decimal) será
Y expresado en hexadecimal
Mensaje respuesta a Consigna numérica (µC PC)
Consiste simplemente en un “eco” del mensaje de la PC, y se efectúa para verificar si el mensaje de la PC fue leído
correctamente por el microcontrolador. En el ejemplo anterior sería
Hardware de comunicación en el µC
En nuestros trabajos utilizamos generalmente el microcontrolador PIC16F628A, que posee el periférico de transmisión
serie (UART). Para otros modelos de microcontrolador con UART integrada las consideraciones son similares. En el
microcontrolador PIC16F628A el pin 7 (RB1/RX) puede utilizarse como pin de entrada/salida RB1 o como pin de recepción de datos serie RX, y el pin 8 (RB2/TX) como pin de entrada/salida RB2 o como pin de transmisión serie TX.
Software de comunicación en el µC
Para habilitar estos pines como RX y TX, es decir para que el µC pueda comunicarse con un dispositivo serie externo, el
programa en el µC debe inicializar el periférico UART escribiendo los valores apropiados en ciertos registros de control
del microcontrolador. Si se utiliza un lenguaje de alto nivel, por ejemplo en el BASIC del PIC Simulator, la inicialización
se realiza de manera muy simple mediante una instrucción como:
Hseropen 9600 (1)
Se dice que esta comunicación es 9600, N, 8, 1 (9600 bps, No paridad, 8 bits de datos, 1 bit de stop). Son válidas otras velocidades estándar como 1200, 2400, 4800, 9600, 19200 etc.)
Al escribir la instrucción anterior, RB1 y RB2 pasan a ser los pines Rx y Tx respectivamente. En el 16F628 estos pines utilizan 5 volts para representar el ‘1’ y 0 volts para el ‘0’, lo que comúnmente se denomina “niveles TTL”.
Hardware de comunicación en PC
En los modelos antiguos de PC es posible disponer del conector de puerto serie
RS232, como se muestra en la figura 4. En este conector el pin 2 es Rx, el pin 3 es
Tx y el pin 5 es masa (los números están en relieve en el plástico interior).
Como los voltajes de las señales RS232 están invertidos respecto a las del
microcontrolador (el “0” se representa con +12 volts y el “1” con –12 volts), se
requiere un adaptador eléctrico como el integrado MAX232 (figura 5a), o una
solución económica como un inversor CD4069/CD40106 (figura 5b), que si bien
no es estándar funciona en la mayoría de los puertos. En caso de querer utilizar el
MAX232 debe consultarse su hoja de datos para detalles del conexionado.
“:” “3” “T” “3” “2” “0” “0” <enter>
58 51 84 51 50 48 48 13
3A 33 54 33 32 30 30 0D
“:” “3” “T” “3” “2” “0” “0” <enter>
Figura 3. Pines Rx y Tx en el PIC 16F628A
Figura 4. Puerto COM (9 pines) en una PC de escritorio
Rx Tx masa
Guía de comunicación serie. Electrónica General y Aplicada. Facultad de Ingeniería UNCuyo
En las PCs de escritorio y notebooks actuales de uso doméstico no está disponible el puerto RS232. En tal caso se puede
utilizar un adaptador USB/Serie como los mostrados en la figura 6. Los adaptadores pueden ser de USB a norma RS232
(izquierda) o a TTL (derecha). En el primer caso se debe conectar también un adaptador eléctrico como los vistos en 5a o
5b, en el segundo se puede conectar directamente al microcontrolador.
Software de comunicación en PC. Terminal
Así como en el microcontrolador debe abrirse el puerto de comunicaciones inicializando la UART (por ejemplo con la
instrucción Hseropen), en la PC debe abrirse el puerto COM que se va a utilizar para enviar y recibir los mensajes. Tanto
abrir el puerto como enviar y recibir mensajes se puede hacer desde una aplicación como Matlab, Visual Basic, LabView
etc, o más simplemente desde un software emulador de Terminal de datos. Algunos emuladores de terminal son Hyperterminal del Windows Xp, TTY Emulator, PuTTY etc.
En la página de la cátedra se dispone del sencillo “Terminal.exe”, en un solo archivo de 334kB y que no requiere
instalación.
https://fing.uncu.edu.ar/catedras/electronica/archivos/recursos/Terminal.zip
Figura 5b. Similar al esquema de 5a, pero en versión económica (no estándar) con inversores (CD4069 etc)
Figura 5a. Adaptador MAX232 para conexión entre un µC y una PC que tiene puerto serie RS232
Figura 6. (a) Adaptador USB/Serie (RS232) (b) Adaptador USB/Serie (TTL)
µC
PC
µC Tx
Rx
Guía de comunicación serie. Electrónica General y Aplicada. Facultad de Ingeniería UNCuyo
La ventana de esta aplicación se muestra en la figura 7
En la parte superior (1) se puede elegir el puerto COM, la velocidad (Baud Rate), los bits de datos, la paridad, los bits de
stop, y el control de flujo (Handshaking). El programa arranca con los valores que utilizaremos en la mayoría de los
casos, sólo debe escogerse el COM Port adecuado.
En el espacio (2) es donde se pueden ver los caracteres recibidos (transmitidos por el µC).
En el renglón inferior (3) es donde se escriben los mensajes (consignas y solicitudes) a ser enviadas al µC.
Intercambio de mensajes entre PC y microcontrolador
Los mensajes que se explicaron anteriormente (solicitudes, consignas) son secuencias de caracteres que deben ser
interpretadas por el programa que corre en el µC. Hay dos maneras de interpretar un mensaje:
Sin buffer: Una vez que se recibió el carácter de inicio “:”, se va procesando cada carácter que se va recibiendo
para identificar comando, parámetros etc.
Con buffer: Una vez que se recibió el carácter de inicio “:”, se van guardando en posiciones consecutivas de memoria RAM (vector, array o buffer) los caracteres que se van recibiendo hasta el carácter de final (ASCII 13).
Recién entonces se procede a procesar cada carácter del mensaje (cada byte copiado en RAM) para identificar
comando, parámetros etc.
Explicaremos el primer método para interpretar un mensaje (sin buffer).
Supongamos un mensaje como la solicitud vista anteriormente:
“:” “3” “P” <enter>
Figura 7. Terminal
(1)
(3)
(2)
(entra a rutina de recepción de mensaje)
dato=midirecc N
S
N
S
dato dato
dato=”:” dato=”P”
dato
N
S
:,midirecc,piso,13
Si no es el inicio del
mensaje, sale de rutina
Si es el inicio, lee
próximo carácter y
guarda en “dato”
Lee carácter y o guarda
en la variable “dato”
(sale de rutina de recepción de mensaje)
Si “dato” no es igual a la
dirección propia del µC
(variable “midirecc”), sale de
rutina (el mensaje es para
otro µC)
Si el mensaje es para
este µC, lee próximo
carácter y guarda en
“dato”
Si dato distinto de “P”
lo comparará con otros
comandos posibles
Si es “P” transmite la respuesta,
que es la secuencia de
caracteres que incluye el inicio
“:”, la dirección propia
“midirecc”, el número de piso
expresado como cadena
decimal, y el carácter de final 13
(CR)
Guía de comunicación serie. Electrónica General y Aplicada. Facultad de Ingeniería UNCuyo
Este programa codificado en el BASIC del PIC Simulator quedaría:
Hserin dato ‘Espera recibir carácter por puerto serie, que guarda en la variable “dato” If dato = ”:” then ‘Si el carácter recibido es “:” entonces… Hserin dato ‘Espera recibir próximo carácter If dato = midirecc then ‘Si este carácter es igual a la dirección propia (guardada en “midirecc”)… Hserin dato ‘Recibe próximo carácter If dato = “P” then ‘Si el carácter recibido es “P” (comando solicitud de piso) entonces… Hserout “:”,midirecc,”P”,piso,13 ‘Transmite mensaje de respuesta (Ej “:3P7<enter>”) Else ‘Si el carácter recibido no es “P” ‘ (otros if para ver otros comandos) Endif ‘Termina sentencia if (if dato = ”P”) Endif ‘Termina sentencia if (if dato 0 midirecc) Endif ‘Termina sentencia if (if dato = “:”)
También se puede escribir de la siguiente forma
Hserin dato ‘Espera carácter que guarda en variable “dato” If dato <> “:” then goto finmsg ‘Si es distinto de “:” va a rótulo “finmsg”. En un solo renglón sin “else” ni “endif” Hserin dato ‘Si es igual a “:” continúa en esta línea, espera carácter que guarda en dato If dato <> midirecc then goto finmsg ‘Si es distinto de dirección propia va a rótulo “finmsg” Hserin dato ‘Si es igual a dirección propia recibe próximo carácter If dato = “P” then ‘Si el carácter es “P” entonces… Hserout “:”,midirecc,”P”,piso,13 ‘Transmite mensaje de respuesta Else ‘Si el carácter no es “P” ‘ (otros if para ver otros comandos) Endif ‘Termina sentencia if (if dato = “P”) finmsg: ‘ (rótulo de destino para los goto de más arriba)
Como se observó en este ejemplo, para interpretar un mensaje el programa debe ir leyendo cada carácter y procesándolo
según de qué parte de la secuencia es. Lo escrito después de la comilla ‘ son comentarios no ejecutables.
Lectura de números expresados como caracteres decimales de longitud fija y variable:
Antes de analizar cómo se reciben cadenas de caracteres decimales, recordemos que todos los caracteres son
5representados internamente en los procesadores mediante un código ASCII, y en particular a los caracteres decimales
“0” a “9” les corresponden los códigos ASCII 48 a 57. Es así que al recibir un carácter decimal “0”, “1”… “9” en realidad
se reciben los números 48, 49 … 57. Para transformar un carácter decimal en el valor numérico que representa basta
entonces con restarle 48. Así,
“0” – 48 = 48 – 48 = 0
“1” – 48 = 49 – 48 = 1
… “9” – 48 = 57 – 48 = 9
Volviendo a la comunicación, si se quiere pasar un parámetro numérico, como en el ejemplo del ascensor para hacer que
el tiempo T de apertura de puerta sea 3200 milisegundos, el supervisor podría enviar una trama como
Si el tiempo fuera de 954 milisegundos, la trama podría enviarse manteniendo la longitud fija de 4 caracteres.
o eliminando los ceros innecesarios, es decir con longitud variable dependiendo del valor a representar.
“:” “3” “T” “3” “2” “0” “0” <enter>
“:” “3” “T” “0” “9” “5” “4” <enter>
“:” “3” “T” “9” “5” “4” <enter>
Rutina 1
Rutina 2
Guía de comunicación serie. Electrónica General y Aplicada. Facultad de Ingeniería UNCuyo
En el primer caso puede haberse convenido por ejemplo que los números estén expresados en 4 caracteres de “0000” a
“9999”, de manera que siempre el peso del primer carácter será x1000, el segundo x100, el tercero x10 y el cuarto x1.
Considerando entonces lo dicho sobre el código ASCII y los pesos, una rutina en BASIC para leer una cadena decimal de 4 cifras puede ser:
(antes de esta rutina ya se han procesado los caracteres previos “:”, “3”, “T”) Hserin umil ‘Recibe carácter “0” a “9” y guarda en variable umil umil = umil – 48 ‘Transforma valor de umil (“0” a “9” o 48 a 57) en valor 0 a 9 Hserin centena ‘Similar para variable centena centena = centena - 48 Hserin decena ‘Similar para variable decena decena = decena – 48 Hserin unidad ‘Similar para variable unidad unidad = unidad – 48 total = umil * 1000 + centena * 100 + decena * 10 + unidad ‘Calcula total
por ejemplo, si la cadena recibida es “3200” (es decir “3”, “2”, “0”, “0” ó 51, 50, 48, 48) al restar 48 quedan
umil = 3, centena = 2, decena = 0, unidad = 0
y finalmente
total = 3 * 1000 + 2 * 100 + 0 * 10 + 0 = 3200
Esta rutina utiliza 5 variables (umil, centena, decena, unidad, total). Se puede utilizar una única variable dato para recibir
el carácter, acumulando en la variable total las sumas parciales. La rutina puede ser entonces:
Hserin dato ‘Primer carácter recibido (unidad de mil) dato = dato – 48 ‘lo transforma en número total = dato * 1000 ‘Lo multiplica por 1000 y guarda en variable total Hserin dato ‘Segundo carácter recibido (centena) dato = dato – 48 ‘lo transforma en número total = total + dato * 100 ‘Lo multiplica por 100 y lo suma al valor anterior de la variable total Hserin dato ‘Tercer carácter recibido (decena) dato = dato – 48 ‘lo transforma en número total = total + dato * 10 ‘Lo multiplica por 10 y lo suma al valor anterior de total Hserin dato ‘Cuarto carácter recibido (unidad) dato = dato – 48 ‘lo transforma en número total = total + dato ’y lo suma al valor anterior de total
Viendo que el procedimiento es del algún modo repetitivo, es posible abreviarlo haciendo uso de un lazo finito, de 4
ciclos o repeticiones. En la siguiente rutina lo que se escribe entre la instrucción For n = 1 to 4 y la instrucción Next n se
ejecuta 4 veces.
total = 0 ‘Antes del lazo se hace la variable total = 0 For n = 1 to 4 ‘Comienza lazo finito (4 ciclos). Se usa una variable auxiliar n para contar los ciclos Hserin dato ‘Recibe carácter dato = dato – 48 ‘lo transforma en número total = total * 10 + dato ‘lo suma al valor anterior de total, que es previamente multiplicado por 10 Next n ‘Termina lazo finito
En este programa la variable total se inicializa en 0, antes de la instrucción For. Dentro del lazo finito se lee el carácter,
se le resta 48 y se lo multiplica por 10. Esto se hace 4 veces. Obsérvese que – por ejemplo – si la cadena recibida es “3200”:
En el primer ciclo se recibe “3” (es decir dato = 51), se le resta 48 (queda dato = 3), y como total es inicialmente
0, quedará total = 0 * 10 + 3 = 3
En el segundo ciclo se recibe “2” (dato = 50), se le resta 48 (dato = 2), y total = 3 * 10 + 2 = 32
En el tercer ciclo se recibe “0” (dato = 48), se le resta 48 (dato = 0), y total = 32 * 10 + 0 = 320
En el cuarto ciclo se recibe “0” (dato = 48), se le resta 48 (dato = 0), y total = 320 * 10 + 0 = 3200
es decir el valor entero
Hemos visto 3 métodos para transformar una cadena decimal de longitud fija en el número entero correspondiente. El
último método, además de compacto, es de fácil adaptación a distintas longitudes, simplemente cambiando el 4 por la
longitud que se adopte.
Este último método, con una pequeña modificación, permite también recibir cadenas decimales de longitud variable, como el ejemplo de la cadena “954” en vez de “0954”.
Rutina 3
Rutina 4
Rutina 5
Guía de comunicación serie. Electrónica General y Aplicada. Facultad de Ingeniería UNCuyo
Repetimos la trama anterior
Suponiendo que ya se han procesado los caracteres “:”, “3” y “T”, quedan la cadena decimal (de longitud variable) y el
<enter>
Observando la cadena completa, una persona reconoce inmediatamente el peso de cada dígito. Pero el µC no conoce de
antemano estos pesos porque no sabe cuántos caracteres decimales recibirá antes del <enter>. Sin embargo, se puede
aplicar la idea del lazo finito, pero que en vez de repetirse un número predeterminado de veces se repita hasta que se detecte el <enter>.
total = 0 ‘Antes del lazo se hace la variable total = 0 recibenum: ‘Comienzo del lazo. No tiene número predeterminado de ciclos Hserin dato ‘Recibe carácter If dato = 13 then goto final ‘Si carácter es el delimitador de final (ASCII 13) sale del lazo dato = dato – 48 ‘si no es 13, debe ser “0” a “9”. Lo transforma en número 0 a 9 total = total * 10 + dato ‘lo suma al valor anterior de total previamente multiplicado por 10 goto recibenum ‘Fin del lazo. Se ejecuta hasta que se recibe el carácter 13 final: ‘Rótulo para salir del lazo
El lazo está dado entre el rótulo “recibenum” y la instrucción goto recibenum. Igual que antes, se inicializa total = 0 fuera
del lazo. Se ha agregado la condición de bifurcación “if dato = 13 then goto final” (es decir, si el dato recibido es el
<enter> salir del lazo)
Escritura de números expresados como caracteres decimales de longitud variable:
En el entorno BASIC del PIC Simulator la escritura en formato decimal es más sencilla que la lectura. Se utiliza la
instrucción Hserout y basta con anteponer el carácter numeral “#” a la variable a expresar. Por ejemplo, si N=2381, y se
realiza
Hserout #N
Se transmiten los caracteres ‘2’,’3’,’8’,’1’
La instrucción Hserout admite concatenar utilizando una coma ‘,’. Así, la expresión:
Hserout “valor:”,#N
transmite la cadena “valor:” seguida de los caracteres antes mencionados.
Si no se antepone el numeral, el número o la expresión numérica serán transmitidos como valores binarios. Así, por
ejemplo, la instrucción
Hserout “valor:”, #N, 13
Transmite la cadena “valor:”, la cadena de caracteres decimales correspondiente a N, y el ASCII 13 (el <enter>)
En resumen:
Para desarrollar un automatismo supervisado se requiere que el controlador pueda comunicarse con un supervisor,
usualmente una PC, aunque también puede ser un PLC, terminal etc.
Para crear el canal de comunicación debe configurarse hardware y software, tanto en la PC como en el microcontrolador, compatibilizando niveles eléctricos y acordando la velocidad de transmisión, paridad etc.
Para intercambiar información mediante mensajes (solicitudes, consignas y respuestas) debe establecerse un formato o
protocolo de comunicación.
En el microcontrolador hay que programar las rutinas capaces de interpretar estos mensajes, procesando cada carácter. Se
han explicado rutinas para interpretar la parte numérica del mensaje, que será una cadena decimal de longitud fija o
variable, y para transmitir las repuestas solicitadas.
“:” “3” “T” “9” “5” “4” <enter>
“9” “5” “4” <enter>
Rutina 6
Guía de comunicación serie. Electrónica General y Aplicada. Facultad de Ingeniería UNCuyo
Ejemplos
Para afirmar los conceptos vistos vamos a realizar ejemplos progresivos de programas en microcontrolador. En todos los
casos el circuito es el mismo. Se resolverán todos los ejemplos en el BASIC (PIC Simulator) y en C (CCS PICC). Los
alumnos de Industrial pueden optar por BASIC o C, los de Mecatrónica deben trabajar en C (ejemplos al final).
1. Oscilador simple de período fijo 1Hz El propósito es ver las partes esenciales de un programa para comandar una salida.
2. Oscilador de período fijo con cambio de modo.
Al ejemplo anterior se agrega la lectura de señales binarias externas para arranque y parada del oscilador.
3. Oscilador “supervisado por puerto serie”, con comunicación simple.
Se agrega la posibilidad de solicitar información, pasar parámetros y operar en forma remota, desde un
supervisor,
4. Oscilador “supervisado por puerto serie”, con comunicación con interrupción (sin buffer). Se resuelve el
problema del ejemplo 3 sobre la periodicidad de la revisión de dato nuevo en puerto serie con Hserget.
5. Oscilador “supervisado por puerto serie”, con comunicación con buffer e interrupción.
Similar al ejemplo 4, pero utilizando buffer para no interferir con el automatismo permanente de dato recibido.
6. Oscilador “supervisado en bus”. Se muestra cómo se interpreta un mensaje que incluye el campo de dirección luego del carácter “:” (como los explicados en las rutinas 1 y 2 de la guía). Se toma como base el ejemplo 3
(comunicación simple), agregando simplemente la verificación de dirección.
Se utilizará el PIC 16F628A, con RB7 como salida del oscilador, RA1 y RA0 como arranque/parada respectivamente, y
RX, TX (RB1, RB2) para comunicación serie, a 9600 bits por segundo. En el ejemplo 1 únicamente se utiliza RB7, en el
2 se utilizan también RA0, RA1, y en 3, 4, 5 se agrega el puerto de comunicaciones Rx/Tx.
Ejemplo 1: Oscilador simple de período fijo 1Hz – BASIC '****************************** SIMBOLOS ********************************
Symbol salida = PORTB.7 'define el símbolo "salida", asignándolo al pin RB7
'************************** CONFIGURACIÓN *******************************
TRISB.7 = 0 'Pin RB7 como salida
'************************** CICLO PRINCIPAL *******************************
ciclo: 'rótulo “ciclo”
salida = 1 'enciende salida
WaitMs 500 'espera 500 milisegundos
salida = 0 'apaga salida
WaitMs 500 'espera 500 milisegundos
Goto ciclo 'vuelve al rótulo “ciclo”
'********************** fin de ciclo principal ****************************
End
µC µC parada
arranque
µC parada
arranque
PC
Rx Tx
Tx Rx
Oscilador simple (Ej 1) Oscilador con cambio de modo (Ej 2) Oscilador supervisado (Ejs 3, 4 y 5)
arranque
parada
PC
Figura 8. Esquemas de conexión de los ejemplos
Figura 9. Asignación de pines del µC para los ejemplos
salida salida salida
Guía de comunicación serie. Electrónica General y Aplicada. Facultad de Ingeniería UNCuyo
Nota: Todo lo escrito después de una comilla 'son comentarios, que sirven para documentar y explicar el programa. Al momento de la
compilación (traducción a lenguaje del microcontrolador) son ignorados.
Ejemplo 2: Oscilador de período fijo con cambio de modo – BASIC '-------------------------------- SIMBOLOS --------------------------------
Symbol salida = PORTB.7 'define el símbolo "salida", asignándolo al pin RB7
Symbol arranque = PORTA.1 'arranque es pin RA1
Symbol parada = PORTA.0 'parada es pin RA0
'----------------------------- CONFIGURACIÓN ------------------------------
TRISB.7 = 0 'Pin RB7 como salida
'Los demás pines son entradas
'---------------------------- CICLO PRINCIPAL -----------------------------
reposo:
if arranque = 1 Then Goto ciclo 'lee RA1, si está en alto va a ciclo
Goto reposo
ciclo: 'rótulo “ciclo”
salida = 1 'enciende salida
WaitMs 500 'espera 500 milisegundos
salida = 0 'apaga salida
WaitMs 500 'espera 500 milisegundos
If parada = 1 Then Goto reposo 'lee RA0, si está en alto va a reposo
Goto ciclo 'vuelve al rótulo “ciclo”
'------------------------- fin de ciclo principal --------------------------
End
Ejemplo 3: Oscilador supervisado – comunicación simple – BASIC 'Realiza encendido/apagado de "salida" (RB7) cada t [ms]
'Lleva el conteo de pulsos en la variable contador (de 0 a 65535)
'Al comando ":C" informa la cantidad de pulsos producidos
'Al comando ":Tnnnn modifica el valor de t, siempre que esté entre 10 ms y 4000 ms)
'-------------------------------- SIMBOLOS --------------------------------
Symbol salida = PORTB.7 'define el símbolo "salida"
Symbol arranque = PORTA.1 'arranque es pin RA1
Symbol parada = PORTA.0 'parada es pin RA0
'------------------------- DECLARACIÓN DE VARIABLES -----------------------
Dim t As Word 'variable t
Dim dato As Byte 'variable auxiliar para recibir datos de puerto serie
Dim contador As Byte 'variable de conteo de pulsos
Dim total As Word 'variable auxiliar para convertir cadena decimal
'de caracteres en un número tipo word
'---------------------------- CONFIGURACIÓN -------------------------------
TRISB.7 = 0 'Pin PORTB.7 como salida
Hseropen 9600 '"Abre" puerto de comunicaciones a 9600 bits por segundo
'----------------------------INICIALIZACIÓN -------------------------------
Hserout "LISTO", 13 'envía mensaje por puerto serie
t = 500 'inicializa t en 500 ms
contador = 0 'inicializa contador en 0
'----------------------------CICLO PRINCIPAL ------------------------------
reposo:
If arranque = 1 Then Goto ciclo 'lee RA1, si está en alto va a ciclo
Hserget dato 'toma dato en registro de recepción serie (si no hay dato nuevo lee 0)
If dato = ":" Then Gosub recibedato
Goto reposo
ciclo:
Hserget dato
If dato = ":" Then Gosub recibedato
contador = contador + 1
salida = 1
WaitMs t
salida = 0
WaitMs t
If parada = 1 Then Goto reposo 'lee RA0, si está en alto va a reposo
Goto ciclo
'--------------------- fin de ciclo principal ----------------------------
End
recibedato:
Hserin dato 'espera dato después de los ":" (hay que esperar, se usa hserin)
If dato = "C" Then 'solicitud de cantidad de pulsos generados
Hserout #contador, CrLf 'informa con el valor de contador (observar "#")
Endif
If dato = "T" Then 'consigna de nuevo valor para t
total = 0
proxdato: Hserin dato 'rutina para recibir cadena decimal y transformar en número
If dato = 13 Then Goto findato 'si se recibe caracter 13 (el "enter") termina cadena decimal
total = total * 10 + dato - 48
Goto proxdato
findato:
If total < 4000 And total > 10 Then 'verifica rango correcto
t = total 'caso afirmativo modifica t
Guía de comunicación serie. Electrónica General y Aplicada. Facultad de Ingeniería UNCuyo
Endif
Endif
Return
Ejemplo 4: Oscilador supervisado – comunicación con interrupción – BASIC El uso de la interrupción de un cierto periférico (en nuestro caso puerto serie) consta de dos partes:
La habilitación de la interrupción, activando el bit específico de habilitación de interrupción por recepción
RCIE del registro PIE1, y el bit de habilitación de interrupción global GIE del registro INTCON.
La rutina de servicio de la interrupción, que se escribe entre las sentencias On Interrupt y Resume, luego de la
sentencia End del programa principal. Esta rutina será similar a la del rótulo recibedato en el ejemplo 3. Al final
de esta rutina, antes de Resume, debe borrarse el flag que disparó la interrupción (en este caso el RCIF del
PIR1)
'Realiza encendido/apagado de "salida" (RB7) cada t [ms]
'Lleva el conteo de pulsos en la variable contador (de 0 a 65535)
'Al comando ":C" informa la cantidad de pulsos producidos
'Al comando ":Txxx modifica el valor de t, siempre que esté entre 10 ms y 4000 ms)
'Se observa que el "automatismo" (en este caso endender/apagar salida)
'se desentiende del problema de los mensajes por puerto serie.
'Los mensajes son atendidos en una interrupción.
'-----------------------------------SIMBOLOS ----------------------------
Symbol salida = PORTB.7 'define el símbolo "salida"
Symbol arranque = PORTA.1 'arranque es pin RA1
Symbol parada = PORTA.0 'parada es pin RA0
'---------------------------- DECLARACIÓN DE VARIABLES ------------------
Dim t As Word 'variable t
Dim dato As Byte 'variable auxiliar para recibir datos de puerto serie
Dim contador As Word 'variable de conteo de pulsos
Dim total As Word 'variable auxiliar para convertir cadena decimal
'de caracteres en un número tipo word
'---------------------------- CONFIGURACIÓN -----------------------------
TRISB.7 = 0 'Pin PORTB.7 como salida
Hseropen 9600 '"Abre" puerto de comunicaciones a 9600 bits por segundo
'---habilitación de interrpución ---
PIR1.RCIF = 0 'bandera de interrupción por caracter recibido por puerto serie
PIE1.RCIE = 1 'habilitación de dicha interrupción específica
INTCON.PEIE = 1 'habilitación de las interrupciones por periféricos
INTCON.GIE = 1 'habilitación Global de interrupciones
'----------------------------INICIALIZACIÓN ----------------------------
Hserout "LISTO", 13 'envía mensaje por puerto serie
t = 500 'inicializa t en 50 ms
contador = 0 'inicializa contador en 0
'----------------------------CICLO PRINCIPAL ----------------------------
reposo:
If arranque = 1 Then Goto ciclo 'lee RA1, si está en alto va a ciclo
Goto reposo
ciclo:
contador = contador + 1
salida = 1
WaitMs t
salida = 0
WaitMs t
If parada = 1 Then Goto reposo 'lee RA0, si está en alto va a reposo
Goto ciclo
'--------------------------- fin de ciclo principal ---------------------
End
'----------------------------RUTINA DE INTERRUPCIÓN ---------------------
On Interrupt
Save System 'resguarda valores de variables
Hserget dato 'toma dato que arribó al puerto serie (no hay que esperar, se usa hserget)
If dato = ":" Then 'si dato es ":" ejecuta lo que sigue, si no vuelve
Hserin dato 'espera dato después de los ":" (hay que esperar, se usa hserin)
If dato = "C" Then 'solicitud de cantidad de pulsos generados
Hserout #contador, CrLf 'informa con el valor de contador (observar "#")
Endif
If dato = "T" Then 'consigna de nuevo valor para t
total = 0
proxdato: Hserin dato 'rutina para recibir cadena decimal y transformar en número
If dato = 13 Then Goto findato 'si se recibe caracter 13 (el "enter") termina cadena
total = total * 10 + dato - 48
Goto proxdato
findato:
If total < 4000 And total > 10 Then 'verifica rango correcto
t = total 'caso afirmativo modifica t
Endif
Endif
Endif
Guía de comunicación serie. Electrónica General y Aplicada. Facultad de Ingeniería UNCuyo
PIR1.RCIF = 0 'borra “flag de interrupción”, que se activa cuando se recibe dato (no
'confundir con el habilitador PIE1.RCIE
Resume
Ejemplo 5: Oscilador supervisado – comunicación con interrupción y buffer – BASIC '-----------------------------------SIMBOLOS ----------------------------
Symbol salida = PORTB.7 'define el símbolo "salida"
Symbol arranque = PORTA.1 'arranque es pin RA1
Symbol parada = PORTA.0 'parada es pin RA0
'---------------------DECLARACIÓN DE VARIABLES --------------------------
Dim buffer(10) As Byte 'array para recibir caracteres de puerto serie
Dim ibuffer As Byte 'índice de buffer
Dim t As Word 'variable t
Dim dato As Byte 'variable auxiliar para recibir datos de puerto serie
Dim contador As Word 'variable de conteo de pulsos
Dim total As Word 'variable auxiliar para convertir cadena decimal
'de caracteres en un número tipo word
'----------------------------CONFIGURACIÓN ------------------------------
TRISB.7 = 0 'Pin PORTB.7 como salida
Hseropen 9600 '"Abre" puerto de comunicaciones a 9600 bits por segundo
'--habilitación de interrpución --
PIR1.RCIF = 0 'bandera de interrupción por caracter recibido por puerto serie
PIE1.RCIE = 1 'habilitación de dicha interrupción específica
INTCON.PEIE = 1 'habilitación de las interrupciones por periféricos
INTCON.GIE = 1 'habilitación Global de interrupciones
'----------------------------INICIALIZACIÓN -----------------------------
Hserout "LISTO", 13 'envía mensaje por puerto serie
t = 500 'inicializa t en 50 ms
contador = 0 'inicializa contador en 0
ibuffer = 0
'----------------------------CICLO PRINCIPAL ----------------------------
reposo:
If arranque = 1 Then Goto ciclo 'lee RA1, si está en alto va a ciclo
Goto reposo
ciclo:
contador = contador + 1
salida = 1
WaitMs t
salida = 0
WaitMs t
If parada = 1 Then Goto reposo 'lee RA0, si está en alto va a reposo
Goto ciclo
'----------------------------fin de ciclo principal ---------------------
End
'----------------------------RUTINA DE INTERRUPCIÓN ---------------------
On Interrupt
Save System 'resguarda valores de variables
Hserget dato 'toma dato que arribó al puerto serie (no hay que esperar, se usa hserget)
Select Case dato
Case ":" 'carácter delimitador de inicio, inicializa ibuffer
ibuffer = 0
Case 13 'carácter delimitador de final, comienza la interpretación del mensaje (ver
'primero el “Case Else” de este Select Case, que es recepción de carácter 'dato
(no delimitador) para entender esto
buffer(ibuffer) = 13 'pone delimitador al elemento
dato = buffer(0)
Select Case dato
Case "T" 'consigna de nuevo valor para t
total = 0
ibuffer = 1 'Donde comienza la cadena decimal del parámetro numérico
proxdato: 'rutina para recibir cadena decimal y transformar en número
dato = buffer(ibuffer)
If dato = 13 Then Goto findato 'si se recibe caracter 13 (el "enter") termina cadena
decimal
total = total * 10 + dato - 48
ibuffer = ibuffer + 1
Goto proxdato
findato:
If total < 4000 And total > 10 Then 'verifica rango correcto
t = total 'caso afirmativo modifica t
Endif
Case "C" 'solicitud de cantidad de pulsos generados
Hserout ":C", #contador, 13 'informa con el valor de contador (observar "#")
Case Else
EndSelect
Case Else ' Si el carácter recibido no es “:” o 13, es dato que debe guardarse en buffer
buffer(ibuffer) = dato ' Se guarda en elemento buffer(0), buffer(1) … según ibuffer
ibuffer = ibuffer + 1 ' ibuffer se incrementa para apuntar al siguiente elemento
' del buffer para recibir el próximo caracter
EndSelect
finrecibedato:
Guía de comunicación serie. Electrónica General y Aplicada. Facultad de Ingeniería UNCuyo
PIR1.RCIF = 0
Resume
Ejemplo 6: Oscilador supervisado en bus – BASIC Se han resaltado las instrucciones que se agregan al Ejemplo 3 para procesar mensajes con direccionamiento:
Una declaración de variable dirpropia (en principio podría ser también una constante).
Una asignación inicial de valor a esta variable (en este ejemplo un valor “3”, pero podría ser más flexible si se obtuviera
leyendo pines de un puerto, de forma que el instalador podría configurar la dirección sin tener que regrabar el programa
en el microcontrolador)
Luego de los “:”, en “recibedato” lee el siguiente carácter y lo compara con dirpropia. Si coinciden sigue recibiendo
mensaje, sino lo ignora.
'Realiza encendido/apagado de "salida" (RB7) cada t [ms]
'Lleva el conteo de pulsos en la variable contador (de 0 a 65535)
'Al comando ":C" informa la cantidad de pulsos producidos
'Al comando ":Tnnnn modifica el valor de t, siempre que esté entre 10 ms y 4000 ms)
'----------------------------SIMBOLOS -----------------------------------
Symbol salida = PORTB.7 'define el símbolo "salida"
Symbol arranque = PORTA.1 'arranque es pin RA1
Symbol parada = PORTA.0 'parada es pin RA0
'----------------------------DECLARACIÓN DE VARIABLES -------------------
Dim t As Word 'variable t
Dim dato As Byte 'variable auxiliar para recibir datos de puerto serie
Dim dirpropia As Byte 'variable “dirección propia” para identificar mensajes destinados a este µC
Dim contador As Byte 'variable de conteo de pulsos
Dim total As Word 'variable auxiliar para convertir cadena decimal
'de caracteres en un número tipo word
'---------------------------- CONFIGURACIÓN ------------------------------
TRISB.7 = 0 'Pin PORTB.7 como salida
Hseropen 9600 '"Abre" puerto de comunicaciones a 9600 bits por segundo
'----------------------------INICIALIZACIÓN ------------------------------
dirpropia = "3" 'asigna su propia dirección, alguna entre “1” y “9”
Hserout ":",dirpropia,"LISTO", 13 'envía mensaje por puerto serie
t = 500 'inicializa t en 500 ms
contador = 0 'inicializa contador en 0
'----------------------------CICLO PRINCIPAL -----------------------------
reposo:
If arranque = 1 Then Goto ciclo 'lee RA1, si está en alto va a ciclo
Hserget dato 'toma dato en registro de recepción serie (si no hay dato nuevo lee 0)
If dato = ":" Then Goto recibedato
Goto reposo
ciclo:
Hserget dato
If dato = ":" Then Gosub recibedato
contador = contador + 1
salida = 1
WaitMs t
salida = 0
WaitMs t
If parada = 1 Then Goto reposo 'lee RA0, si está en alto va a reposo
Goto ciclo
'----------------------------fin de ciclo principal ----------------------------
End
recibedato:
Hserin dato 'espera dato después de los ":" (hay que esperar, se usa hserin)
If dato = dirpropia Then
Hserin dato
If dato = "C" Then 'solicitud de cantidad de pulsos generados
Hserout #contador, CrLf 'informa con el valor de contador (observar "#")
Endif
If dato = "T" Then 'consigna de nuevo valor para t
total = 0
proxdato: Hserin dato 'rutina para recibir cadena decimal y transformar en número
If dato = 13 Then Goto findato 'si se recibe caracter 13 (el"enter")termina cadena decimal
total = total * 10 + dato - 48
Goto proxdato
findato:
If total < 4000 And total > 10 Then 'verifica rango correcto
t = total 'caso afirmativo modifica t
Endif
Endif
Endif
Return
Guía de comunicación serie. Electrónica General y Aplicada. Facultad de Ingeniería UNCuyo
Para los alumnos que resolverán el automatismo en lenguaje C (optativo para Industrial, obligatorio para Mecatrónica) se dan los mismos ejemplos 1 a 5 en el lenguaje C del compilador PICC de CCS. http://www.ccsinfo.com/ccsfreedemo.php
Ejemplo 1: Oscilador simple de período fijo 1Hz – C
#include <16F628A.h>
#use delay(internal=4000000)
#byte PORTB = 0x06 // Dirección física del PORTB
#byte TRISB = 0x86 // Dirección física del TRISB (controla si los bits de PORTB son E/S)
#bit salida = PORTB.7 // bit "salida" es el bit 7 del PORTB
#bit tsalida = TRISB.7 // bit "tsalida" es el bit 7 del TRISB. Controla si bit "salida" es E/S
// Valor 0 para utilizar el bit como salida, 1 para entrada.
void main()
{
tsalida = 0;
while(TRUE) // Lazo infinito (desde "{" hasta "}"
{
salida = 1; //Prende bit de salida
delay_ms(500); //Retardo de 500 milisegundos
salida = 0; //Apaga bit de salida
delay_ms(500);
}
}
Ejemplo 2: Oscilador de período fijo con cambio de modo – C #include <16F628A.h> //Cabecera que incluye biblioteca del microcontrolador a utilizar
#use delay(internal=4000000) //Frecuencia de oscilador del microcontrolador
#byte PORTA = 0x05
#bit arranque = PORTA.1 // bit "arranque" es el bit 1 del PORTA
#bit parada = PORTA.0 // bit "PARADA" es el bit 0 del PORTA
#byte PORTB = 0x06
#byte TRISB = 0x86
#bit salida = PORTB.7 //bit “arranque” es el bit 1 del PORTA
#bit tsalida = TRISB.7 //bit "tsalida" es el bit 7 del TRISB. Controla si bit "salida" es E/S.
//Valor 0 para salida 1 para entrada
void main()
{
tsalida = 0;
reposo: //Rótulo/etiqueta de la rutina 'reposo'
if (arranque == 1) goto ciclo; //Si se cumple la condición, ejecuta rutina ciclo
goto reposo; //Ejecuta rutina 'reposo'
ciclo: //Rótulo/etiqueta de la rutina 'ciclo'
while(TRUE) //Bucle infinito
{
salida = 1;
delay_ms(500);
salida = 0;
delay_ms(500);
if (parada == 1) goto reposo; //Si se cumple la condición, sale del bucle infinito
}
}
Guía de comunicación serie. Electrónica General y Aplicada. Facultad de Ingeniería UNCuyo
Ejemplo 3: Oscilador supervisado – comunicación simple – C #include <16F628A.h>
#use delay(internal=4000000)
#use rs232(baud=9600,parity=N,xmit=PIN_B2,rcv=PIN_B1,bits=8,stream=PORT1) //Directiva de compilador
//para declarar el uso de puerto serie y sus parámetros
#byte PORTA = 0x05
#bit arranque = PORTA.1
#bit parada = PORTA.0
#byte PORTB = 0x06
#byte TRISB = 0x86
#bit salida = PORTB.7
#bit tsalida = TRISB.7
int16 contador; //Declaración de variable 'contador', tipo entero de 16 bits
int16 t;
int16 total;
char dato; //Declaracion de variable 'dato' , tipo caracter 8 bit
void recibedato() //Funcion 'recibedato' tipo de retorno nulo(void) no devuelve ningun valor
{
dato = getc(); //getc() lee un caracter nuevo. Almacena este caracter en la variable dato
if (dato=='C')
{
printf("%ld\r\n",contador); //Imprime por puerto serie el valor de la variable contador
}
Else
if (dato=='T')
{
total = 0;
proxdato:
dato = getc();
if (dato == 13) goto findato; //Etiqueta de finalizacion de adquisicion de caracteres,
//cuando se recibe el caracter '13' (enter)
total = total * 10 + dato - 48; //Conversion de caracter ASCII a numero entero
goto proxdato;
findato:
if ((total<4000)&&(total>10)) //Verificacion de que la variable se encuentre en un
intervalo adecuado
t = total;
}
}
void main() //Funcion principal
{
tsalida = 0;
puts("LISTO\r"); //puts() funcion que envía una cadena de
caracteres por puerto serie
t=500; //Período inicial
reposo:
if (arranque == 1) goto ciclo;
if(kbhit()) if(getc()==':') recibedato(); //kbhit() detecta si recibe un caracter ingresado
por teclado, getc() verifica que caracter es.
Si se cumple la condición se ejecuta la función
recibe dato.
goto reposo;
ciclo:
while(TRUE)
{
if(kbhit()) if(getc()==':') recibedato();
contador++;
salida = 1;
delay_ms(t); //Retardo de 't' milisegundos
salida = 0;
delay_ms(t);
if (parada == 1) goto reposo;
}
}
Guía de comunicación serie. Electrónica General y Aplicada. Facultad de Ingeniería UNCuyo
Ejemplo 4: Oscilador supervisado – comunicación con interrupción – C #include <16F628A.h>
#use delay(internal=4000000)
#use rs232(baud=9600,parity=N,xmit=PIN_B2,rcv=PIN_B1,bits=8,stream=PORT1)
#byte PORTA = 0x05
#bit arranque = PORTA.1
#bit parada = PORTA.0
#byte PORTB = 0x06
#byte TRISB = 0x86
#bit salida = PORTB.7
#bit tsalida = TRISB.7
int16 contador;
int16 t;
int16 total;
char dato;
#INT_RDA //Directiva que indica que la función recibedato se ejecuta al producirse
//una interrupción por puerto serie
void recibedato()
{
dato = getc();
if (dato=='C')
{
printf("%ld\r\n",contador);
}
else
if (dato=='T')
{
total = 0;
proxdato:
dato = getc();
if (dato == 13) goto findato;
total = total * 10 + dato - 48;
goto proxdato;
findato:
if ((total<4000)&&(total>10))
t = total;
}
}
void main()
{
tsalida = 0;
puts("LISTO\r");
t=500;
enable_interrupts(INT_RDA); //Habilita interrupciones por puerto serie. Reemplaza a kbhit().
enable_interrupts(GLOBAL); //Habilita interrupciones globales
reposo:
if (arranque == 1) goto ciclo;
goto reposo;
ciclo:
while(TRUE)
{
contador++;
salida = 1;
delay_ms(t);
salida = 0;
delay_ms(t);
if (parada == 1) goto reposo;
}
}
Guía de comunicación serie. Electrónica General y Aplicada. Facultad de Ingeniería UNCuyo
Ejemplo 5: Oscilador supervisado – comunicación con interrupción y buffer – C #include <16F628A.h>
#use delay(internal=4000000)
#use rs232(baud=9600,parity=N,xmit=PIN_B2,rcv=PIN_B1,bits=8,stream=PORT1)
#byte PORTA = 0x05
#bit arranque = PORTA.1
#bit parada = PORTA.0
#byte PORTB = 0x06
#byte TRISB = 0x86
#bit salida = PORTB.7
#bit tsalida = TRISB.7
char buffer[10]; //Arreglo de caracteres de longitud 10. Almacena hasta 10 caracteres
char ibuffer; //Variable auxiliar que según su valor permite ubicar en distinto orden los
//caracteres recibidos
int16 t;
char dato;
int16 contador;
int16 total;
void interpreta()
{
dato = buffer[0];
switch(dato)
{
case 'C':
printf("%ld\r\n",contador);
break;
case 'T':
total = 0;
ibuffer=1;
proxdato:dato = buffer[ibuffer];
if (dato == 13) goto findato;
total = total * 10 + dato - 48;
ibuffer++;
goto proxdato;
findato: if ((total<4000)&&(total>10)) t = total;
}
}
#INT_RDA
void recibedato()
{
dato = getc();
switch(dato)
{
case ':':
ibuffer = 0; //Al recibir el caracter ':' se entiende que es inicio de mensaje y ubicará
//el proximo caracter recibiddo en la primer posicion del arreglo.
break;
case 13:
buffer[ibuffer] = 13;
interpreta();
break;
default:
buffer[ibuffer] = dato;
ibuffer++;
break;
}
}
void main()
{
tsalida = 0;
puts("LISTO\r");
t=500;
enable_interrupts(INT_RDA);
enable_interrupts(GLOBAL);
reposo:
if (arranque == 1) goto ciclo;
goto reposo;
ciclo:
while(TRUE)
{
contador++;
salida = 1;
delay_ms(t);
salida = 0;
delay_ms(t);
if (parada == 1) goto reposo;
}
}
Guía de comunicación serie. Electrónica General y Aplicada. Facultad de Ingeniería UNCuyo
Los ejemplos se pueden ensayar en el simulador del PIC Simulator IDE, o en el módulo ISIS del software Proteus. Este último permite simulaciones en tiempo real. El esquema utilizado para la simulación en ISIS es el siguiente:
RA7/OSC1/CLKIN16
RB0/INT6
RB1/RX/DT7
RB2/TX/CK8
RB3/CCP19
RB410
RB511
RB6/T1OSO/T1CKI12
RB7/T1OSI13
RA0/AN017
RA1/AN118
RA2/AN2/VREF1
RA3/AN3/CMP12
RA4/T0CKI/CMP23
RA6/OSC2/CLKOUT15
RA5/MCLR4
U1
PIC16F628A
R1PULLUP
U1_VDD
RXD
RTS
TXD
CTS
A
B
C
D
1
0