Sie sind auf Seite 1von 43

Manual 8

Introduccin al puerto serial


El puerto serie es una de las interfaces de comunicacin mas populares que existen, desde los aos 60's se encuentra en equipos de todo tipo y hasta ahora sigue implementndose por su versatilidad y sencillez. El enlace serial solo requiere de 3 cables: Transmisin, Recepcin y Tierra, en la prctica existen problemas por la cada de voltaje en la seal, cuando falta algn bit de la trama todos los dems se ven afectados y recibimos un carcter errneo, es importante considerar este detalle al momento de programar en C#, siempre debe corroborar los datos y establecer identificadores al final de cada trama.

La primera versin del puerto serial tena un conector tipo DB-25 como el usado actualmente en el puerto paralelo, sin embargo muchos de los pines no se aplicaban, IBM ofreci la solucin con el conector DB9.

Prctica: Chat por puerto serie entre 2 computadoras


En este ejercicio vamos a crear un programa de Chat por RS232, para que funcione se ocupan dos computadoras con conector DB9 y el mismo programa, los cables se cruzan en los pines RX y TX. Usted requiere dos computadoras con C# y puerto serial para probar el ejemplo, tambin ocupa dos cables RS232 para cruzar los pines 2 y 3.
5 5 9 4 8 3 7 2 6 1 1 2 6 3 7 4 8

Conector DB9 PC1

Conector DB9 PC2

Tambin es posible probarlo con una computadora, solo cruzamos los pines 2 y 3 para recibir el mismo dato que enviamos.

Manual 8

Es necesario contar con un puerto COM habilitado en el administrador de dispositivos de la PC, los convertidores USB-Serial son vlidos. En el administrador de dispositivos de Windows puede ver todos los puertos disponibles y el identificador asignado. En nuestro caso utilizamos el COM3.

Ahora creamos un nuevo proyecto de Windows Forms donde arrastramos los siguientes controles:

TextBox Name: txtConversacion ListBox Name: ListBoxChat

Formulario Name: frmChat Text. Chat RS232

Button Name: btnEnviar Enabled: False TextBox Name: txtMensaje Label Name: lblNick SerialPort Name: serialPortChat BaudRate: 9600 DataBits: 8 PortName: COM3 StopBits: 1

CheckBox Name: chkPuertoSerie Text: Abrir Puerto Serie TextBox Name: txtNick

Manual 8

En nuestro cdigo declaramos un objeto string con mbito para toda la clase.
using using using using using using using using System; System.Collections.Generic; System.ComponentModel; System.Data; System.Drawing; System.Linq; System.Text; System.Windows.Forms;

namespace ProyectoChatRS232 { public partial class frmChat : Form { string datoSerial; public frmChat() { InitializeComponent(); }

Ahora en el evento DataReceived de nuestro puerto serie:

private void serialPortChat_DataReceived(object sender, System.IO.Ports.SerialDataReceivedEventArgs e) { try //intentamos leer el puerto { serialPortChat.ReadTimeout = 2000;//espera 2 segundos por el dato //almacena toda la cadena de datos hasta que lee "-FIN-" datoSerial = serialPortChat.ReadTo("-FIN-"); //ahora recorta los datos e invoca al manejador this.Invoke(new EventHandler(TextoRecibido)); } catch //no llego la cadena completa, interceptamos el error { MessageBox.Show("Error, no recib el identificador final de la cadena -FIN-"); serialPortChat.DiscardInBuffer(); //borra los datos del buffer de entrada } } }

Creamos una funcin para manejar el evento TextoRecibido: (se debe teclear manualmente)
private void TextoRecibido(object sender, EventArgs e) { txtConversacion.Text = ""; txtConversacion.AppendText(datoSerial); listBoxChat.Items.Add(datoSerial); }

Manual 8

Para el evento click del botn:

private void btnEnviar_Click(object sender, EventArgs e) { string mensaje = txtNick.Text + " dice: " + txtMensaje.Text; serialPortChat.Write(mensaje + "-FIN-"); listBoxChat.Items.Add(mensaje.ToString()); }

Finalmente en el CheckBox que habilita el puerto:

private void chkPuertoSerie_CheckedChanged(object sender, EventArgs e) {if (chkPuertoSerie.Checked) { try { if (!serialPortChat.IsOpen) //si el puerto esta cerrado { serialPortChat.Open(); } //habilita el botn solo si esta abierto el puerto btnEnviar.Enabled = true; chkPuertoSerie.Text = "Puerto Abierto"; chkPuertoSerie.BackColor = Color.YellowGreen; } catch { MessageBox.Show("Algo anda mal, no pude abrir el puerto COM"); chkPuertoSerie.Checked = false; chkPuertoSerie.Text = "Puerto Cerrado"; } } else { try { if (serialPortChat.IsOpen) { serialPortChat.Close(); chkPuertoSerie.BackColor = Color.Red; chkPuertoSerie.Text = "Puerto Cerrado"; btnEnviar.Enabled = false; } } catch { MessageBox.Show("Algo anda mal, no pude cerrar el COM"); } } }

Manual 8

Para realizar la prueba debe instalar el ejemplo en ambas computadoras, recuerde que el puerto COM puede ser diferente en cada una, en dado caso modifique las propiedades del control SerialPort.

Recuerde cruzar los pines 2 y 3 en los cables.

El primer paso es abrir el puerto serie: Usted puede elegir el Nick de usuario y escribir los mensajes en forma similar al Messenger.

Cuando ambas computadoras abren su puerto se establece el enlace. Recuerde que si no tiene dos computadoras puede cruzar los pines 2 y 3 de su cable y recibir los datos que enva.

La comunicacin por cable y RS232 maneja voltajes de +15 y -15 volts, aparte transmitir y recibir por dos hilos ofrece un buen grado de seguridad en los datos, personalmente he comunicado equipos a distancias mayores a 70 metros.

Manual 8

Comunicacin con Microcontroladores PIC


La comunicacin con microcontroladores abre gran cantidad de posibilidades a sus prototipos, usted puede crear todo el control en el PIC y una interfaz de graficacin, configuracin y reportes en C#. La forma de extraer los datos del PIC ser por puerto Serial. Los siguientes ejemplos estn vinculados con el manual 7 de este curso.

El diagrama para el PIC es el siguiente:


5 Volts

11 32 31 12 VDD VDD VSS VSS RB0/AN12/INT RB1/AN10/C12IN3RB2/AN8 RB3/AN9/PGM/C12IN2RB4/AN11 RB5/AN13/T1G RB6/ICSPCLK RB7/ICSPDAT 33 34 35 36 37 38 39 40

5 Volts

Capacitores 1 ufaradio

+ 1 2 3 4 5 6 7 8 16 15 14 13 12 11 10 9 Vcc Gnd T1OUT R1IN R1OUT T1IN T2IN R2OUT

16F887
No ocupa oscilador!
Leds
Resistencias 330 ohm

DISPLAY LCD

2 3 4 5 6 7 14 13 8 9 10 1

RA0/AN0/ULPWU/C12IN0RA1/AN1/C12IN1RA2/AN2/VREF-/CVREF/C2IN+ RA3/AN3/VREF+/C1IN+ RA4/T0CKI/C1OUT RA5/AN4/SS/C2OUT RA6/OSC2/CLKOUT RA7/OSC1/CLKIN RC0/T1OSO/T1CKI RC1/T1OSI/CCP2 RE0/AN5/RD RC2/P1A/CCP1 RE1/AN6/WR RC3/SCK/SCL RE2/AN7/CS RC4/SDI/SDA RE3/MCLR/Vpp/ RC5/SDO RC6/TX/CK RC7/RX/DT

RD0 RD1 RD2 RD3 RD4 RD5/P1B RD6/P1C RD7/P1D

19 20 21 22 27 28 29 30 15 16 17 18 23 24 25 26

ENABLE RS RW D4 D5 D6 D7

+ -

5 9 4 8 3 7 2 6 1

Conector DB9 hembra

Resistencias 1k ohm

Entrada analgica con potencimetro de 10k ohm

Microswitch

MAX232

+ + -

C1+ V+ C1C2+ C2VT2OUT R2IN

Manual 8

Prctica: Recepcin de datos por puerto serie desde el PIC


Este ejercicio esta orientado a recibir los datos de la prctica 9 en el manual 7, su funcin es recibir el dato y filtrarlo para su monitoreo en el Label. Creamos un nuevo proyecto de Windows Forms y agregamos los siguientes controles:
TextBox Name: txtRecibeDatos Label Name: lblCanalRe0 Text: Lectura RE0 CheckBox Name: chkPuertoSerie Text: Abrir Puerto Serie BackColor: Red SerialPort Name: serialPort Formulario Name: frmTarjeta

El puerto serial debe estar con la misma configuracin del PIC: #use rs232(baud=9600,parity=N,xmit=PIN_C6,rcv=PIN_C7,bits=8)

using using using using using using using using

System; System.Collections.Generic; System.ComponentModel; System.Data; System.Drawing; System.Linq; System.Text; System.Windows.Forms;

namespace LecturaPuertoSerial { public partial class frmLecturaSerial : Form { string datoSerial; public frmLecturaSerial() { InitializeComponent(); }

Manual 8

private void TextoRecibido(object sender, EventArgs e) { //en esta funcin recibimos los datos para su anlisis. txtRecibeDatos.Text = ""; txtRecibeDatos.AppendText(datoSerial); analisisCadenas(datoSerial); } private void analisisCadenas(string cadena) { if (cadena.Contains("RE0")) { //borramos la parte de texto de la cadena recibida cadena = cadena.Replace("RE0", ""); lblCanalRe0.Text = "Lectura RE0: " + cadena; } } private void chkPuertoSerie_CheckedChanged(object sender, EventArgs e) { if (chkPuertoSerie.Checked) { try { if (!serialPort.IsOpen) //si el puerto esta cerrado { serialPort.Open(); } chkPuertoSerie.Text = "Puerto Abierto"; chkPuertoSerie.BackColor = Color.YellowGreen; } catch { MessageBox.Show("Algo anda mal con el puerto COM"); chkPuertoSerie.Checked = false; } } else { try { if (serialPort.IsOpen) { serialPort.Close(); chkPuertoSerie.BackColor = Color.Red; chkPuertoSerie.Text = "Puerto Cerrado"; } }

Manual 8

catch { MessageBox.Show("Algo anda mal no pude cerrar el COM"); } } } private void serialPort_DataReceived(object sender, System.IO.Ports.SerialDataReceivedEventArgs e) { try //intentamos leer el puerto { serialPort.ReadTimeout = 2000;//espera 2 segundos por el dato //almacena toda la cadena de datos hasta que lee "Fin" datoSerial = serialPort.ReadTo("Fin"); //ahora recorta los datos e invoca al manejador this.Invoke(new EventHandler(TextoRecibido)); } catch //no llego la cadena completa, interceptamos el error { MessageBox.Show("Error, no recib el identificador final de la cadena: Fin" + datoSerial); //borra los datos del buffer de entrada serialPort.DiscardInBuffer(); } } } }

Al ejecutar ambos programas puede monitorear el valor del potencimetro en pantalla.

Manual 8

Prctica: Envo de datos por puerto serie al PIC


Este ejercicio esta vinculado a la prctica 10 del manual 7, el objetivo es mandar un byte por puerto serial al PIC. Creamos un nuevo proyecto de Windows Forms y agregamos los siguientes controles:

Button Name: btnMandaByte Enabled: False CheckBox Name: chkPuertoSerie Text: Abrir Puerto Serie BackColor: Red SerialPort Name: serialPort
El puerto serial debe estar con la misma configuracin del PIC: #use rs232(baud=9600,parity=N,xmit=PIN_C6,rcv=PIN_C7,bits=8)

Formulario Name: frmEnvioSerial Text: Envo de byte por puerto seria NumericUpDown Name: numStepByte Minimum: 0 Maximum: 255

using using using using using using using using

System; System.Collections.Generic; System.ComponentModel; System.Data; System.Drawing; System.Linq; System.Text; System.Windows.Forms;

namespace EnvioDatosSerial { public partial class frnEnvioSerial : Form { public frnEnvioSerial() { InitializeComponent(); }

Manual 8

private void chkPuertoSerie_CheckedChanged(object sender, EventArgs e) { if (chkPuertoSerie.Checked) { try { if (!serialPort.IsOpen) //si el puerto esta cerrado { serialPort.Open(); } btnMandaByte.Enabled = true; chkPuertoSerie.Text = "Puerto Abierto"; chkPuertoSerie.BackColor = Color.YellowGreen; } catch { MessageBox.Show("Algo anda mal con el puerto COM"); chkPuertoSerie.Checked = false; } } else { try { if (serialPort.IsOpen) { serialPort.Close(); chkPuertoSerie.BackColor = Color.Red; chkPuertoSerie.Text = "Puerto Cerrado"; btnMandaByte.Enabled = false; } } catch { MessageBox.Show("Algo anda mal no pude cerrar el COM"); } } } private void btnMandaByte_Click(object sender, EventArgs e) { // ahora enva el numero entre 0 y 255 del numStepByte acompaado de un Enter serialPort.Write(numStepByte.Value.ToString() + (char)13); } } }

Al ejecutar ambos programas puede mandar los datos desde el numericStepper al PIC, el dato se refleja en el display LCD.

Manual 8

En los ejemplos anteriores establecimos envo y recepcin serial por separado, en el siguiente ejercicio creamos la comunicacin bidireccional por medio de mensajes entre C# y el PIC.

Prctica: Comunicacin serial bidireccional con PIC 16f887


En este ejercicio la cantidad de comandos de intercambio es mayor, por tal motivo tenemos 3 mensajes para que C# y el PIC se comuniquen: C# manda los siguientes mensajes al PIC: "escribe: Cuando el PIC recibe esta cadena se queda esperando un nmero entre 0-255 que imprime en el puerto A. RE0": Con este mensaje el PIC nos responde con la conversin a decimal del puerto analogico RE0 (0-5 volts), la resolucin es de 8 bits. "byteEnt" : Esta cadena le dice al PIC que nos responda con los 8 bits de entradas digitales del microswitch.

Mandame el REO
serialPort.Write("RE0" + (char)13);

"comando identificado, ah va!!"

C#
El PIC esta siempre esperando cualquiera de los tres mensajes para responder.

PIC

Cada mensaje que manda el PIC tiene un identificadorl con la cadena Fin, esto permite hacer mas eficiente la lectura en C# y conocer el final de la trama de datos.

Manual 8

Creamos un nuevo proyecto de Windows Forms:

Arrastramos los siguientes controles:


Formulario Name: frmTarjeta Label Name: lblCanalRe0 Text: Re0

TextBox Name: txtRecibeDatos Button Name: btnRecibeRe0 Enabled: False Text: Recibe canal anlogo Button Name: btnRecibeDatDig Enabled: False Text: Recibe datos digitales Button Name: btnMandaByte Enabled: False Text: Manda byte puerto A

ListBox Name: listBoxDatosEntrada NumericUpDown Name: numStepByte Minimum: 0 Maximum: 255 CheckBox Name: chkPuertoSerie Text: Abrir Puerto Serie BackColor: Red

SerialPort Name: serialPort

El puerto serial debe estar con la misma configuracin del PIC: #use rs232(baud=9600,parity=N,xmit=PIN_C6,rcv=PIN_C7,bits=8)

Manual 8

Este ejercicio es similar al Chat, tambin creamos un objeto string visible para toda la clase:
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 ProyectoPIC16f883 { public partial class frmTarjeta : Form { string datoSerial; public frmTarjeta() { InitializeComponent(); }

En el CheckBox escribimos:
private void chkPuertoSerie_CheckedChanged(object sender, EventArgs e) { if (chkPuertoSerie.Checked) { try { if (!serialPort.IsOpen) //si el puerto esta cerrado { serialPort.Open(); } btnMandaByte.Enabled = true; btnRecibeRe0.Enabled = true; btnRecibeDatDig.Enabled = true; chkPuertoSerie.Text = "Puerto Abierto"; chkPuertoSerie.BackColor = Color.YellowGreen; } catch MessageBox.Show("Algo anda mal con el puerto COM"); { chkPuertoSerie.Checked = false; } } else { try { if (serialPort.IsOpen) { serialPort.Close(); chkPuertoSerie.BackColor = Color.Red; chkPuertoSerie.Text = "Puerto Cerrado"; btnMandaByte.Enabled = false; btnRecibeRe0.Enabled = false; btnRecibeDatDig.Enabled = false; } }

Manual 8

catch { MessageBox.Show("Algo anda mal no pude cerrar el COM"); } } } }

Para cada uno de los botones en su evento Click escribimos:

private void btnMandaByte_Click(object sender, EventArgs e) { // primero se manda la cadena "escribe" con el Enter para // avisar que viene un numero despus, (char)13= Enter serialPort.Write("escribe" + (char)13); // ahora enva el numero entre 0 y 255 del numStepByte serialPort.Write(numStepByte.Value.ToString() + (char)13); } private void btnRecibeDatDig_Click(object sender, EventArgs e) { // Al mandar "byteEnt" al PIC nos regresa los 8 bits de entrada // el orden viene de esta manera: // b0=RA7, b1=RA6, b2=RC0,b3=RC1,b4=RC2,b5=RC3,b6=RC4,b7=RC5 serialPort.Write("byteEnt" + (char)13); //(char)13= Enter } private void btnRecibeRe0_Click(object sender, EventArgs e) { //al mandar "RE0" el PIC nos responde con el valor decimal de //la conversin del canal anlogo a 8 bits serialPort.Write("RE0" + (char)13); }

De nuevo creamos una funcin que refleje los datos recibidos:


private void TextoRecibido(object sender, EventArgs e) { // en esta funcin recibimos los datos para su anlisis y reordenamiento. txtRecibeDatos.Text = ""; txtRecibeDatos.AppendText(datoSerial); //ahora llamamos a la funcin que extrae los datos // MessageBox.Show(datoSerial); analisisCadenas(datoSerial); }

Manual 8

Ahora otra nueva funcin para separar los datos:


private void analisisCadenas(string cadena) { string cad; //cuando el PIC nos manda el dato anlogo del Ra0 // le quitamos lo que no sirve if (cadena.Contains("Ra0+")) {//El dato siempre llega de esta forma: Ra0+ numero +, // solo nos quedamos con: numero cad = cadena.Replace("Ra0+", ""); cad = cad.Replace("+", ""); lblCanalAn0.Text = "Lectura RA0: " + cad; } //cuando nos llega la trama con los bits de entrada if (cadena.Contains("byteEnt")) {//limpiamos todos los valores antes de actualizar listBoxDatosEntrada.Items.Clear(); cad = cadena.Replace("byteEnt", ""); //con el Split cortamos cada parte de la cadena donde exista un '+' //con cada dato se forma un arreglo de cadenas string[] arreglocadena = cad.Split('+'); foreach (string st in arreglocadena) { //ahora cada miembro del arreglo entra a los items del listbox listBoxDatosEntrada.Items.Add(st.ToString()); } } }

En el evento DataReceived del Puerto serie:


private void serialPort_DataReceived(object sender, System.IO.Ports.SerialDataReceivedEventArgs e) { try //intentamos leer el puerto { serialPort.ReadTimeout = 2000;//espera 2 segundos por el dato //almacena toda la cadena de datos hasta que lee "Fin" datoSerial = serialPort.ReadTo("Fin"); //ahora recorta los datos e invoca al manejador this.Invoke(new EventHandler(TextoRecibido)); } catch //no llego la cadena completa, interceptamos el error { MessageBox.Show("Error, no recib el identificador final de la cadena: Fin"); serialPort.DiscardInBuffer(); //borra los datos del buffer de entrada } }

Ahora podemos probar la comunicacin bidireccional con el PIC, tenga especial cuidado en no conectar la tierra del DB9 a un voltaje externo.

Manual 8

Al pulsar los botones en C# le manda la peticin al Pic, este digitaliza el dato anlogo y los 8 bits de entrada para mandarlos por serial, tambin escribe en el puerto B el valor del Numeric Up Down.

Prctica: Envo de datos para control de led RGB


Este ejercicio esta vinculado con la prctica 17 del manual 7. El objetivo es mandar los valores RGB al PIC configurados previamente en los TrackBar.

Manual 8

En un nuevo proyecto de Windows Forms creamos la interfaz.

Formulario Name: frmLedRGB Text: Control de led RGB TrackBar Name: tBarRed LargeChange: 1 Minimum: 0 Maximum: 255 TrackBar Name: tBarGreen LargeChange: 1 Minimum: 0 Maximum: 255 TrackBar Name: tBarBlue LargeChange: 1 Minimum: 0 Maximum: 255 SerialPort Name: serialPort

Label Name: lblRGB Button Name: btnR BackColor: Red Text: Actualiza Rojo Button Name: btnG BackColor: 0, 192, 0 Text: Actualiza Verde Button Name: btnB BackColor: DodgerBlue Text: Actualiza Azul CheckBox Name: chkPuertoSerie Text: Abrir Puerto Serie BackColor: Red

El puerto serial debe estar con la misma configuracin del PIC: #use rs232(baud=9600,parity=N,xmit=PIN_C6,rcv=PIN_C7,bits=8)

Seleccionando los 3 TrackBar nos vamos a sus eventos en cada Scroll.

y creamos un mtodo compartido: "miEvento"

Manual 8

Escribimos el siguiente cdigo.


using using using using using using using using System; System.Collections.Generic; System.ComponentModel; System.Data; System.Drawing; System.Linq; System.Text; System.Windows.Forms;

namespace LedRGB { public partial class frmLedRGB : Form { public frmLedRGB() { InitializeComponent(); } private void chkPuertoSerie_CheckedChanged(object sender, EventArgs e) { if (chkPuertoSerie.Checked) { try { if (!serialPort.IsOpen) //si el puerto esta cerrado { serialPort.Open(); } chkPuertoSerie.Text = "Puerto Abierto"; chkPuertoSerie.BackColor = Color.YellowGreen; btnRGB.Enabled = true; } catch { MessageBox.Show("Algo anda mal con el puerto COM"); chkPuertoSerie.Checked = false; } } else { try { if (serialPort.IsOpen) { serialPort.Close(); chkPuertoSerie.BackColor = Color.Red; chkPuertoSerie.Text = "Puerto Cerrado"; btnRGB.Enabled = false; } } catch { MessageBox.Show("Algo anda mal no pude cerrar el COM"); } } }

Manual 8

//este mtodo se manda llamar por los eventos Scroll de cada TrackBar //su objetivo es actualizar el color del lblRGB private void miEvento(object sender, EventArgs e) { lblRGB.Text = "R:" + tBarRed.Value.ToString() + " G:" + tBarGreen.Value.ToString() + " B:" + tBarBlue.Value.ToString(); lblRGB.BackColor = Color.FromArgb(tBarRed.Value, tBarGreen.Value, tBarBlue.Value); } private void btnR_Click(object sender, EventArgs e) { //manda al PIC la letra R acompaada del byte y el ENTER serialPort.Write("R" + tBarRed.Value.ToString() + (char)13); } private void btnG_Click(object sender, EventArgs e) { //manda al PIC la letra G acompaada del byte y el ENTER serialPort.Write("G" + tBarGreen.Value.ToString() + (char)13); } private void btnB_Click(object sender, EventArgs e) { //manda al PIC la letra B acompaada del byte y el ENTER serialPort.Write("B" + tBarBlue.Value.ToString() + (char)13); } } }

Ejecute ambos programas para comprobar la comunicacin.

Prctica: Comunicacin por USB con el PIC


Este ejercicio esta vinculado con la prctica 18 del manual 7, el objetivo es intercambiar datos por medio de un puerto COM virtual por medio de las libreras CDC. Recuerde... Para nosotros el puerto USB se va a comportar como un COM normal, es el mismo tipo de programacin que manejamos en ejemplos anteriores.

Manual 8

Creamos un proyecto nuevo de Windows Forms:

TextBox Name: txtRecibeDatos Button Name: btnMandaDato Text: Manda letra a

Formulario Name: frmUSB Text:Comunicacin USB con PIC

SerialPort Name: serialPort

CheckBox Name: chkPuertoSerie Text: Abrir Puerto Serie BackColor: Red

Para realizar este ejercicio su hardware debe estar listo y el driver CDC previamente instalado, los pasos se encuentran en el manual 7 (pgina 60).

Recuerde que el identificador que asignamos al puerto COM virtual solo nos sirve para pruebas, si usted desarrolla un producto con CDC debe pagar una licencia particular.

Manual 8

using using using using using using using using

System; System.Collections.Generic; System.ComponentModel; System.Data; System.Drawing; System.Linq; System.Text; System.Windows.Forms;

namespace ComunicacionUSB { public partial class frmUSB : Form { string datoSerial; public frmUSB() { InitializeComponent(); } private void chkPuertoSerie_CheckedChanged(object sender, EventArgs e) { if (chkPuertoSerie.Checked) { try { if (!serialPort.IsOpen) //si el puerto esta cerrado { serialPort.Open(); } btnMandaDato.Enabled = true; chkPuertoSerie.Text = "Puerto Abierto"; chkPuertoSerie.BackColor = Color.YellowGreen; } catch { MessageBox.Show("Algo anda mal con el puerto COM"); chkPuertoSerie.Checked = false; } } else { try { if (serialPort.IsOpen) { serialPort.Close(); chkPuertoSerie.BackColor = Color.Red; chkPuertoSerie.Text = "Puerto Cerrado"; btnMandaDato.Enabled = false; } } catch { MessageBox.Show("Algo anda mal no pude cerrar el COM"); } } }

Manual 8

private void TextoRecibido(object sender, EventArgs e) { //en esta funcin recibimos los datos para su anlisis y reordenamiento. txtRecibeDatos.Text = ""; txtRecibeDatos.AppendText(datoSerial); } private void serialPort_DataReceived(object sender, System.IO.Ports.SerialDataReceivedEventArgs e) { try //intentamos leer el puerto { serialPort.ReadTimeout = 2000;//espera 2 segundos por el dato //almacena toda la cadena de datos hasta que lee "Fin" datoSerial = serialPort.ReadTo("Fin"); //ahora recorta los datos e invoca al manejador this.Invoke(new EventHandler(TextoRecibido)); } catch //no llego la cadena completa, interceptamos el error { MessageBox.Show("Error, no recib el identificador final de la cadena: Fin" + datoSerial); serialPort.DiscardInBuffer(); //borra los datos del buffer de entrada } } private void btnMandaDato_Click(object sender, EventArgs e) //manda el carcter "a" { serialPort.Write("a"); } } }

Presione el botn y el PIC encender el A1 (led amarillo), tambin recibir la letra "a" por parte del PIC.

Hasta el momento tenemos el conocimiento bsico para comunicarnos con el PIC por serial, ahora vamos a entrar a otro tipo de control que no requiere microcontroladores, es un perifrico sencillo que tienen la mayora de las PC's, aunque tiene limitaciones trataremos de darle un enfoque til, nos referimos al Puerto Paralelo.

Manual 8

Prctica: Control del puerto paralelo en C#


El manejo del puerto paralelo le permite hacer proyectos muy bsicos de control sin necesidad de PIC's o PLC's, en los siguientes ejercicios aprenderemos a leer y escribir datos digitales con la interfaz electrnica necesaria. El puerto paralelo vio la luz desde la primera computadora personal de IBM (1981), su enfoque inicial fue para impresoras de matriz de punto, en esos aos represento una alternativa mas gil para enviar datos que el puerto RS232.

Actualmente la mayora de las tarjetas madre no incluyen el puerto paralelo o el conector DB25, sin embargo usted puede integrar tarjetas PCI con este perifrico.

Puerto Paralelo - Conector DB25


Registro de Estatus Registro de Datos
S0 S1 S2 S3 S4 S5 S6 S7 D7 D6 D5 D4 D3 D2 D1 D0

{
7

13 12

11 10

25 24 23 22 21 20 19 18 17 16 15 14

Para los bits S0,S1,S2, no tenemos acceso, dependiendo la tarjeta madre estos valores pueden ser: 000 111

C7 C6 C5 C4 C3 C2 C1 C0

Registro de Control

IMPORTANTE: Observe que el bit S7 esta negado, debe considerar este detalle al momento de leer el puerto.

Manual 8

Prctica: Lectura y escritura bsica de puerto paralelo


En este ejercicio vamos construir la interfaz electrnica para controlar 8 bits de salida y leer 4 entrada por medio del puerto DB25. Vamos a implementar el siguiente circuito con el Buffer 74L541 para alimentar los leds y reducir la carga de corriente en el puerto, el material necesario es: 1 Protoboard 1 Buffer 74LS541 1 Microswitch 4 resistencias de 1 kohm 8 resistencias de 330 ohm 8 leds comunes de 5mm Cableado

Equipo necesario: 1 fuente de voltaje de 5 volts DC Pinzas, Multmetro.

Diagrama del circuito


Vcc
1

OE

14 15 16 17 18 19 20 21 22 23 24 25

2 3 4 5 6 7 8 9 10 11 12 13

1 2 3 4 5 6 7 8 9 10

20 19 18 17 16 15 14 13 12 11

OE

Leds

74LS541

Importante El Bit S7 esta negado internamente, el dato que ingresemos ser invertido al entrar al registro.

Resistencias 330 ohm

+
5 Volts Resistencias 1 kohm

Fuente

Microswitch

Manual 8

Todo el circuito puede implementarlo en un protoboard.

IMPORTANTE Trabajar con fuentes externas de voltaje y perifricos de la PC presenta un riesgo de quemar componentes de la tarjeta madre, se debe poner en comn la tierra de la PC con la fuente externa y tener mucho cuidado en que no entre voltaje por ese punto a la computadora, esto provocara un dao irreparable.

Recuerde respetar los colores del protoboard: Lnea azul: Tierra Lnea roja: Voltaje

Buffer
Tierra
D7 D0

Manual 8

El puerto paralelo requiere una librera para funcionar: inpout32.dll, si no la tiene en la carpeta C:\Windows\System32\inpout32.dll debe descargarla desde internet. Posiblemente ocupe registrarla, escriba lo siguiente en la ventana de ejecutar: REGSVR32 c:\windows\system32\inpout32.dll Con nuestra interfaz electrnica lista nos vamos a VisualStudio y creamos un nuevo proyecto de WindowsForms.

Ahora arrastramos los siguientes controles:


Formulario Name: frmPuertoParalelo Label Name: lblLecturaPuerto Text: Lectura: Button Name: btnLeerPuerto HSCrollBar Name: SBDato Minimum:0, Maximum: 255 Label Name: lblDatos Text: Escritura:

Escribimos el cdigo para los eventos de cada control mostrados:


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.Runtime.InteropServices; //esta directiva es necesaria namespace frmPuertoParalelo { public partial class frmPuertoParalelo : Form { //Creamos esta clase para importar la DLL y tener acceso a sus comandos public class PortAccess { [DllImport("inpout32.dll", EntryPoint = "Out32")] public static extern void Output(int adress, int value); [DllImport("inpout32.dll", EntryPoint = "Inp32")] public static extern int Input(int address); } public frmPuertoParalelo() { InitializeComponent(); }

Manual 8

private void SBDato_Scroll(object sender, ScrollEventArgs e) { //escribimos un dato de 8 bits (0-255) en el registro de datos //observe que el valor se manda en decimal (int) //el valor 888 es la direccin del registro de datos PortAccess.Output(888, SBDato.Value); lblDatos.Text = "Escritura: " + SBDato.Value.ToString(); } private void btnLeerPuerto_Click(object sender, EventArgs e) { //leemos el registro de status con los bits S4, S5, S6, S7 del diagrama, //el bit S3 se encuentra forzado a tierra sin el microswitch. //los bits S0,S1,S2 no estan disponibles y por lo regular su valor es 0 //el valor 889 es la direccin del registro de Status lblLecturaPuerto.Text = "Lectura: " + PortAccess.Input(889).ToString(); } } }

Antes de conectar el protoboard a la PC probamos las entradas del buffer, observe que por defecto sus salidas estn activadas, por lo tanto esta esperando una tierra en su entrada para apagar el led, tomamos cualquier cable largo y lo conectamos a tierra, el otro extremo lo posicionamos en cada entrada del buffer para comprobar como se apaga cada led. Una vez probado el protoboard verifique que no existan cables sueltos que puedan provocar cortos, use su multmetro para probar continuidad entre el cable DB25 y las entradas del buffer. Antes de prender la fuente que alimenta el protoboard observe el monitor de la PC, si nota un parpadeo al encenderla apague rpidamente la fuente o desconecte el cable, esto puede salvar su tarjeta madre, si no hay cambio todo esta bien conectado, en caso de apagarse el monitor su tarjeta acaba de pasar al otro mundo.

Cuando conectamos mal el puerto y la tarjeta se daa se debe a un corto circuito interno, en estos casos se queman integrados bsicos que pueden ser mas caros de reparar que comprar una tarjeta nueva, tenga cuidado.

Ejecutamos y al mover el scrollbar los leds deben cambiar su estado:

Aparece este mensaje?

Manual 8

El error se debe a la falta inpout32.dll en la carpeta Windows\system32 o en los ejecutables de su proyecto.

En caso de no existir error usted puede ver el valor del scrollbar representado por los leds.

Observe como el dato se actualiza de forma instantnea en los leds, la razn es por utilizar el evento scroll.

Para leer diferentes datos movemos los interruptores del microswitch y damos click en el btnLeerPuerto para actualizar.

Manual 8

Recuerde que el microswitch esta controlando los bits S7,S6,S5 y S4, el bit S3 lo tenemos directo a tierra para evitar datos "flotados", el detalle importante es que tenemos 16 valores posibles para los 4 bits de lectura, sin embargo los datos que leemos no son del 0 al 15 decimal, en realidad son los 4 bits ms significativos del registro de estatus, sumado a esto el bit S7 se encuentra negado. En resumen le recomiendo hacer una tabla de verdad manualmente, usando el microswitch del circuito genere las combinaciones digitales y presione el botn de actualizacin en C#, de esta forma puede tener con certeza los 16 diferentes datos.

Registro de Estatus Registro de Datos


S0 S1 S2 S3 S4 S5 S6 S7 D7 D6 D5 D4 D3 D2 D1 D0

13 12

11 10

25 24 23 22 21 20 19 18 17 16 15 14

Vcc
1

OE

14 15 16 17 18 19 20 21 22 23 24 25

2 3 4 5 6 7 8 9 10 11 12 13

1 2 3 4 5 6 7 8 9 10

20 19 18 17 16 15 14 13 12 11

OE

Leds

74LS541

Resistencias 330 ohm

+
5 Volts Resistencias 1 kohm

Fuente

Microswitch

Como pudo notar el puerto paralelo es muy sencillo de controlar, solo debe tener la librera inpout32.dll en la carpeta c:\windows\system32, a diferencia del puerto serial no requiere abrirse y configurarse.

Manual 8

Introduccin a TCP/IP
TCP/IP Protocolo de Control de Transmisin (TCP) y Protocolo de Internet (IP) La historia de TCP/IP comienza en 1972 en el Departamento de Defensa de Estados Unidos y bajo la infraestructura de ARPANET, su funcin es enlazar computadoras con diferentes sistemas operativos y redes de cualquier tamao, actualmente es el protocolo en que se basa Internet. TCP/IP es obra de Robert Elliot Kahn y Vinton Cerf, ambos recibieron el Premio Turing en 2004. Los lineamientos de diseo para TCP fueron los siguientes: La red se divide en sub-secciones, cada una es capaz de hablar entre si mediante paquetes administrados por un router. Ningn nodo de la red puede crear una ruptura de todo el sistema ni tomar el control. Cada paquete de informacin tiene un nmero de secuencia que le permite llegar al destino. Cuando una computadora manda informacin a otra debe enterarse si realmente fue recibida, esto se logra por medio de otro paquete de confirmacin. Si la informacin se pierde o pasa el tiempo de espera, se retransmite. Cada paquete de datos lleva un checksum que se calcula por el emisor y se comprueba por el receptor, con esto se evitan errores durante el transporte.

Existe un viejo dicho sobre TCP/IP, Es tan bueno que funciona entre dos latas unidas por un cordn.

El concepto de Socket
Los Socket o Zcalos son entidades que nos permiten establecer una conexin entre programas locales o con diferentes computadoras de una red. Otra de manera de entenderlo es como una interfaz de programacin de aplicaciones (API) que permite al sistema operativo administrar los mensajes. En Internet los Socket brindan el mecanismo para la entrega de datos, sus tres caractersticas bsicas son: La IP donde nos vamos a conectar. El puerto que vamos a escuchar. El protocolo de comunicacin (comnmente TCP).

Manual 8

Los lineamientos para que los programas se comuniquen son: Conocer la direccin y puerto, poder localizarse. Tener el mismo protocolo de comunicacin, hablar el mismo idioma. El Socket soluciona este requerimiento con sus propiedades: Se basa en un protocolo. Almacena las direcciones de origen y destino. Tiene los nmeros de puerto y los identificadores de cada programa en el sistema operativo. La arquitectura Cliente-Servidor se basa en Sockets, el cliente es quien inicia la comunicacin y el servidor siempre esta a la espera de las peticiones. Cuando usted va a un restaurante siempre existe un mesero esperando para Servirlo ya que usted es su Cliente, quien hace la peticin es usted, quien responde es el Servidor, es tan sencillo como eso. El proceso iniciado por un Socket nos crea un hilo en la mquina cliente y el servidor, en C# contamos con comandos de conexin y desconexin bastante sencillos.

Prctica: Comunicacin bsica Cliente-Servidor


En este ejercicio vamos a crear un Servidor y Cliente por medio de Sockets, el objetivo de mostrar la forma de comunicarse entre ambas aplicaciones. Ambos programas se ejecutan en la misma computadora, el Servidor es de tipo Consola y el Cliente es formulario de Windows.
x

Servidor
x

Cliente

Comenzamos con el Servidor: Creamos un nuevo proyecto tipo consola.

Lo nombramos: ServidorConsola

Manual 8

using using using using using using using using

System; System.Collections.Generic; System.Linq; System.Text; System.Net.Sockets; System.Net; System.Threading; System.Runtime.InteropServices;

namespace ServidorConsola { class Program { static void Main(string[] args) { inicioPrograma(); } private static void inicioPrograma() { string errorDetectado = ""; //propiedad para detectar errores Int32 puerto = 8888;//puerto para crear el Socket IPAddress direccionIPLocal = IPAddress.Parse("127.0.0.1"); //IP localhost //Creamos un Servidor que va a escuchar la IP en el puerto 8888 TcpListener servidor = new TcpListener(direccionIPLocal, puerto); int contadorPeticiones = 0; //propiedad para guardar el conteo de peticiones TcpClient clientSocket = default(TcpClient);//preparamos el Socket servidor.Start();//inicia el servidor Console.WriteLine(" Inicia el Servidor en LocalHost, puerto 8888, queda a la espera de un Cliente..."); clientSocket = servidor.AcceptTcpClient(); //se queda esperando al cliente //cuando entra el cliente pasa esta lnea Console.WriteLine(" -------------------------o)----------------------------- \n"); Console.WriteLine(" Un Cliente se acaba de conectar!!! "); contadorPeticiones = 0; while (errorDetectado == "") //en caso de excepcin nos salimos del While { //operacin riesgosa, en caso de error salta la excepcin try { NetworkStream networkStream = clientSocket.GetStream(); //Declaramos un arreglo de bytes byte[] bytesFrom = new byte[10025]; networkStream.Read(bytesFrom, 0, (int)clientSocket.ReceiveBufferSize); //creamos una propiedad para recibir el stream de datos en ASCII string dataFromClient = System.Text.Encoding.ASCII.GetString(bytesFrom); dataFromClient = dataFromClient.Substring(0, dataFromClient.IndexOf("$")); Console.WriteLine(" Datos recibidos del Cliente: " + dataFromClient); //Al recibir la informacin mandamos un mensaje al Cliente con las peticiones contadorPeticiones++; string respuestaServidor = "Respuesta del Servidor " + Convert.ToString(contadorPeticiones); Byte[] sendBytes = Encoding.ASCII.GetBytes(respuestaServidor); networkStream.Write(sendBytes, 0, sendBytes.Length); networkStream.Flush(); Console.WriteLine("El Servidor mando... " + respuestaServidor); }

Manual 8

catch (Exception ex) { Console.Clear(); //limpia la consola Console.WriteLine("Alguien cerr el cliente que estaba escuchando!!"); Console.WriteLine("\n\n"); Console.WriteLine("El error es...\n"); Console.WriteLine(ex.ToString()); //cuando se detecta un error capturamos la cadena y nos salimos del While errorDetectado = ex.ToString(); } } //apagamos el Servidor servidor.Stop(); clientSocket.Close(); Console.WriteLine(" \n\n"); Console.WriteLine("---------------------------- "); Console.WriteLine("Servidor apagado "); Console.ReadLine(); } } }

Al ejecutar el Servidor se queda escuchando el puerto 8888, si no existe Cliente mantiene el mismo estado.

El Servidor se program en Consola para mostrar que en esencia son aplicaciones que no requieren un usuario controlando la interfaz, su labor es simplemente servir informacin, sean bases de datos, servicios web, etc.

En el manual 6 configuramos un Servidor OPC de la marca KepWare, si recuerda, desde que se dieron de alta los tags del PLC los datos estuvieron disponibles para el Cliente en C#, un Servidor es simplemente un programa intermediario para seccionar las tareas.

Ahora que tenemos un Servidor escuchando el puerto 8888 vamos a crear un Cliente en Windows con posibilidad de mandar datos por el usuario...

Manual 8

Creamos un nuevo proyecto de Windows Forms con el nombre ClienteTCPIP. Arrastramos los siguientes controles:

Formulario Name: frmCliente Text: Cliente TCP

Label Name: lblMensajes Text: Desconectado BackColor: Red TextAlign: MiddleCenter

ListBox Name: listBoxMensajes

Label Name: lblDatos

HScrollBar Name: hSBarDatos Minimum: 0 Maximum: 100 LargeChange: 1

Manual 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.Net.Sockets; namespace ClienteTCPIP { public partial class frmCliente : Form {//creamos nuestro Socket System.Net.Sockets.TcpClient clienteSocket = new System.Net.Sockets.TcpClient(); public frmCliente() { InitializeComponent(); } //al cargar el formulario intenta conectarse al Servidor private void frmCliente_Load(object sender, EventArgs e) { listBoxMensajes.Items.Add("Conectado!, inicia operacin nuestro Cliente..."); try { clienteSocket.Connect("127.0.0.1", 8888); lblMensajes.Text = "Conectado"; lblMensajes.BackColor = Color.Lime; } catch "); { MessageBox.Show("Hey Amigo! no me enojo si enciendes el Servidor! :/ Application.Exit();//cierra el programa } } //cada vez que cambia el valor del Scroll se manda un dato al Servidor private void hSBarDatos_ValueChanged(object sender, EventArgs e) { try {//preparamos el buffer de salida NetworkStream serverStream = clienteSocket.GetStream(); byte[] outStream = System.Text.Encoding.ASCII.GetBytes (hSBarDatos.Value.ToString() + "$"); serverStream.Write(outStream, 0, outStream.Length); serverStream.Flush(); //Leemos el buffer de entrada con datos del servidor byte[] inStream = new byte[10025]; //preparamos un arreglo de bytes serverStream.Read(inStream, 0, (int)clienteSocket.ReceiveBufferSize); string datosRetorno = System.Text.Encoding.ASCII.GetString(inStream); listBoxMensajes.Items.Add("Datos desde el Servidor: " + datosRetorno); lblDatos.Text = hSBarDatos.Value.ToString(); } catch { //al detectar el error cierra el Socket lblMensajes.BackColor = Color.Red; lblMensajes.Text = "Desconectado"; clienteSocket.Close(); } } } }

Manual 8

Para probar los programas ejecutamos primero el Servidor...

Al ejecutar el Cliente la Consola nos muestra la confirmacin de un Cliente conectado...

El Cliente aparece como conectado: El ListBox despliega otro mensaje de confirmacin. Mueva el ScrollBar y observar como el Servidor recibe los datos y le reenva una respuesta:

Manual 8

En caso de cerrar el Cliente mientras el Servidor esta operando nos detecta el error e imprime lo siguiente:

Si ejecuta el Cliente sin Servidor operando se muestra el siguiente mensaje de error y se cierra el programa.

Finalmente si se cierra el Servidor con el Cliente operando se detecta el error al mover el ScrollBar y se cierra el Socket.

Manual 8

En el ejercicio anterior el Cliente y Servidor se ejecutaron en la misma PC bajo la IP del LocalHost, ahora vamos a crear un Chat entre dos computadoras por el otro protocolo para Sockets: UDP.

Prctica: Identificando la IP de mi PC
Para crear el Chat ocupamos conocer la IP fija de cada mquina en una Intranet, con este ejemplo puede hacerlo desde C#. En un proyecto de Windows Forms arrastre un botn con el nombre: btnIP, en su evento click escriba:

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.Net;//agregar esta directiva para tener acceso a funciones de red namespace IdentificacionIP { public partial class frmIP : Form { public frmIP() { InitializeComponent(); } private void btnIP_Click(object sender, EventArgs e) { string NombreMiPCHost = Dns.GetHostName(); IPHostEntry local = Dns.GetHostEntry(NombreMiPCHost); foreach (IPAddress direccionIP in local.AddressList) { btnIP.Text = "El nombre de mi PC Host es: " + NombreMiPCHost + " ........con la IP: " + direccionIP.ToString(); } } } }

Manual 8

Prctica: Chat entre dos computadoras por UDP


En este ejercicio aplicaremos el protocolo UDP para comunicar dos computadoras en red, con el mismo programa podr probar en las dos mquinas cambiando los puertos y direcciones IP. En el manejo de puertos TCP o UDP siempre estamos a la espera de un dato sorpresa, para solucionarlo aplicamos el concepto de Hilo. Qu es un Hilo? Un Hilo (Thread) es un proceso que se ejecuta en forma paralela a nuestro programa, para el ejemplo creamos un Hilo que siempre esta esperando un dato por los puertos UDP, una de las grandes ventajas de C# es precisamente el manejo de subprocesos. Un Hilo en C# es una funcin que siempre se esta ejecutando sin importar la interaccin del usuario, cuando se cumplen ciertas condiciones el subproceso se activa y nos puede invocar mtodos para manejar la informacin, en resumen, nos permite hacer cdigo multitarea ms eficiente. Para ejecutar los programas debe asignar una IP fija a cada PC: En la ventana de propiedades de TCP/IP asigne las siguientes IP:

192.168.1.4

192.168.1.5

PC1 Switch

PC2

En un nuevo proyecto de Windows Forms vamos a crear una ventana de Chat muy similar al primer ejemplo del manual.

Manual 8

Formulario Name: frmChat Text. Chat por UDP ListBox Name: ListBoxChat

TextBox Name: txtMensaje Label Name: lblNick

Button Name: btnEnviar Enabled: False

TextBox Name: txtNick

El cdigo:
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.Net.Sockets; using System.Net; using System.Threading; //programa para establecer un Chat entre dos computadoras por UDP namespace ChatUDP { public partial class frmChat : Form { delegate void llamadaDelegado(string cadena); //servidor UdpClient servidor = new UdpClient(5001);//puerto de recepcin IPEndPoint ipDestino = new IPEndPoint(new IPAddress(0), 0); //Cliente UdpClient cliente = new UdpClient(5000);//puerto de envo public frmChat() { InitializeComponent(); //inicia el hilo del servidor para estar escuchando el puerto Thread hiloServidor = new Thread(new ThreadStart(esperaDatosDeCliente)); hiloServidor.Start(); }

Manual 8

//este mtodo se invoca cuando se reciben los datos por el Socket UDP private void esperaDatosDeCliente() { while (true) { //al llegar un dato entra aqu byte[] datosCliente = servidor.Receive(ref ipDestino); mensajesListBox(System.Text.Encoding.ASCII.GetString(datosCliente)); servidor.Send(datosCliente,datosCliente.Length, ipDestino); } } //creamos este mtodo intermediario para trabajar con el hilo y el delegado private void mensajesListBox(string msg) { imprimeMensaje(msg); } //recibimos el mensaje del otro mtodo, //actualizamos el listBoxChar con ayuda del delegado private void imprimeMensaje(string m) { if (this.listBoxChat.InvokeRequired) { //Acceder a un control desde otro hilo llamadaDelegado d = new llamadaDelegado(imprimeMensaje); this.Invoke(d, new object[]{m}); } else { //cuando el mtodo fue generado por btnEnviar entra aqu listBoxChat.Items.Add(m); } } //al dar click nos manda el dato por la red a la IP destino private void btnEnviar_Click(object sender, EventArgs e) { mensajesListBox(txtMensaje.Text); string paqueteDatos = txtNick.Text + " dice: " + txtMensaje.Text; //convertimos el string en un arreglo de bytes byte[] datosEnvio = System.Text.Encoding.ASCII.GetBytes(paqueteDatos); //mandamos los datos al puerto donde se encuentra el otro cliente cliente.Send(datosEnvio, datosEnvio.Length, "192.168.1.5", 5678); txtMensaje.Clear(); //limpia el mensaje escrito } } }

Para ejecutar los dos programas requiere hacer cambios en la 2da versin, la forma ms sencilla es copiar la carpeta del proyecto, pegarla en la otra PC y hacer las modificaciones en los puertos.

Manual 8

Para la PC1 con la IP 192.168.1.4 debe configurar de esta forma el cdigo del cliente.
//puerto de recepcin UdpClient servidor = new UdpClient(5001); IPEndPoint ipDestino = new IPEndPoint (new IPAddress(0), 0); //puerto de envo UdpClient cliente = new UdpClient(5000);

Para la PC2 con la IP 192.168.1.5 debe configurar de esta forma el cdigo del cliente.
//puerto de recepcin UdpClient servidor = new UdpClient(5678); IPEndPoint ipDestino = new IPEndPoint (new IPAddress(0), 0); //puerto de envo UdpClient cliente = new UdpClient(5679);

En el evento click del botn de envo debe quedar:


cliente.Send(datosEnvio, datosEnvio.Length, "192.168.1.5", 5678);

En el evento click del botn de envo debe quedar:


cliente.Send(datosEnvio, datosEnvio.Length, "192.168.1.4", 5001);

Al ejecutar en ambas PC's obtenemos un sencillo Chat por red.

Das könnte Ihnen auch gefallen