2. Instalación de Virtual Serial Port
Creación de una nueva aplicación en C# 2012
toolStrip y componentes básicos
Manejo de los puertos seriales
Apertura de un puerto
Transmisión
Recepción
Autor: Andrés Gerardo Fuentes Covarrubias
2
3. Forma comoda de depurar las aplicaciones al
crear puertos seriales virtuales pareados
Un puerto serial para la simulación en ISIS
Proteus
Un puerto serial para el programa en Visual
C# 2012
Autor: Andrés Gerardo Fuentes Covarrubias
3
4. Abrir VC# 2012 y elegir
“Archivo”->”Nuevo Proyecto”
Después “Aplicación de Windows Forms y el botón
“Aceptar” después de darle nombre al nuevo proyecto
Autor: Andrés Gerardo Fuentes Covarrubias
4
5. •
Elegir dos controles:
1.
Para manejo de los puertos
seriales:
“SerialPort ”, será el
encargado de manejar todas
las propiedades, métodos y
eventos relacionados con el
puerto o los puertos seriales
de la aplicación, crear tantos
como puertos seriales se
necesite.
2.
Para manejo de los controles
básicos de las
comunicaciones seriales, así
como mensajes e
indicadores, elija el control
“ToolStrip”
Estos controles no son visibles en la
forma principal, por lo tanto se
colocan en el “Status Strip”
Autor: Andrés Gerardo Fuentes Covarrubias
5
6. Controles en la aplicación,
ToolStrip.
ComboBox
TextBox
Boton
Label
Observe que para .Net el
control para puerto serial
contiene todas las
propiedades para las
características de la trama
en tiempo de diseño
Autor: Andrés Gerardo Fuentes Covarrubias
6
7. Controles en la aplicación, área de
trabajo
toolStrip
TabControl
OvalShape
Botones
Autor: Andrés Gerardo Fuentes Covarrubias
7
8. using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.IO;
using System.IO.Ports;
using System.Threading;
using Microsoft.VisualBasic.PowerPacks;
namespace consolaSerialCDC
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
El código fuente inicial solo describe las librerías a
ser utilizadas al momento y el esqueleto inicial para
el “namespace” correspondiente a nuestra
aplicación.
Por lo general, este esqueleto de Clase principal es
creada por VisualStudio al momento de inicializar el
nuevo proyecto.
Finalmente el desarrollador debe indicar
explícitamente las referencias externas con
instrucciones “using” seguidas del “namespace”
relacionado con la librería.
Agregar estas referencias
externas
}
}
Autor: Andrés Gerardo Fuentes Covarrubias
8
9. La apertura de un puerto serial en Visual C# es tan sencillo como agregar el siguiente código al
botón “Conectar” del ToolStrip:
if(!serialPort1.IsOpen)
{
try
{
}
serialPort1.Open();
}
catch (System.Exception ex)
{
MessageBox.Show(ex.ToString());
}
Las propiedades del control SerialPort se pueden
establecer en tiempo de diseño mediante el cuadro de
propiedades.
Autor: Andrés Gerardo Fuentes Covarrubias
9
10. Siempre se puede abrir un puerto con el código siguiente y tambien establecer las
caracteristicas de la trama:
usuario
serialPort1.BaudRate = 9600;
// Velocidad de transmisión
serialPort1.Parity = Parity.None;
//Tipo de paridad
serialPort1.DataBits = 8;
//Número de bits de datos
serialPort1.StopBits = StopBits.One;
//Número de bits de parada
serialPort1.PortName = toolStripTextBox1.Text; //Use el control adecuado para el
serialPort1.Open();
//Abrir el puerto
Vincule el código anterior con un botón y podrá abrir el puerto serial capturado en el control
“toolStripTextBox1” al presionar el botón “Conectar”
Sin embargo, es recomendable usar los controles adecuados que listen los recursos reconocidos
por el sistema y que los pongan a disposición del usuario de la aplicación, para eso se agregaran
en el toolStrip.
Autor: Andrés Gerardo Fuentes Covarrubias
10
11. •Siempre que haya un puerto serial abierto se puede enviar datos por ese puerto.
•En el TabControl “Consola”, Agregue dos controles
TextBox
Botón
Agregue el código del botón
private void button1_Click(object sender, EventArgs e)
{
if (conectado == true)
{
if (tbTerminalEnviar.Text.Length > 0)
{
serialPort1.WriteLine("@" + tbTerminalEnviar.Text + "r");
}
else
{
MessageBox.Show("MENSAJE VACIO");
}
}
else
{
MessageBox.Show("Puerto Serial NO CONECTADO");
}
}
Autor: Andrés Gerardo Fuentes Covarrubias
11
12. Siempre es posible enviar también un solo caracter por el puerto serial:
byte[] miBuffer= new byte[1];
miBuffer[0] = 0x62;
//Carácter a enviar por el puerto.
SP1.Write(miBuffer, 0, miBuffer.Length);
Por ejemplo, si lo que se desea es enviar una trama completa, entonces:
// Enviar trama
byte[] miBuffer= new byte[3];
// Tres caracteres máximo.
miBuffer[0] = 0x74;
miBuffer[1] = 0x54;
miBuffer[2] = 0x13;
SP1.Write(miBuffer, 0, miBuffer.Length);
Autor: Andrés Gerardo Fuentes Covarrubias
12
13. También se puede vincular código a otros controles de usuario:
Indicadores con el control Ovalshape para
simular leds.
Salidas por botón
Cada control incluye código:
strBufferOut = "1";
serialPort1.DiscardOutBuffer();
serialPort1.Write(strBufferOut);
//Buffer de transmisión
//Limpiamos el buffer de transmisión
//Enviar caracteres
Autor: Andrés Gerardo Fuentes Covarrubias
13
14. El control comboBox nos permite listar los recursos hardware de comunicaciones
seriales.
También mediante un control “textBox” se puede visualizar el
puerto serial seleccionado, posteriormente mediante un “Botón”
ejecutar el código vinculado con la apertura del puerto.
Un control adicional tipo “Label” se puede visualizar si el puerto
seleccionado esta en estado “Conectado” o “No Conectado”,
también cambiar la propiedad “ForeColor” a Green o Red
respectivamente.
Autor: Andrés Gerardo Fuentes Covarrubias
14
16. private void btActualizar_Click(object sender, EventArgs e)
{
UpdateSerialPorts();
}
El código de “Actualizar” nos permite atender un evento de “Conexión en caliente”. Es
decir cuando un usuario conecta una nueva interfaz serial USB cuando nuestra
aplicación se esta ejecutando, de esta manera se puede actualizar la colección de
datos del control “comboBox” y el usuario podrá localizar en esta su interfaz.
Autor: Andrés Gerardo Fuentes Covarrubias
16
17.
Invocar la función UpdateSerialPorts() en nuestra función Form_Load1()
para que la colección de nombres de puertos sea actualizada en el mismo
momento de la carga de la forma principal.
private void Form1_Load(object sender, EventArgs e)
{
UpdateSerialPorts();
lblEstadoPuerto.Text = "No Conectado";
lblEstadoPuerto.ForeColor = Color.Red;
conectado = false;
}
Autor: Andrés Gerardo Fuentes Covarrubias
17
18.
Agregar un evento para actualizar el textBox del toolStrip cada vez que el
nombre de puerto serial cambie, de esta manera se podrá conectar el
puerto serial correcto al presionar el botón “Conectar”
private void toolStripComboBox1_TextChanged(object sender, EventArgs e)
{
toolStripTextBox1.Text =
toolStripComboBox1.Items[toolStripComboBox1.SelectedIndex].ToString();
}
Autor: Andrés Gerardo Fuentes Covarrubias
18
19. Agregue una variable booleana tipo bandera
para el manejo del estado del puerto serial,
de esta manera será mas cómoda la
validación del estado de la interfaz de
comunicaciones.
public Boolean conectado;
Autor: Andrés Gerardo Fuentes Covarrubias
19
20. El proceso de recepción de datos es un
proceso un poco mas complejo, ya que es
necesario instalar el vector de interrupción
del evento “DataReceived” y crear un nuevo
Thread (hilo) que atienda al manejador de ese
evento.
Autor: Andrés Gerardo Fuentes Covarrubias
20
21. Crear un nuevo control TextBox,
que sea multilínea, con
ScrollBar vertical y ajustado a la
parte inferior del formulario.
Este control va a operar como
nuestra consola del usuario, para
desplegar mensajes de la
aplicación, los datos enviados y
los recibidos.
Autor: Andrés Gerardo Fuentes Covarrubias
21
22. Para crear un manejador, se debe agregar un nuevo manejador de eventos, y vincularlo con el
método apropiado del control “serialPort”, el procedimiento consta de tres pasos:
1. Codigo de al cargar el formulario:
public Form1()
{
txtRecibidos.Text = "";
strBufferIn = "";
serialPort1.DataReceived += new SerialDataReceivedEventHandler(
serialPort1_DataReceived);
}
Autor: Andrés Gerardo Fuentes Covarrubias
22
23. 2. El codigo del manejador de eventos
private void serialPort1_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
strBufferIn = "";
//Debemos hacer una pausa, para que el buffer se llene por completo
//y pueda cargar todos los datos.
//Si esta pausa no se realiza, no carga las lineas por completo y solo
//nos muestra parte del mensaje enviado.
Thread.Sleep(250);
strBufferIn += serialPort1.ReadExisting();
if (serialPort1.BytesToRead > 0)
strBufferIn += serialPort1.ReadExisting();
String Linea;
Linea = strBufferIn;
}
//Guardamos la cadena original para "Split"
//Posterior
this.Invoke(new EventHandler(Actualiza_textbox));
Autor: Andrés Gerardo Fuentes Covarrubias
23
25. Siempre es posible manejar la barra de estado de nuestro formulario:
•Barra de estado
•Menú de opciones
Autor: Andrés Gerardo Fuentes Covarrubias
25
26. Para agregar el reloj del sistema a la barra de estado:
Agregue un control “timer”
Configure las propiedades
Autor: Andrés Gerardo Fuentes Covarrubias
26
27.
1
Ejecute los siguientes pasos en el orden indicado:
3
2
Cambie la propiedad
“Text” a “hh:mm:ss”
Agregar el código al control del timer:
private void timer1_Tick(object sender, EventArgs e)
{
statusStrip1.Items[0].Text = DateTime.Now.ToLongTimeString();
}
Autor: Andrés Gerardo Fuentes Covarrubias
27
28. Control mas efectivo sobre los caracteres
delimitadores
Posibilidad de hacer parsing en línea
Autor: Andrés Gerardo Fuentes Covarrubias
28
30. Use un delimitador de campo, por lo general
es el caracter “,”
Use un delimitador de cadena, por lo general
es el caracter “;”
Use el método Split
Procese los tokens encontrados
Autor: Andrés Gerardo Fuentes Covarrubias
30
32. private void Actualiza_textbox(object s, EventArgs e)
{
string[] parts = recibidos.Split(seps); //Tokenizamos la trama
if (parts.Length == 3)
{
//Validamos numero de
//tokens encontrdos, deben ser 3
lblTemp.Text = parts[1];
lblVolt.Text = parts[2];
}
lblRecibido.Text = recibidos;
txtRecibidos.Text += recibidos+"rn";
//Actualizamos etiquetas
//Visualizamos trama actual
//Actualizamos el textBox consola
}
Autor: Andrés Gerardo Fuentes Covarrubias
32
33.
'Definir las características de la comunicación
Serie.BaudRate = 19200
'Fijar velocidad de comunicaciones
Serie.DataBits = 8
'Longitud en bits para Byte de datos
Serie.Parity = Parity.Even
'Asignar paridad(enumeration parity)
Serie.StopBits = StopBits.Two
'Bits parada después byte de datos
'Abrir/Control/Liberar Puerto
Serie.Open()
'Abrir el puerto Serie
Serie.Close()
'Cerrar el Puerto Serie
Serie.Dispose()
'Liberar objeto
Dim SiNo As Integer
SiNo = Serie.IsOpen
'El Puerto esta abierto?
Dim Puerto As String
Puerto = Serie.PortName
'Nombre del puerto
Autor: Andrés Gerardo Fuentes Covarrubias
33
34.
'Manejo y Control de señales
Dim Estado As Boolean
Estado = Serie.CDHolding
Estado = Serie.CtsHolding
Estado = Serie.DsrHolding
Serie.DtrEnable = True
Serie.RtsEnable = True
'True=Activa / False=Inactiva
'Estado de la señal carrier detect
'Señal Clear to Send
'Señal Data Set Ready
'Activar de Data Terminal Ready
'Activar Request To Send
'Control Transmission/Recepcion
Serie.ReadBufferSize = 1024
'Dimensionar tamaño buffer recepción
Serie.WriteBufferSize = 1024
'Dimensionar tamaño buffer envío
Serie.ReadTimeout = 10
'Fuera de tiempo para las lecturas
Serie.WriteTimeout = 10
'Fuera de tiempo para las escrituras
Serie.Handshake = Handshake.XOnXOff
'Tipo control para recepción/envío
Serie.DiscardInBuffer()
'Borrar el buffer de entrada
Serie.DiscardOutBuffer()
'Borrar el buffer de salida
Autor: Andrés Gerardo Fuentes Covarrubias
34
35.
'Enviar datos
Contador = Serie.BytesToWrite
Serie.Write("Hola Mundo")
Serie.WriteLine("Hola Mundo")
'Leer datos
Contador = Serie.BytesToRead
'Bytes en espera de ser leídos
Serie.ReadByte()
'Leer un byte
Serie.ReadChar()
'Leer un char
Serie.ReadLine()
'Leer una línea
Serie.ReadExisting()
'Leer los datos existentes en buffer
'Bytes en espera de ser escritos
'Enviar una cadena de caracteres
'Enviar una línea
Autor: Andrés Gerardo Fuentes Covarrubias
35
36. Interfaz serial RS232C MCP2200
Circuito LM35z a °C
Registrador de temperaturas
Graficador de 2 canales
Autor: Andrés Gerardo Fuentes Covarrubias
36
37. El hardware de interfaz consta de un
convertidor de protocolo serial – paralelo
a USB, lo que lo hace muy atractivo para
estas aplicaciones.
El circuito esta basado en el MCP2200
de Microchip, este cuenta con una DLL
(librería) muy rica en funciones para
configuración de patillaje, entrada de
niveles digitales y salidas de control.
Autor: Andrés Gerardo Fuentes Covarrubias
37
38. Principales características:
•Modo full – duplex hasta 1Mbps
•Manejo de la conexión en modo Virtual
Serial Port bajo todas las versiones de
Windows, Linux y Mac
•Soporta Control de flujo
•Hasta 8 pines de propósito general
•Memoria de usuario de 256 bytes de
propósito general
•Leds de actividad para el monitoreo del
bus
•Totalmente programable en lenguajes
visuales mediante DLL de usuario.
Autor: Andrés Gerardo Fuentes Covarrubias
38
40. Para la implementación del modelo de
programación basta con instalar la referencia
externa en el proyecto a la DLL provista por el
fabricante.
Invocación de los objetos y métodos dentro
del código del proyecto
Autor: Andrés Gerardo Fuentes Covarrubias
40
41. bool ClearPin(pinNumber)
Pone en nivel 0 “pinNumber”
bool SetPin(pinNumber)
Pone en nivel 1 “pinNumber”
bool ReadPin(pinNumber, *pinValue)
Lee el nivel lógico en la entrada “pinNumber” y lo
refleja en la variable booleana “pinValue”
int ReadPinValue(pinNumber)
Lee el nivel lógico en la entrada “pinNumber”
Autor: Andrés Gerardo Fuentes Covarrubias
41
42. bool ReadPort(*portValue)
Lee el valor completo del puerto GPx como int y lo
refleja en la variable “portValue”
bool ReadPort(*portValue)
bool WritePort(portValue)
Autor: Andrés Gerardo Fuentes Covarrubias
42
44. bool IsConnected()
int ReadEEPROM(uiEEPAddress)
int WriteEEPROM(uiEEPAddress, ucValue)
Autor: Andrés Gerardo Fuentes Covarrubias
44
45.
ComPim: Para salida de datos
por medio de un Virtual Port
Monitoreo por medio de la
Terminal Virtual
Autor: Andrés Gerardo Fuentes Covarrubias
45
46.
Interconecta por “cable
cruzado” la terminal
virtual y el control
ComPim
Por medio de un
programa de
hiperterminal se puede
monitorear la actividad
serial RS232C
No se necesita
convertidor de protocolo
MAX232
Autor: Andrés Gerardo Fuentes
Covarrubias
46
47. Comunicaciones Full-Duplex
Compatibilidad 9600, 8 , N, 1
Programable en lenguaje de alto nivel
BaudRate totalmente configurable
Capaz de manejar e identificar paridad
Autor: Andrés Gerardo Fuentes Covarrubias
47
48. ZedGraph es uno de los controles mas
utilizados en ingeniería para desplegar
gráficos de puntos o líneas.
Como es un control externo es necesario
instalarlo como un componente adicional.
Autor: Andrés Gerardo Fuentes Covarrubias
48
49. La primera parte consiste en su inicialización
La segunda parte ocurre tambien en tiempo
de ejecución y consiste en la impresión de los
puntos recibidos y unirlos mediante lineas.
Autor: Andrés Gerardo Fuentes Covarrubias
49
51. 1. Definir un objeto tipo lista:
Consiste en la
inicialización del
control
Generalmente se
efectúa al cargar la
forma principal por
primera vez
Se puede usar una
función de usuario
PointPairList list1 = new PointPairList();
2. Crear la función de usuario:
private void inicializaGrafico(ZedGraphControl zgc)
{
GraphPane myPane = zgc.GraphPane;
// Titulos
myPane.Title.Text = "Gráfico de temperaturas";
myPane.XAxis.Title.Text = "Muestra";
myPane.YAxis.Title.Text = "Temperatura";
myPane.YAxis.Scale.Max = 150;
// Inicializa una curva con diamantes en cada muestra
// la palabra "temperatura" como titulo de la muestra
}
LineItem myCurve = myPane.AddCurve("Temperatura",
list1, Color.Red,
SymbolType.None);
3. Inicializarla dentro de Form_Load1
4. No olvidar referenciar el NameSpace ZedGraph con el Using
correspondiente
Autor: Andrés Gerardo Fuentes Covarrubias
51
52. private void Form1_Load(object sender, EventArgs e)
{
UpdateSerialPorts();
inicializaGrafico(graficoTemp);
}
private void inicializaGrafico(ZedGraphControl zgc)
{
GraphPane myPane = zgc.GraphPane;
// Titulos
myPane.Title.Text = "Gráfico de temperaturas";
myPane.XAxis.Title.Text = "Muestra";
myPane.YAxis.Title.Text = "Temperatura";
myPane.YAxis.Scale.Max = 150;
// Inicializa una curva con diamantes en cada muestra tomada
// la palabra "temperatura" como titulo de la muestra
}
LineItem myCurve = myPane.AddCurve("Temperatura", list1, Color.Red, SymbolType.None);
Autor: Andrés Gerardo Fuentes Covarrubias
52
53. La recepción debe cambiar ya que
tradicionalmente se procesa el buffer de
recepción en conjunto.
Ahora deberá procesarse carácter a carácter
hasta obtener un carácter de fin de trama =
“;”
Despues de recibir el fin de trama deberá
separarse los campos con el método Split
Autor: Andrés Gerardo Fuentes Covarrubias
53