Cambiar los ‘SerialPort Settings’ en tiempo de ejecución.

Atendiendo a una consulta de los foros de MSDN, me complace compartir con vosotros una solución para asignar los ajustes de apertura del puerto serie al vuelo.



Entendiendo que en algunas situaciones, puede ser ventajoso poder cambiar la velocidad, paridad, bits… etc, ‘On Line’. Aunque para la mayoría de comunicaciones con dispositivos dichos parámetros son ajustados en tiempo de puesta en marcha y no acostumbran a variar en el transcurso del tiempo.


Esperando os sea útil… Saludos,
Pep Lluis,


PD. Si queréis podéis descargaros la solución de ejemplo en ‘attachments’.


using System;


using System.IO.Ports;


using System.Windows.Forms;


 


namespace SerialPortSettings


{


    public partial class Form1 : Form


    {


        public Form1()


        {


            InitializeComponent();


        }


 


        private void Form1_Load(object sender, EventArgs e)


        {


            // Asignar las Velocidades seleccionables al Combo


            object[] Velocidades = { 19200, 9600, 4800, 2400, 1200 };


            this.comboBox_bits_por_segundo.Items.AddRange(Velocidades);


           


            // Asignar Paridades Seleccionables desde la enumeracion


            foreach (string s in Enum.GetNames(typeof(Parity)))


            {


                this.comboBox_paridad.Items.Add(s);


            }


           


            // Seleccionar los items por defecto


            this.comboBox_bits_por_segundo.SelectedIndex = 0;


            this.comboBox_paridad.SelectedIndex = 0;


            // Abrir el puerto serie con los items por defecto


            SeleccionCambiada(sender,e);


            // Asignar la funcion a ejecutar por disparo de evento al cambio de indice en el combobox


            this.comboBox_bits_por_segundo.SelectedIndexChanged += new System.EventHandler(this.SeleccionCambiada);


            this.comboBox_paridad.SelectedIndexChanged += new System.EventHandler(this.SeleccionCambiada);


        }


 


       


        private void SeleccionCambiada(object sender, EventArgs e)


        {


            // Deberemos añadir un control de excepciones si queremos capturar posibles errores


 


            // Para reasignar valores… primero cerrar el puerto


            this.serialPort1.Close();


            // Asignar los nuevos Settings


            this.serialPort1.BaudRate = Convert.ToInt16(comboBox_bits_por_segundo.Text);


            this.serialPort1.Parity = (Parity)Enum.Parse(typeof(Parity), comboBox_paridad.Text);


 


            this.serialPort1.Open();


            // Ver las asignaciones actuales.


            this.Velocidad.Text = this.serialPort1.BaudRate.ToString();


            this.Paridad.Text = this.serialPort1.Parity.ToString();


        }


 


    }


}


 

8 thoughts on “Cambiar los ‘SerialPort Settings’ en tiempo de ejecución.”

  1. Buenas tardes pepluis gracias por el gran aporte pero brindas sobre todo gratis por tu blog me a servido de mucho en mi trabajo. Sin embargo, tengo una pregunta; cuando se recibe la data de un puerto virtual la configuracion y el codigo debe cambiar?porque tengo un programa que en un puerto fisico recibe la data normal, pero cuando le pongo para que reciba de un puerto virtual no me recibe nada.O tambien si habria alguna manera de compartir el flujo de datos de un puerto. Gracias de antemano.

    compartir el flujo de datos de un puerto COM .

    p.d: Todo esta hecho en vb 2005

  2. Hola Leolaz,
    Gracias por tus amables palabras.

    En teoria un puerto serie “Virtual” deberia comportarse identicamente igual que uno fisico. Aunque se me hace dificil entender que puede estar ocurriendo por desconocer los detalles. Creo que en ese sentido que el fabricante de la aplicacion “Virtual” deberia darte instrucciones precisas de su funcionamiento y/o compatibilidades.

    Lamento no tener mayor conocimiento en este campo.
    Saludos,
    Pep Lluis,

  3. Gracias por tu ayuda, mira en unos ejemplos que tiene microsoft sobre puerto hay un modo diferente de acceder a ellos, ya logre capturar la informacion, pero solo al levantar la aplicacion por mas que le pongo en el timer para que lo haga cada segundo no pasa nada sigue mostrando la misma información . Si fueras tan amable de corregirme aqui te dejo los metodos.

    C:

    Load
    =========================
    CommPort.Open(6, 9600, 8, RS232.DataParity.Parity_None, _
    RS232.DataStopBit.StopBit_1, 4096)
    Me.Timer1.Enabled = True
    Me.Timer1.Interval = 1000

    TimerTick
    ===============================
    While (CommPort.Read(1) <> -1)

    WriteMessage(Chr(CommPort.InputStream(0)), False)
    End While

    WriteMessage
    ===============================
    Me.TextBox1.Text += message
    If linefeed Then
    Me.TextBox1.Text += vbCrLf
    End If

  4. Disculpa Leolaz,
    Deberias especificarme la version de VB que estas utilizando y el control… se trata del antiguo MSCOMM32.OCX?

    Puedes tambien contactar conmigo a traves de la opcion [Contact] al inicio de esta pagina.

    Espero tus noticias,
    Pep Lluis,

  5. Hola. Me gustaría saber como debe hacerse en .NET el cambio de paridad mientras se está enviando. La intención es enviar una trama en modo multiprocesador (con los 2 bytes de dirección con la paridad en marca y el resto paridad espacio) para comunicar con un microcontrolador que utiliza este tipo de comunicación. Toda la trama debe ir seguida sin pausas ni cortes. En Visual 6.0 y con mscomm lo que hacía y me funcionaba era:
    s.Format(_T(“%d,%C,%d,%d”), 9600, (TCHAR)’M’, 8, 1);// Pongo el bit multiprocesador. Cambio a uso de MARCA
    m_COM.SetSettings(s);

    memcpy(pchBuffer, (LPSTR)buffer.GetData(), 2);

    MultiByteToWideChar(CP_ACP, 0, pchBuffer, 2, pchData, 2);
    var.vt = VT_BSTR;
    var.bstrVal = ::SysAllocStringLen(pchData, 2);
    // Send data to comm port.
    // bytes_sended=2; // apunto los datos que voy a dejar sin procesar

    m_COM.SetOutput(var);
    SysFreeString(var.bstrVal);

    // char a1 = buffer.GetAt(0);
    // char a2 = buffer.GetAt(1);
    buffer.RemoveAt(0,2);

    Sleep(1); // Retardo necesario para que se envíen los 2 primeros bits. Si se pone sleep más grande ya no funciona.
    s.Format(_T(“%d,%C,%d,%d”), 9600, (TCHAR)’S’, 8, 1);// Pongo el bit multiprocesador. Cambio a uso de ESPACIO
    m_COM.SetSettings(s);

    memcpy(pchBuffer, (LPSTR)buffer.GetData(), nBytes-2);
    MultiByteToWideChar(CP_ACP, 0, pchBuffer, nBytes-2, pchData, nBytes-2);

    //buffer.InsertAt(0,a2);
    //buffer.InsertAt(0,a1);
    var.vt = VT_BSTR;
    var.bstrVal = ::SysAllocStringLen(pchData, nBytes-2);
    // Send data to comm port.

    El sleep lo que hace es darle tiempo a salir a los 2 primeros bytes con marca. Y luego se cambia a espacio. El problema es que los dispositivos a los que les envío la trama deben recibirla seguida, sin cortes entre los 2 bytes de dirección y el resto de la trama por eso si se pone el sleep más largo no funciona. La opción de cerrar el puerto, que yo no hago, y que tu planteas en el ejemplo en .NET, no sé si daría algún problema con los datos que se están enviando mientras tanto y no sé si sería demasiado lento el cierre y apertura de nuevo del COM. Tengo que probarlo. Otra cosa que he visto es que el mismo código en esta función para 6.0 compilado en VS2005 no funciona. Seguramente porque el código final generado no mantiene los mismo tiempos que tuve que ajustar para 6.0.

  6. Hola Luis,
    Quizas no funcione… pero has intentado algo similar a esto :

    Dim Direccion(1) As Byte
    Direccion(0) = &H30
    Direccion(1) = &H32
    PuertoSerie.Parity = IO.Ports.Parity.Mark
    PuertoSerie.Write(Direccion, 0, 2)
    PuertoSerie.Parity = IO.Ports.Parity.None
    PuertoSerie.Write(“El Resto de Trama”)

  7. No me habilita un temporizador dentro del evento DataReceived pero tampoco me tira error:

    Private Sub SerialPort_DataReceived(ByVal sender As Object, ByVal e As System.IO.Ports.SerialDataReceivedEventArgs) Handles SerialPort.DataReceived

    leido = True
    Me.Timer1.Enabled = True

    End Sub

    Private Sub Timer1_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Timer1.Tick
    MsgBox(“Pasó por acá”)
    End Sub

  8. Hola Matias,
    Prueba este codigo…
    Imports System.IO.Ports
    Public Class Form1
    WithEvents PuertoSerie As New SerialPort(“COM2″)
    Dim MiTemporizador As New System.Timers.Timer

    Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
    MiTemporizador.Interval = 1000
    MiTemporizador.Enabled = False
    AddHandler MiTemporizador.Elapsed, AddressOf Temporizar
    PuertoSerie.Open()
    End Sub

    Sub recepcion() Handles PuertoSerie.DataReceived
    MiTemporizador.Enabled = True
    Dim Recibidos As String = PuertoSerie.ReadExisting
    End Sub

    Sub Temporizar()
    MiTemporizador.Enabled = False
    MessageBox.Show(“Hace Un segundo que recibi datos”)
    End Sub

    Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
    PuertoSerie.Write(“Hola”)
    End Sub
    End Class

    Saludos,
    Pep Lluis,

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>