comunicaciones seriales c# 2012
DESCRIPTION
Recurso Didáctico para la Materia Sistemas Embebidos y ControlTRANSCRIPT
Caso: Visual C# 2012 ExpressMICROCHIP MCP2200
Por:
M.C. ANDRÉS GERARDO FUENTES COVARRUBIAS
1
Sistemas Digitales Avanzados
Instalación de Virtual Serial PortCreación de una nueva aplicación en
C# 2012 toolStrip y componentes básicosManejo de los puertos serialesApertura de un puertoTransmisiónRecepción
Autor: Andrés Gerardo Fuentes Covarrubias 2
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
Autor: Andrés Gerardo Fuentes Covarrubias 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 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 6
Controles en la aplicación, ToolStrip.
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
ComboBox
TextBox Boton Label
Autor: Andrés Gerardo Fuentes Covarrubias 7
Controles en la aplicación, área de trabajo
TabControl
OvalShape
Botones
toolStrip
Autor: Andrés Gerardo Fuentes Covarrubias 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 referenciasexternas
Autor: Andrés Gerardo Fuentes Covarrubias 9
if(!serialPort1.IsOpen){
try{
serialPort1.Open();}catch (System.Exception ex){
MessageBox.Show(ex.ToString());}
}
La apertura de un puerto serial en Visual C# es tan sencillo como agregar el siguiente código al botón “Conectar” del ToolStrip:
Las propiedades del control SerialPort se pueden establecer en tiempo de diseño mediante el cuadro de propiedades.
Autor: Andrés Gerardo Fuentes Covarrubias 10
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 usuario serialPort1.Open(); //Abrir el puerto
Siempre se puede abrir un puerto con el código siguiente y tambien establecer las caracteristicas de la trama:
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 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
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"); } }
Agregue el código del botón
Autor: Andrés Gerardo Fuentes Covarrubias12
byte[] miBuffer= new byte[1];
miBuffer[0] = 0x62; //Carácter a enviar por el puerto.SP1.Write(miBuffer, 0, miBuffer.Length);
Siempre es posible enviar también un solo caracter por el puerto serial:
// Enviar tramabyte[] miBuffer= new byte[3]; // Tres caracteres máximo.
miBuffer[0] = 0x74;miBuffer[1] = 0x54;miBuffer[2] = 0x13;
SP1.Write(miBuffer, 0, miBuffer.Length);
Por ejemplo, si lo que se desea es enviar una trama completa, entonces:
Autor: Andrés Gerardo Fuentes Covarrubias 13
strBufferOut = "1"; //Buffer de transmisión serialPort1.DiscardOutBuffer(); //Limpiamos el buffer de transmisión serialPort1.Write(strBufferOut); //Enviar caracteres
Cada control incluye código:
Indicadores con el control Ovalshape para simular leds.
Salidas por botón
También se puede vincular código a otros controles de usuario:
Autor: Andrés Gerardo Fuentes Covarrubias 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 15
private void UpdateSerialPorts() { toolStripComboBox1.Items.Clear();
// Añadir solo los puertos válidos try { foreach (String d in SerialPort.GetPortNames()) { toolStripComboBox1.Items.Add(d);} } catch { UpdateSerialPorts(); return; }
toolStripComboBox1.SelectedIndex = toolStripComboBox1.Items.Count - 1; if (toolStripComboBox1.Items.Count > 0) { toolStripComboBox1.SelectedIndex = 0; toolStripTextBox1.Text = toolStripComboBox1.Items[toolStripComboBox1.SelectedIndex].ToString(); } }
private void btActualizar_Click(object sender, EventArgs e)
{ UpdateSerialPorts(); }
Autor: Andrés Gerardo Fuentes Covarrubias 16
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.
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
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
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
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
Autor: Andrés Gerardo Fuentes Covarrubias 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 22
1. Codigo de al cargar el formulario:
public Form1() {
txtRecibidos.Text = ""; strBufferIn = ""; serialPort1.DataReceived += new
SerialDataReceivedEventHandler(serialPort1_DataReceived);
}
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:
Autor: Andrés Gerardo Fuentes Covarrubias 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 24
2. El codigo del “delegado”
private void Actualiza_textbox(object s, EventArgs e) { txtRecibidos.Text += strBufferIn + "\r\n"; }
Autor: Andrés Gerardo Fuentes Covarrubias 25
Siempre es posible manejar la barra de estado de nuestro formulario:
•Barra de estado
•Menú de opciones
Autor: Andrés Gerardo Fuentes Covarrubias 26
Agregue un control “timer”
Para agregar el reloj del sistema a la barra de estado:
Configure las propiedades
Ejecute los siguientes pasos en el orden indicado:
Autor: Andrés Gerardo Fuentes Covarrubias 27
Agregar el código al control del timer:
private void timer1_Tick(object sender, EventArgs e){ statusStrip1.Items[0].Text = DateTime.Now.ToLongTimeString();}
1 2 3
Cambie la propiedad“Text” a “hh:mm:ss”
Control mas efectivo sobre los caracteres delimitadores
Posibilidad de hacer parsing en línea
Autor: Andrés Gerardo Fuentes Covarrubias 28
Autor: Andrés Gerardo Fuentes Covarrubias 29
private void serialPort1_DataReceived(object sender, SerialDataReceivedEventArgs e)
{ recibidos = ""; carSerial = (char) 0; while(carSerial!=';') { carSerial = (char) serialPort1.ReadChar(); if (carSerial == ';') break; recibidos += carSerial.ToString(); }
this.Invoke(new EventHandler(Actualiza_textbox)); }
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 SplitProcese los tokens encontrados
Autor: Andrés Gerardo Fuentes Covarrubias 30
public Form1() { InitializeComponent(); }
private void btSplit_Click(object sender, EventArgs e)
{ str = txtCadena.Text; string[] parts =
str.Split(seps); for (int i = 0; i < parts.Length;
i++) cadenaSplit += parts[i]+"\
r\n"; txtConsola.Text =
cadenaSplit; } }}
Autor: Andrés Gerardo Fuentes Covarrubias 31
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;
namespace splitCampos{ public partial class Form1 : Form { string str; char[] seps={','}; string cadenaSplit;
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]; //Actualizamos etiquetas lblVolt.Text = parts[2]; } lblRecibido.Text = recibidos; //Visualizamos trama actual txtRecibidos.Text += recibidos+"\r\n"; //Actualizamos el textBox
consola }
Autor: Andrés Gerardo Fuentes Covarrubias 32
'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
'Manejo y Control de señales Dim Estado As Boolean 'True=Activa / False=Inactiva
Estado = Serie.CDHolding 'Estado de la señal carrier detect Estado = Serie.CtsHolding 'Señal Clear to Send Estado = Serie.DsrHolding 'Señal Data Set Ready Serie.DtrEnable = True 'Activar de Data Terminal Ready Serie.RtsEnable = True '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
'Enviar datos Contador = Serie.BytesToWrite 'Bytes en espera de ser
escritos Serie.Write("Hola Mundo") 'Enviar una cadena de caracteres Serie.WriteLine("Hola Mundo") 'Enviar una línea '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
Autor: Andrés Gerardo Fuentes Covarrubias 35
Interfaz serial RS232C MCP2200Circuito LM35z a °CRegistrador de temperaturasGraficador de 2 canales
Autor: Andrés Gerardo Fuentes Covarrubias 36
Autor: Andrés Gerardo Fuentes Covarrubias 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 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 39
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
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
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
void InitMCP2200(VID, PID)bool ConfigureIO(mask)
Autor: Andrés Gerardo Fuentes Covarrubias 43
bool IsConnected() int ReadEEPROM(uiEEPAddress) int WriteEEPROM(uiEEPAddress,
ucValue)
Autor: Andrés Gerardo Fuentes Covarrubias 44
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
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
Comunicaciones Full-DuplexCompatibilidad 9600, 8 , N, 1Programable en lenguaje de alto
nivelBaudRate totalmente configurableCapaz de manejar e identificar
paridad
Autor: Andrés Gerardo Fuentes Covarrubias 47
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
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
Autor: Andrés Gerardo Fuentes Covarrubias 50
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
1. Definir un objeto tipo lista: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_Load14. No olvidar referenciar el NameSpace ZedGraph con
el Using correspondiente
Autor: Andrés Gerardo Fuentes Covarrubias 51
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
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
private void Actualiza_textbox(object s, EventArgs e){ string[] parts = strBufferIn.Split(seps);
if (parts.Length == 3) { lblTemp.Text = parts[1]; temperaturaCanal1 = Convert.ToSingle(parts[1]); numMuestra++; float x = (float)numMuestra; float y = (float)temperaturaCanal1; list1.Add(x, y); graficoTemp.AxisChange(); graficoTemp.Refresh(); lblVolt.Text = parts[2]; } txtConsola.Text += strBufferIn + "\r\n";}
Autor: Andrés Gerardo Fuentes Covarrubias 54
[email protected] [email protected] [email protected]:
/Andres.FuentesCovarrubias
Autor: Andrés Gerardo Fuentes Covarrubias 55