Foros del Web » Programación para mayores de 30 ;) » .NET »

Crear puerto serie.

Estas en el tema de Crear puerto serie. en el foro de .NET en Foros del Web. Hola: Como curiosidad, estoy usando WPF C# 2013. Quiero usar el puerto serie RS232, en AWF tiene el componente serialPort1, mientras WPF no lo incluye. ...
  #1 (permalink)  
Antiguo 25/02/2015, 10:35
 
Fecha de Ingreso: mayo-2007
Ubicación: PIC-16F84A
Mensajes: 724
Antigüedad: 15 años, 4 meses
Puntos: 8
Crear puerto serie.

Hola:



Como curiosidad, estoy usando WPF C# 2013. Quiero usar el puerto serie RS232, en AWF tiene el componente serialPort1, mientras WPF no lo incluye. Quiero enviar tramas de bytes pulsando un botón.

En Visual C# 2013 AWF su código es así:

Código:
private void button_t_Click(object sender, EventArgs e)
{
    byte[] mBuffer = new byte[5];
    mBuffer[0] = 0x74;
    mBuffer[1] = 0x75;
    mBuffer[2] = 0x89;
    mBuffer[3] = 0x20;
    mBuffer[4] = 0x6C;
    serialPort1.Write(mBuffer, 0, mBuffer.Length);
}
También en forma de cadena se hace así:

Código:
private void button_b_Click(object sender, EventArgs e)
{
    byte[] mBuffer = Encoding.ASCII.GetBytes("Hello World");
    serialPort1.Write(mBuffer, 0, mBuffer.Length);
}
Abrir puerto y cerrarlo.

Código:
serialPort1.Open();

serialPort1.Close();
using System.IO.Ports;

Sabiendo todo lo de arriba, cuya información aparece aquí.

¿Es posible hacer una aplicación con WPF?

Algún código de ejemplo?

Un cordial saludos.
__________________
Meta Shell, VERSIÓN 1.2.2
Descargar
  #2 (permalink)  
Antiguo 27/02/2015, 19:23
 
Fecha de Ingreso: junio-2003
Ubicación: Asturias
Mensajes: 2.429
Antigüedad: 19 años, 3 meses
Puntos: 7
Respuesta: Crear puerto serie.

Si, se puede. Funciona en WinForms ?? Pues en WPF también.

Es exactamente lo mismo..
__________________
Charlie.
  #3 (permalink)  
Antiguo 27/02/2015, 21:10
 
Fecha de Ingreso: mayo-2007
Ubicación: PIC-16F84A
Mensajes: 724
Antigüedad: 15 años, 4 meses
Puntos: 8
Respuesta: Crear puerto serie.

Buenas campeón:

He comprobado que no es exactamente lo mismo.
Código:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;

using System.IO.Ports; // No olvidar.
using System.Threading;

namespace WpfApplication1
{
    /// <summary>
    /// Lógica de interacción para MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        // Utilizaremos un string como buffer de recepción.
        string Recibidos;

        SerialPort serialPort1 = new SerialPort();

        public MainWindow()
        {
            InitializeComponent();

            serialPort1.BaudRate = 115200;
            serialPort1.PortName = "COM4";
            serialPort1.Parity = Parity.None;
            serialPort1.DataBits = 8;
            serialPort1.StopBits = StopBits.Two;

            // Abrir puerto mientras se ejecute la aplicación.
            if (!serialPort1.IsOpen)
            {
                try
                {
                    serialPort1.Open();
                }
                catch (System.Exception ex)
                {
                    MessageBox.Show(ex.ToString());
                }

            }

            // Ejecutar la función REcepción por disparo del Evento ¡DataReived'.
            //serialPort1.DataReceived += new SerialDataReceivedEventHandler(Recepcion);
        }

        private void Recepcion(object sender, SerialDataReceivedEventHandler e)
        {
            // Acumular los caracteres recibidos a nuestro 'buffer' (string).
            Recibidos += serialPort1.ReadExisting();

            // Invocar o llamar al proceso de tramas.
            //this.Invoke(new EventHandler(Actualizar));
             
        }


        // Procesar los datos recibidos en el buffer y estraer tramas completas.
        private void Actualizar(object s, EventArgs e)
        {
            // Asignar el valor de la trama al RichTextBox.
            RichTextBox_Mensajes.DataContext = Recibidos;
        }

        private void Button_Led_8_ON_Click(object sender, RoutedEventArgs e)
        {
            byte[] mBuffer = Encoding.ASCII.GetBytes("Led_8_ON");
            serialPort1.Write(mBuffer, 0, mBuffer.Length);
        }

        private void Button_Led_8_OFF_Click(object sender, RoutedEventArgs e)
        {
            byte[] mBuffer = Encoding.ASCII.GetBytes("Led_8_OFF");
            serialPort1.Write(mBuffer, 0, mBuffer.Length);
            RichTextBox_Mensajes.DataContext = "Hola";
        }

    }
}
Error:
Error 1 Ninguna sobrecarga correspondiente a 'Recepcion' coincide con el 'System.IO.Ports.SerialDataReceivedEventHandler' delegado C:\Users\Meta\Documents\Visual Studio 2013\Projects\WpfApplication1\WpfApplication1\Main Window.xaml.cs 58 41 WpfApplication1

Error 2:
Error 2 'WpfApplication1.MainWindow' no contiene una definición de 'Invoke' ni se encontró ningún método de extensión 'Invoke' que acepte un primer argumento de tipo 'WpfApplication1.MainWindow' (¿falta una directiva using o una referencia de ensamblado?) C:\Users\Meta\Documents\Visual Studio 2013\Projects\WpfApplication1\WpfApplication1\Main Window.xaml.cs 67 18 WpfApplication1

Ojalá fuera exactamente lo mismo.

si pongo como dos comentarios a estos errores, se puede encener y apagar el Led, eso si, no puedo leer mensaje sy publicarla en el richTextBox.

Saludos.
__________________
Meta Shell, VERSIÓN 1.2.2
Descargar
  #4 (permalink)  
Antiguo 27/02/2015, 21:24
(Desactivado)
 
Fecha de Ingreso: enero-2015
Mensajes: 393
Antigüedad: 7 años, 8 meses
Puntos: 52
Respuesta: Crear puerto serie.

Tenes un error en el codigo en la linea:

Código C#:
Ver original
  1. private void Recepcion(object sender, SerialDataReceivedEventHandler e)

En primer lugar, el event handler que declara la clase System.IO.Port.SerialPort para el evento DataRecieved tiene la siguiente firma:

Código C#:
Ver original
  1. public delegate void SerialDataReceivedEventHandler(object sender, SerialDataReceivedEventArgs e);

Con lo cual el segundo argumento "e" es de tipo SerialDataReceivedEventArgs y no SerialDataReceivedEventHandler como lo estas declarando en tu codigo. Tenes que cambiar la firma del metodo Recepcion por lo siguiente:

Código C#:
Ver original
  1. private void Recepcion(object sender, SerialDataReceivedEventArgs e)

En segundo lugar, C# infiere automaticamente los delegados al usar +=, con lo cual utilizar new y el tipo de delegado es absolutamente innecesario y redundante. Te sugiero que cambies esto:

Código C#:
Ver original
  1. serialPort1.DataReceived += new SerialDataReceivedEventHandler(Recepcion);

Por esto:

Código C#:
Ver original
  1. serialPort1.DataReceived += Recepcion;

----------------------------------------

Adicionalmente y como te mencioné en un post anterior, el RichTextBox de WPF no es simplemente un "control para mostrar texto", es un editor de FlowDocuments, si lo que quieres es mostrar texto en varios colores y formatos, sin que el usuario pueda editarlo (read only), con un simple TextBlock te alcanza.

Por ultimo, estas mezclando el codigo de presentation (UI) con el codigo de IO (SerialPort) que no tienen nada que ver. Te sugiero (nuevamente) que investigues acerca de DataBinding y como hacer las cosas de manera correcta en WPF y en general.
  #5 (permalink)  
Antiguo 27/02/2015, 22:03
 
Fecha de Ingreso: mayo-2007
Ubicación: PIC-16F84A
Mensajes: 724
Antigüedad: 15 años, 4 meses
Puntos: 8
Respuesta: Crear puerto serie.

Hola:

Gracias, aún así me da un error en el this.Invoke.

Código:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;

using System.IO.Ports; // No olvidar.
using System.Threading;

namespace WpfApplication1
{
    /// <summary>
    /// Lógica de interacción para MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        // Utilizaremos un string como buffer de recepción.
        string Recibidos;

        SerialPort serialPort1 = new SerialPort();

        public MainWindow()
        {
            InitializeComponent();

            serialPort1.BaudRate = 115200;
            serialPort1.PortName = "COM4";
            serialPort1.Parity = Parity.None;
            serialPort1.DataBits = 8;
            serialPort1.StopBits = StopBits.Two;

            // Abrir puerto mientras se ejecute la aplicación.
            if (!serialPort1.IsOpen)
            {
                try
                {
                    serialPort1.Open();
                }
                catch (System.Exception ex)
                {
                    MessageBox.Show(ex.ToString());
                }

            }

            // Ejecutar la función REcepción por disparo del Evento ¡DataReived'.
            serialPort1.DataReceived += Recepcion;
        }

        private void Recepcion(object sender, SerialDataReceivedEventArgs e)
        {
            // Acumular los caracteres recibidos a nuestro 'buffer' (string).
            Recibidos += serialPort1.ReadExisting();

            // Invocar o llamar al proceso de tramas.
            this.Invoke(new EventHandler(Actualizar));
             
        }

        // Procesar los datos recibidos en el buffer y estraer tramas completas.
        private void Actualizar(object s, EventArgs e)
        {
            // Asignar el valor de la trama al RichTextBox.
            RichTextBox_Mensajes.DataContext = Recibidos;

            var doc = new System.Windows.Documents.FlowDocument();
            doc.Blocks.Add(new Paragraph(new Run(Recibidos)));
            RichTextBox_Mensajes.Document = doc;
        }

        private void Button_Led_8_ON_Click(object sender, RoutedEventArgs e)
        {
            byte[] mBuffer = Encoding.ASCII.GetBytes("Led_8_ON");
            serialPort1.Write(mBuffer, 0, mBuffer.Length);
        }

        private void Button_Led_8_OFF_Click(object sender, RoutedEventArgs e)
        {
            byte[] mBuffer = Encoding.ASCII.GetBytes("Led_8_OFF");
            serialPort1.Write(mBuffer, 0, mBuffer.Length);
        }

    }
}
Error 1 'WpfApplication1.MainWindow' no contiene una definición de 'Invoke' ni se encontró ningún método de extensión 'Invoke' que acepte un primer argumento de tipo 'WpfApplication1.MainWindow' (¿falta una directiva using o una referencia de ensamblado?) C:\Users\Meta\Documents\Visual Studio 2013\Projects\WpfApplication1\WpfApplication1\Main Window.xaml.cs 67 18 WpfApplication1


Saludos.
__________________
Meta Shell, VERSIÓN 1.2.2
Descargar
  #6 (permalink)  
Antiguo 27/02/2015, 22:17
(Desactivado)
 
Fecha de Ingreso: enero-2015
Mensajes: 393
Antigüedad: 7 años, 8 meses
Puntos: 52
Respuesta: Crear puerto serie.

Los Elementos de UI (System.Windows.UIElement) de WPF no tienen ningun metodo Invoke() porque:

- invocar rutinas y administrar el threading no es una responsabilidad de un UI element. Esto es un error fundamental de winforms que te "enseña" a poner cualquier cosa en cualquier lado en lugar de tener un orden en lo que estas haciendo.

- WPF tiene un Threading Model (https://msdn.microsoft.com/en-us/library/ms741870(v=vs.110).aspx) que es orquestado y controlado por un componente llamado Dispatcher (https://msdn.microsoft.com/en-us/library/system.windows.threading.dispatcher(v=vs.110).aspx ). Este componente se encarga de coordinar las tareas de threading de toda la UI.
- Los UIElements de WPF a su vez son DispatcherObjects (https://msdn.microsoft.com/en-us/library/system.windows.threading.dispatcherobject(v=vs.110 ).aspx). Esto significa que todos los UIElements (Application, controles, ventanas, paneles, etc, etc) estan asociados a un Dispatcher, con lo cual, para contestar tu pregunta, la forma de llamar una invocacion desde un hilo de ejecucion ajeno a la UI, hacia la UI en WPF es usar el dispatcher del elemento en cuestion:

Código C#:
Ver original
  1. this.Dispatcher.Invoke(new EventHandler(Actualizar));

--------------------------

Por cierto, me interesó tu projecto Meta Shell, pero no lo pude descargar, esta el codigo fuente en algun lado? me interesa contribuir al proyecto ;)
  #7 (permalink)  
Antiguo 27/02/2015, 22:21
 
Fecha de Ingreso: mayo-2007
Ubicación: PIC-16F84A
Mensajes: 724
Antigüedad: 15 años, 4 meses
Puntos: 8
Respuesta: Crear puerto serie.

Ahora me compila bien. Si pulso un botón para enviar tramas de bytes, me sale este cuadro y el programa no funciona.

Excepción no controlada del tipo 'System.Reflection.TargetParameterCountException' en mscorlib.dll

Información adicional: El recuento de parámetros no coincide.


Saludos.
__________________
Meta Shell, VERSIÓN 1.2.2
Descargar
  #8 (permalink)  
Antiguo 27/02/2015, 22:26
(Desactivado)
 
Fecha de Ingreso: enero-2015
Mensajes: 393
Antigüedad: 7 años, 8 meses
Puntos: 52
Respuesta: Crear puerto serie.

No habia mirado la firma de tu metodo Actualizar:

Código C#:
Ver original
  1. private void Actualizar(object s, EventArgs e)

Ves lo que te digo cuando digo que winforms es estupido? para que quiero "object s" y "EventArgs e" si estoy llamando a un metodo sin parametros.

WPF te ahorra la estupidez:

Código C#:
Ver original
  1. private void Actualizar()

Y te simplifica el Invoke:

Código C#:
Ver original
  1. this.Dispatcher.Invoke(Actualizar);
  #9 (permalink)  
Antiguo 27/02/2015, 22:33
 
Fecha de Ingreso: mayo-2007
Ubicación: PIC-16F84A
Mensajes: 724
Antigüedad: 15 años, 4 meses
Puntos: 8
Respuesta: Crear puerto serie.

Hola:

Por fin me funciona.
Código:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;

using System.IO.Ports; // No olvidar.
using System.Threading;

namespace WpfApplication1
{
    /// <summary>
    /// Lógica de interacción para MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        // Utilizaremos un string como buffer de recepción.
        string Recibidos;

        SerialPort serialPort1 = new SerialPort();

        public MainWindow()
        {
            InitializeComponent();

            serialPort1.BaudRate = 115200;
            serialPort1.PortName = "COM4";
            serialPort1.Parity = Parity.None;
            serialPort1.DataBits = 8;
            serialPort1.StopBits = StopBits.Two;

            // Abrir puerto mientras se ejecute la aplicación.
            if (!serialPort1.IsOpen)
            {
                try
                {
                    serialPort1.Open();
                }
                catch (System.Exception ex)
                {
                    MessageBox.Show(ex.ToString());
                }

            }

            // Ejecutar la función REcepción por disparo del Evento ¡DataReived'.
            serialPort1.DataReceived += Recepcion;
        }

        private void Recepcion(object sender, SerialDataReceivedEventArgs e)
        {
            // Acumular los caracteres recibidos a nuestro 'buffer' (string).
            Recibidos += serialPort1.ReadExisting();

            // Invocar o llamar al proceso de tramas.
            this.Dispatcher.Invoke(Actualizar);
            
             
        }

        private void Invoke(EventHandler eventHandler)
        {
            //throw new NotImplementedException();
        }

        // Procesar los datos recibidos en el buffer y estraer tramas completas.
        private void Actualizar()
        {
            // Asignar el valor de la trama al RichTextBox.
            RichTextBox_Mensajes.DataContext = Recibidos;

            var doc = new System.Windows.Documents.FlowDocument();
            doc.Blocks.Add(new Paragraph(new Run(Recibidos)));
            RichTextBox_Mensajes.Document = doc;
        }

        private void Button_Led_8_ON_Click(object sender, RoutedEventArgs e)
        {
            byte[] mBuffer = Encoding.ASCII.GetBytes("Led_8_ON");
            serialPort1.Write(mBuffer, 0, mBuffer.Length);
        }

        private void Button_Led_8_OFF_Click(object sender, RoutedEventArgs e)
        {
            byte[] mBuffer = Encoding.ASCII.GetBytes("Led_8_OFF");
            serialPort1.Write(mBuffer, 0, mBuffer.Length);
        }

    }
}
Hay algo que se me escapa.


No se ve la barra de al lado para mover los mensajes del richTextBox.

Aquí en el Windows Form si se muetsra automaticamente.


Este es su código.
Código:
        // Procesar los datos recibidos en el bufer y extraer tramas completas.
        private void Actualizar(object sender, EventArgs e)
        {
            // Asignar el valor de la trama al richTextBox.
            richTextBox_Mensajes.Text = Recibidos;

            // Selecciona la posición final para leer los mensajes entrantes.
            richTextBox_Mensajes.SelectionStart = richTextBox_Mensajes.Text.Length;

            // Mantiene el scroll en la entrada de cada mensaje.
            richTextBox_Mensajes.ScrollToCaret();
        }
Si, lo se, con basura incluida.
__________________
Meta Shell, VERSIÓN 1.2.2
Descargar

Etiquetas: puerto, visual
Atención: Estás leyendo un tema que no tiene actividad desde hace más de 6 MESES, te recomendamos abrir un Nuevo tema en lugar de responder al actual.
Respuesta




La zona horaria es GMT -6. Ahora son las 03:07.