专业编程基础技术教程

网站首页 > 基础教程 正文

C#程序与单片机通信时,如何自动初始化串口(1)?

ccvgpt 2024-10-12 14:10:30 基础教程 10 ℃

PC端的串口程序,首先要发现串口。而与下位机的连接方式有两种,一种是普通USART的串口,第二种是USB转成虚拟串口。下面介绍一下如何找到正确的串口。

1.发现USART串口

由于普通串口没有标识可以查询,因为必须要把所有的串口枚举出来,然后通过下位机的配合,一个一个的试,没有别的好方法。C#里有SerialPort类,其GetPortNames是静态函数,可以直接使用。列出所有串口端口的代码如下:

C#程序与单片机通信时,如何自动初始化串口(1)?

//列出所有串口
foreach (string n in SerialPort.GetPortNames())
{
 comboBox1.Items.Add(n);
}
//显示出第一个串口
if(comboBox1.Items.Count)
{
 if(comboBox1.Items.Count>0)
 {
 comboBox1.Text = comboBox1.Items[0].ToString();
 }
}

然后对罗列的串口一个个试,看哪个是正确的。

2.USB串口

下面主要讲讲当下位机用USB虚拟串口与PC时,PC端如何自动识别下位机的串口。此时,虚拟串口是一个USB设备,其设备代码Vender ID和Product ID是可以通过电脑的设备管理器里显示出来,如果这个值在本电脑是唯一的话,我们就可以据此识别。

2.1 注册程序

为了能够让程序发现USB活动,如插、拔动作。我们必须将上位机程序注册到系统监视列表中,如下

//监视句柄
private static IntPtr notificationHandle;
//监视信息定义,Windows定义的结构
[StructLayout(LayoutKind.Sequential)]
private struct DevBroadcastDeviceinterface
{
 internal int Size;
 internal int DeviceType;
 internal int Reserved;
 internal Guid ClassGuid;
 internal short Name;
}

定义自己的设备注册函数,让PC程序能接收到USB事件。

//输入是PC程序的句柄
//调用此函数后,程序就能检测到USB活动
public static void RegisterUsbDeviceNotification(IntPtr windowHandle)
{ 
 //只监视我们关心的信息
 DevBroadcastDeviceinterface dbi = new DevBroadcastDeviceinterface
 {
 Size = Marshal.SizeOf(typeof(DevBroadcastDeviceinterface)),
 DeviceType = 5,
 Reserved = 0,
 //USB设备
 ClassGuid = new Guid("A5DCBF10-6530-11D2-901F-00C04FB951ED"),
 Name = 0
 };
 IntPtr Filter = Marshal.AllocHGlobal(dbi.Size);
 Marshal.StructureToPtr(dbi, Filter, true);
 //注册本程序,返回监视句柄
 //此句柄在注销时用
 notificationHandle = RegisterDeviceNotification(windowHandle, Filter, 0);
 Marshal.FreeHGlobal(Filter);
}
//真正的注册函数由系统提供
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
private static extern IntPtr RegisterDeviceNotification(IntPtr recipient, IntPtr notificationFilter, int flags);

2.2 监视事件

注册程序之后,本程序就是接收到USB事件了。接下来要对相应的windows事件进行处理。在C#里,要覆盖原有的WndProc函数。可以把这部分代码放在主窗体程序中,代码如下

//处理接收到的USB事件
protected override void WndProc(ref Message m)
{
 //运行默认的代码
 base.WndProc(ref m);
 //自己增加的代码
 if (m.Msg == HardwareEvent.WM_DEVICECHANGE)
 {
 switch (m.WParam.ToInt32())
 {
 //拔USB
 case 0x8004:
 //在此关闭串口
 Usb_DeviceRemoved();
 break;
 //USB插入
 case 0x8000:
 //在此打开串口
 Usb_DeviceAdded();
 break;
 }
}

2.3 事件识别

长度限制,下次再发。

谢谢关注。如果你是第一次阅读,请参阅此话题的前二篇短文。

想进一步了解此话题,请继续阅读以下文章:

上两篇,

C#程序与单片机通信时,如何实现结构体的字节对齐

C#程序与单片机通信时,如何实现结构体转换为字节流

后一篇

C#程序与单片机通信时,如何自动初始化串口(2)?

Tags:

最近发表
标签列表