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();
}
}
}
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
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,
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
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,
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.
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»)
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
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,