当前位置:文档之家› C#并口及串口通信

C#并口及串口通信

C#并口及串口通信
C#并口及串口通信

串口通信中接收数据时延迟处理与缓存处理的解决方案(C#)

利用串口进行通信,当发送方(A)将数据写入串口后,通过无线或有线方式将数据传送给接收方(B),B通过调用串口读方法comm.read(参数)即可将数据读出。原理十分简单,但最近在利用串口处理SM-42无线传输时,数据总是一段一段的传到B,并不能在comm_DataReceived方法中单纯使用read方法将数据接收完全。我知道用缓存机制,但由于经验少(正在实习),到网上找了找大牛们的方法,并结合自己的理解,发现有两种方法可以处理。

方法一:comm_DataReceived(Comm控件的数据接收方法,当有数据来临时会触发)会创建一个线程(悲哀,因为之前不知道它另辟线程,所以自己编写了一个线程处理函数),因此当串口在等待数据时,不影响主窗体或主线程的操作。所以当数据到来时,可以通过Thread.Sleep(100)让接收函数休息100毫秒,这100毫秒做什么用呢?就是让所有的数据都到达B时再读取,这样就逃避了分批到达的问题。很明显,这是在糊弄。因为万一100毫秒都不够呢?所以,方法二更合适。

代码

1private void comm_DataReceived(object sender, EventArgs e)

2{

3 Thread.Sleep(100); //等待100毫秒

4int nReviceBytesNum =comm.BytesToRead; ///收到的字节数。

5byte[] ReadBuf = new byte[nReviceBytesNum]; ///定义接收字节数组

6 comm.Read(ReadBuf, 0, nReviceBytesNum); ///接收数据

7}

方法二:使用缓存机制完成。首先通过定义一个成员变量List buffer = new List(4096);用来存放所有的数据,在接收函数里,通过buffer.AddRange()方法不断地将接收到的数据加入到buffer中,并同时对buffer中的数据进行检验,如果达到一定的长度并且校验结果正确(校验方法在发送方和接收方一致),再进行处理。具体代码如下:

代码

private List buffer = new List(4096);

private void sp_DataReceived(object sender, EventArgs e) //sp是串口控件

{

int n = sp.BytesToRead;

byte[] buf = new byte[n];

sp.Read(buf, 0, n);

//1.缓存数据

buffer.AddRange(buf);

//2.完整性判断

while (buffer.Count >= 4)

//至少包含帧头(2字节)、长度(1字节)、校验位(1字节);根据设计不同而不同

{

//2.1 查找数据头

if (buffer[0] == 0x01) //传输数据有帧头,用于判断

{

int len = buffer[2];

if (buffer.Count < len + 4) //数据区尚未接收完整

{

break;

byte jiaoyan; //开始校验

jiaoyan = this.JY(ReceiveBytes);

if (jiaoyan != ReceiveBytes[len+3])

//校验失败,最后一个字节是校验位

{

buffer.RemoveRange(0, len + 4);

MessageBox.Show("数据包不正确!");

continue;

}

buffer.RemoveRange(0, len + 4);

/////执行其他代码,对数据进行处理。

}

else//帧头不正确时,记得清除

{

buffer.RemoveAt(0);

}

}

}

在方法二中,有一句“执行其他代码,对数据进行处理”,如果这些代码涉及到主线程的控件比如Label,TextBox,就要涉及跨线程访问控件的问题。(串口的DataReceived方法会创建新线程,这在本文开始时已经说明)对于跨线程访问及更改控件属性,也有两种方法,下一篇文章再介绍。

跨线程访问及修改控件属性的解决方案

在上一篇文章中,写了一些串口通信时数据接收的内容,其中有一行代码有个提问:在数据接收线程中,当接收到数据并且校验正确后,我怎么显示这些数据到窗体中呢?要显示数据,必须要访问主线程(A)的各种控件,而数据接收是另一个线程(B)。有两种方案可以解决这个问题,和上文一样,也是第二个较好。

方法一:取消跨线程操作检查

当线程B在访问线程A创建的控件时,线程A会对控件的线程锁进行检验,当多个线程同时对控件进行写操作时,必然产生冲突,因此此时的程序会非常不稳定,经常突然就退出,Debug显示原因是跨线程操作控件了。既然如此,那就让线程A不去检验其他线程了,在Form_Load函数里加一句:

System.Windows.Forms.Control.CheckForIllegalCrossThreadCalls = false;就万事大吉了。很显然,这种方法不推荐使用。

方法二:使用代理机制

原理:有一个代理D,他负责沟通主线程A和其他线程B,当是主线程操作控件时,正常执行;当是其他线程B

操作控件时,通知代理D,之后代理D唤醒主线程A,告诉主线程A去更改控件的一些属性,显然,这样一来,就不存在跨线程操作了,所有的任务由代理D来完成。示例代码如下:

使用delegate定义一个代理delShow。在其他线程中访问控件textbox1时,直接调用showData("其他线程");就可以了,showData函数能自动区分是否是主线程。

delegate void delShow(); //代理

//将对控件的操作写到一个函数中

private void showData(String para) {

if (!textbox1.InvokeRequired) //不需要唤醒,就是创建控件的线程

//如果是创建控件的线程,直接正常操作

}

else //非创建线程,用代理进行操作

{

delShow ds = new delShow(showData);

//唤醒主线程,可以传递参数,也可以为null ,即不传参数

Invoke(ds, new object []{para});

}

}

//其他线程使用,具体线程的建立自己去查看相关书籍

showData("其他线程");

#3楼 2011-01-21 17:15 单程列车

?

1

2

3

4

5

6

7

8

9 10 11 12

13

delegate void delShow(string key); private void showData(String para) { if (!InvokeRequired) { textBox1.Text = para; } else {

this.Invoke(new delShow(showData), para); } }

给你改了改,这样看起来好一点

C#中使用SerialPort 类实现简单串口编程 .NET 提供了SerialPort 类进行串口通信,使用很简单,连我这个.NET 新手也能很快上手.以下是从网上找到并自己修改后的参考代码:

1 using System;

2 using System.Collections.Generic;

3 using System.Linq;

4 using System.Text;

5 using System.Windows;

6 using System.Windows.Controls;

7 using System.Windows.Data;

8 using System.Windows.Documents;

11using System.Windows.Media.Imaging;

12using System.Windows.Navigation;

13using System.Windows.Shapes;

14using System.IO.Ports;

15

16namespace CsharpComm

17{

18///

19/// Window1.xaml 的交互逻辑

20///

21public partial class Window1 : Window

22 {

23public Window1()

24 {

25 InitializeComponent();

26 }

27

28//定义 SerialPort对象

29 SerialPort port1;

30

31//初始化SerialPort对象方法.PortName为COM口名称,例如"COM1","COM2"等,注意是string类型

32public void InitCOM(string PortName)

33 {

34 port1 = new SerialPort(PortName);

35 port1.BaudRate = 9600;//波特率

36 port1.Parity = Parity.None;//无奇偶校验位

37 port1.StopBits = StopBits.Two;//两个停止位

38 port1.Handshake = Handshake.RequestToSend;//控制协议

39 port1.ReceivedBytesThreshold = 4;//设置 DataReceived 事件发生前内部输入缓冲区中的字节数

40 port1.DataReceived += new SerialDataReceivedEventHandler(port1_DataReceived);//D ataReceived事件委托

41 }

42

43//DataReceived事件委托方法

44private void port1_DataReceived(object sender, SerialDataReceivedEventArgs e)

45 {

46try

47 {

48 StringBuilder currentline = new StringBuilder();

49//循环接收数据

50while (port1.BytesToRead > 0)

51 {

52char ch = (char)port1.ReadByte();

53 currentline.Append(ch);

54 }

55//在这里对接收到的数据进行处理

59catch(Exception ex)

60 {

61 Console.WriteLine(ex.Message.ToString());

62 }

63

64 }

65

66//打开串口的方法

67public void OpenPort()

68 {

69try

70 {

71 port1.Open();

72 }

73catch { }

74if (port1.IsOpen)

75 {

76 Console.WriteLine("the port is opened!");

77 }

78else

79 {

80 Console.WriteLine("failure to open the port!");

81 }

82 }

83

84//关闭串口的方法

85public void ClosePort()

86 {

87 port1.Close();

88if (!port1.IsOpen)

89 {

90 Console.WriteLine("the port is already closed!");

91 }

92 }

93

94//向串口发送数据

95public void SendCommand(string CommandString)

96 {

97byte[] WriteBuffer = Encoding.ASCII.GetBytes(CommandString);

98 port1.Write(WriteBuffer, 0, WriteBuffer.Length);

99 }

100

101//调用实例

102private void btnOpen_Click(object sender, RoutedEventArgs e)

103 {

104//我现在用的COM1端口,按需要可改成COM2,COM3

108 }

109}

值得注意的是:

1. port1.ReceivedBytesThreshold = 4; ReceivedBytesThreshold属性设置触发一次DataReceived事件时将接收到的数据字节数.由于我的硬件是一次发上来4个字节估设置为4.如果不能正确设置这个属性的话,在SerialPort对象第一次触发DataReceived事件时还是正确的(4个字节),但是从第二次触发之后都是一个字节触发一次DataReceived事件...为什么这样搞不清楚...

2.如果在 DataReceived 委托事件中使用了不是DataReceived委托事件所在线程创建的UI控件,函数等,需要使用到Dispatcher 类来达到线程安全,不然会报错.以下是MSDN中Dispatcher类的例子(XAML),简单明了:

1private delegate void AddTextDelegate(Panel p, String text);

2

3private void AddText(Panel p, String text)

4{

5 p.Children.Clear();

6 p.Children.Add(new TextBlock { Text = text });

7}

8

9private void TestBeginInvokeWithParameters(Panel p)

10{

11if (p.Dispatcher.CheckAccess()) AddText(p, "Added directly.");

12else p.Dispatcher.BeginInvoke(

13new AddTextDelegate(AddText), p, "Added by Dispatcher.");

14}

C#的usb通讯编程

using System;

using System.Collections.Generic;

using https://www.doczj.com/doc/8012122176.html,ponentModel;

using System.Data;

using System.Drawing;

using System.Text;

using System.Windows.Forms;

using System.IO;

nam espace U盘更新

{

public partial class Form1 : Form

{

public const int WM_DEVICECHANGE = 0x219;

public const int DBT_DEVICEARRIVAL = 0x8000;

public const int DBT_CONFIGCHANGECANCELED = 0x0019;

public const int DBT_CONFIGCHANGED = 0x0018;

public const int DBT_CUSTOMEVENT = 0x8006;

public const int DBT_DEVICEQUERYREMOVE = 0x8001;

public const int DBT_DEVICETYPESPECIFIC = 0x8005;

public const int DBT_DEVNODES_CHANGED = 0x0007;

public const int DBT_QUERYCHANGECONFIG = 0x0017;

public const int DBT_USERDEFINED = 0xFFFF;

public Form1()

{

InitializeComponent();

}

private void Form1_Load(object sender, EventArgs e)

{

}

protected override void WndProc(ref Message m)

{

try

{

if (m.Msg == WM_DEVICECHANGE)

{

switch (m.WParam.ToInt32())

{

case WM_DEVICECHANGE:

break;

case DBT_DEVICEARRIVAL://U盘插入

DriveInfo[] s = DriveInfo.GetDrives();

foreach (DriveInfo drive in s)

{

if (drive.DriveType == DriveType.Rem ovable)

{

listBox1.Item s.Add("U盘已插入,盘符为:" + https://www.doczj.com/doc/8012122176.html,.ToString());

break;

}

}

break;

case DBT_CONFIGCHANGECANCELED:

break;

case DBT_CONFIGCHANGED:

break;

case DBT_CUSTOMEVENT:

break;

case DBT_DEVICEQUERYREMOVE:

break;

case DBT_DEVICEQUERYREMOVEFAILED:

break;

case DBT_DEVICEREMOVECOMPLETE: //U盘卸载

break;

case DBT_DEVICETYPESPECIFIC:

break;

case DBT_DEVNODES_CHANGED:

break;

case DBT_QUERYCHANGECONFIG:

break;

case DBT_USERDEFINED:

break;

default:

break;

}

}

}

catch (Exception ex)

{

MessageBox.Show(ex.Message);

}

base.WndProc(ref m);

}

}

}

C# USB转串口突然拔出检测解决方案

最近做虚拟串口通讯程序(IRDA-USB-串口),由于是USB设备所以在通讯过程中有可能把串口拔出,程序需要实时检测到串口拔出。并把正在执行的任务结束关闭串口,给出提示。由于程序是C#做的,C#在操作底层比较不方便,需要调用较多的API函数。开始的方法是先捕获USB设备的拔出,再查找

HKEY_LOCAL_MACHINE/HAEDWARE/DEVICEMAP/SERialCOM中的串口是否已经不存在。后来发现这种办法不可行.后来我想查找注册表的

HKEY_LOCAL_MACHINE/SYSTEM/CurrentControlSet/Control/DeviceClasses/a5dcbf10-6530-11d2-901f-00c04 fb951ed} 中的相应项看是否LInked等于零,如果是就是你的usb设备拔出了。而且你还要检测是不是你的那个串口,这样算是可以解决问题.。之后我有想用异常的方法来解决这个问题,首先还是捕获USB设备的拔出消息,由于.NET并不知道串口的拔出,要是该串口正在使用,这是对串口的访问将会产生异常,所以通过捕获异常来处理是最好有方便的。代码如下:

protected override void WndProc(ref Message m)

{

if (m.Msg == 0x0219)

{//设备被拔出

if (对串口进行操作)

{//产生异常

关闭串口

}

}

}

base.WndProc(ref m);

}

当设备被插入/拔出的时候,WINDOWS会向每个窗体发送WM_DEVICECHANGE消息,当消息的wParam 值等于DBT_DEVICEARRIVAL时,表示Media设备被插入并且已经可用;如果wParam值等于

DBT_DEVICEREMOVECOMPLETE,表示Media设备已经被移出。

它们的lParam都指向一个DEV_BROADCAST_HDR结构体,其原形如下:

1 typedef struct _DEV_BROADCAST_HDR

2 {

3 DWORD dbch_size;

4 DWORD dbch_devicetype;

5 DWORD dbch_reserved;

6 } DEV_BROADCAST_HDR, *PDEV_BROADCAST_HDR;

这个结构体仅仅是一个“头”(HDR),其后还有附加数据,dbch_size表示结构体实例的字节数,当其中的

dbch_devicetype字段值等于DBT_DEVTYP_VOLUME时,表示当前设备是逻辑驱动器,且lParam实际上指向的应该是DEV_BROADCAST_VOLUME结构体实例(真佩服这种逻辑),DEV_BROADCAST_VOLUME结构体原形如下:

1typedef struct _DEV_BROADCAST_VOLUME {

2 DWORD dbcv_size;

3 DWORD dbcv_devicetype;

4 DWORD dbcv_reserved;

5 DWORD dbcv_unitmask;

6 WORD dbcv_flags;

7} DEV_BROADCAST_VOLUME, *PDEV_BROADCAST_VOLUME;

其中dbcv_unitmask字段表示当前改变的驱动器掩码,第一位表示驱动器号A,第二位表示驱动器号B,第三位表示驱动器号C,以此类推……dbcv_flags表示驱动器的类别,如果等于1,则是光盘驱动器;如果是2,则是网络驱动器;如果是硬盘、U盘则都等于0

所以,我只需要在程序中捕捉WM_DEVICECHANGE消息,然后根据具体情况去处理即可,下面是我的测试代码:

using System;

using System.Runtime.InteropServices;

using System.Collections.Generic;

using https://www.doczj.com/doc/8012122176.html,ponentModel;

using System.Data;

using System.Drawing;

using System.Text;

using System.Windows.Forms;

namespace UDiskDetect

{

public partial class Form1 : Form

{

public Form1()

{

InitializeComponent();

}

private void Form1_Load(object sender, EventArgs e)

{

}

[StructLayout(LayoutKind.Sequential)]

struct DEV_BROADCAST_HDR

{

public UInt32 dbch_size;

public UInt32 dbch_devicetype;

public UInt32 dbch_reserved;

}

[StructLayout(LayoutKind.Sequential)]

struct DEV_BROADCAST_VOLUME

{

public UInt32 dbcv_reserved;

public UInt32 dbcv_unitmask;

public UInt16 dbcv_flags;

}

protected override void DefWndProc(ref Message m)

{

if (m.Msg == 0x0219)//WM_DEVICECHANGE

{

switch (m.WParam.ToInt32())

{

case 0x8000://DBT_DEVICEARRIVAL

{

DEV_BROADCAST_HDR dbhdr = (DEV_BROADCAST_HDR)Marshal.PtrToStructure(m.LPara m, typeof(DEV_BROADCAST_HDR));

if (dbhdr.dbch_devicetype == 0x00000002)//DBT_DEVTYP_VOLUME

{

DEV_BROADCAST_VOLUME dbv = (DEV_BROADCAST_VOLUME)Marshal.PtrToStructure(m. LParam, typeof(DEV_BROADCAST_VOLUME));

if (dbv.dbcv_flags == 0)

AddVolumes(GetVolumes(dbv.dbcv_unitmask));

}

break;

}

case 0x8004://DBT_DEVICEREMOVECOMPLETE

{

DEV_BROADCAST_HDR dbhdr = (DEV_BROADCAST_HDR)Marshal.PtrToStructure(m.LPara m, typeof(DEV_BROADCAST_HDR));

if (dbhdr.dbch_devicetype == 0x00000002)//DBT_DEVTYP_VOLUME

{

DEV_BROADCAST_VOLUME dbv = (DEV_BROADCAST_VOLUME)Marshal.PtrToStructure(m. LParam, typeof(DEV_BROADCAST_VOLUME));

if (dbv.dbcv_flags == 0)

RemoveVolumes(GetVolumes(dbv.dbcv_unitmask));

}

}

}

base.DefWndProc(ref m);

}

///

///根据驱动器掩码返回驱动器号数组

///

///掩码

///返回驱动器号数组

public static char[] GetVolumes(UInt32 Mask) {

List Volumes = new List();

for (int i = 0; i < 32; i++)

{

uint p = (uint)Math.Pow(2, i);

if ((p | Mask) == p)

{

Volumes.Add((char)('A' + i));

}

}

return Volumes.ToArray();

}

public void AddVolumes(char[] Volumes)

{

foreach (char volume in Volumes)

listBox1.Items.Add(volume);

}

public void RemoveVolumes(char[] Volumes) {

foreach (char volume in Volumes)

listBox1.Items.Remove(volume);

}

}

}

C#实现USB接口的程序代码

C#实现USB接口的程序代码.

namespace ConsoleApplication1

{

class Program

{

static void Main(string[] args)

{

USB usb;

usb = new UDisk();//插入U盘

usb.OutputFile();//从U盘读出文件

usb.InputFile();//往U盘写入文件

usb.Dispose();//拔出U盘

Console.WriteLine("");

usb = new MDisk();//插入移动硬盘

usb.OutputFile();//从移动硬盘读出文件

usb.InputFile();//往移动硬盘写入文件

usb.Dispose();//拔出移动硬盘

Console.WriteLine("");

usb = new MP4();//插入MP4

usb.OutputFile();//从MP4读出文件

usb.InputFile();//往MP4写入文件

usb.Dispose();//拔出MP4

Console.ReadKey();

}

//USB接口

public interface USB : IDisposable

{

void OutputFile();//读出文件

void InputFile();//写入文件

}

//U盘

public class UDisk : USB

{

public UDisk()

{

Console.WriteLine("U盘准备就绪...");

}

public void OutputFile()

}

public void InputFile()

{

Console.WriteLine("往U盘写入文件");

}

public void Dispose()

{

Console.WriteLine("U盘已被拔出");

}

}

//移动硬盘

public class MDisk : USB

{

public MDisk()

{

Console.WriteLine("移动硬盘准备就绪...");

}

public void OutputFile()

{

Console.WriteLine("从移动硬盘读出文件");

}

public void InputFile()

{

Console.WriteLine("往移动硬盘写入文件");

}

public void Dispose()

{

Console.WriteLine("移动硬盘已被拔出");

}

}

//MP4

public class MP4 : USB

{

public MP4()

{

Console.WriteLine("MP4准备就绪...");

}

public void OutputFile()

{

Console.WriteLine("从MP4读出文件");

}

public void InputFile()

{

Console.WriteLine("往MP4写入文件");

}

C#:USB设备枚举(一)DeviceIoControl的PInvoke 开发环境:

Visual Studio V2010

.NET Framework 4 Client Profile

版本历史:

V1.0 2011年10月10日

实现对DeviceIoControl接口的PInvoke

参考资料:

https://www.doczj.com/doc/8012122176.html,/

------------------------------------------------------------ */

using System;

using System.Runtime.InteropServices;

namespace Splash.IO.PORTS

{

#region ENUM

public enum USB_HUB_NODE : uint

{

UsbHub,

UsbMIParent

}

public enum USB_CONNECTION_STATUS

{

NoDeviceConnected,

DeviceConnected,

DeviceFailedEnumeration,

DeviceNotEnoughPower,

DeviceNotEnoughBandwidth,

DeviceHubNestedTooDeeply,

DeviceInLegacyHub

}

public enum USB_DEVICE_SPEED : byte

{

UsbLowSpeed, // 低速USB 1.1

UsbFullSpeed, // 全速USB 1.1

UsbHighSpeed, // 高速USB 2.0

UsbSuperSpeed // 极速USB 3.0

}

#endregion

public partial class USB

{

internal const Int32 IOCTL_GET_HCD_DRIVERKEY_NAME = 0x220424;

internal const Int32 IOCTL_USB_GET_ROOT_HUB_NAME = 0x220408;

internal const Int32 IOCTL_USB_GET_NODE_CONNECTION_NAME = 0x220414;

internal const Int32 IOCTL_USB_GET_NODE_INFORMATION = 0x220408;

internal const Int32 IOCTL_USB_GET_NODE_CONNECTION_INFORMATION_EX = 0x220448; internal const Int32 IOCTL_USB_GET_DESCRIPTOR_FROM_NODE_CONNECTION = 0x220410;

internal const Int32 MAXIMUM_USB_STRING_LENGTH = 255;

internal const Int32 USB_STRING_DESCRIPTOR_TYPE = 3;

[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]

internal struct USB_HCD_DRIVERKEY_NAME

{

public Int32 ActualLength;

[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)]

public String Name;

}

[StructLayout(LayoutKind.Sequential, Pack = 1)]

internal struct USB_HUB_DESCRIPTOR

{

public Byte bDescriptorLength;

public Byte bDescriptorType; // 描述符类型:0x29

public Byte bNumberOfPorts; // 支持的下游端口数目

public Int16 wHubCharacteristics; // 特征描述

public Byte bPowerOnToPowerGood; // 从端口加电到端口正常工作的时间间隔(以2ms 为单位)

public Byte bHubControlCurrent; // 设备所需最大电流

[MarshalAs(UnmanagedType.ByValArray, SizeConst = 64)]

public Byte[] bRemoveAndPowerMask; // 指示连接在集线器端口的设备是否可移走

}

[StructLayout(LayoutKind.Sequential)]

internal struct USB_HUB_INFORMATION

{

public USB_HUB_DESCRIPTOR HubDescriptor;

public Byte HubIsBusPowered;

}

[StructLayout(LayoutKind.Sequential)]

internal struct USB_MI_PARENT_INFORMATION

{

public Int32 NumberOfInterfaces;

};

[StructLayout(LayoutKind.Explicit)]

internal struct UsbNodeUnion

{

[FieldOffset(0)]

public USB_HUB_INFORMATION HubInformation;

[FieldOffset(0)]

public USB_MI_PARENT_INFORMATION MiParentInformation;

[StructLayout(LayoutKind.Sequential)]

internal struct USB_NODE_INFORMATION

{

public USB_HUB_NODE NodeType;

public UsbNodeUnion u;

}

#endregion

#region USB_NODE_CONNECTION_INFORMATION

[StructLayout(LayoutKind.Sequential, Pack = 1)] internal struct USB_DEVICE_DESCRIPTOR

{

public Byte bLength;

public Byte bDescriptorType;

public UInt16 bcdUSB;

public Byte bDeviceClass;

public Byte bDeviceSubClass;

public Byte bDeviceProtocol;

public Byte bMaxPacketSize0;

public UInt16 idVendor;

public UInt16 idProduct;

public UInt16 bcdDevice;

public Byte iManufacturer;

public Byte iProduct;

public Byte iSerialNumber;

public Byte bNumConfigurations;

}

[StructLayout(LayoutKind.Sequential, Pack = 1)] internal struct USB_ENDPOINT_DESCRIPTOR

{

public Byte bLength;

public Byte bDescriptorType;

public Byte bEndpointAddress;

public Byte bInterval;

}

[StructLayout(LayoutKind.Sequential, Pack = 1)]

internal struct USB_PIPE_INFO

{

public USB_ENDPOINT_DESCRIPTOR EndpointDescriptor;

public UInt32 ScheduleOffset;

}

[StructLayout(LayoutKind.Sequential, Pack = 1)]

internal struct USB_NODE_CONNECTION_INFORMATION_EX

{

public Int32 ConnectionIndex;

public USB_DEVICE_DESCRIPTOR DeviceDescriptor;

public Byte CurrentConfigurationValue;

public Byte Speed;

public Byte DeviceIsHub;

public Int16 DeviceAddress;

public Int32 NumberOfOpenPipes;

public USB_CONNECTION_STATUS ConnectionStatus;

[MarshalAs(UnmanagedType.ByValArray, SizeConst = 32)] public USB_PIPE_INFO[] PipeList;

}

#endregion

#region USB_DESCRIPTOR_REQUEST

[StructLayout(LayoutKind.Sequential)]

internal struct USB_SETUP_PACKET

{

public Byte bmRequest;

public Byte bRequest;

public UInt16 wValue;

public UInt16 wIndex;

[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]

internal struct USB_STRING_DESCRIPTOR

{

public Byte bLength;

public Byte bDescriptorType;

[MarshalAs(UnmanagedType.ByValTStr, SizeConst = MAXIMUM_USB_STRING_LENGTH)] public String bString;

}

[StructLayout(LayoutKind.Sequential)]

internal struct USB_DESCRIPTOR_REQUEST

{

public Int32 ConnectionIndex;

public USB_SETUP_PACKET SetupPacket;

public USB_STRING_DESCRIPTOR Data;

}

#endregion

#region USB_NODE_CONNECTION_DRIVERKEY_NAME

[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]

internal struct USB_NODE_CONNECTION_DRIVERKEY_NAME

{

public Int32 ConnectionIndex;

public Int32 ActualLength;

[MarshalAs(UnmanagedType.ByValTStr, SizeConst = MAXIMUM_USB_STRING_LENGTH)] public String DriverKeyName;

}

#endregion

#region DeviceIoControl

[DllImport("kernel32.dll", CharSet = CharSet.Ansi, SetLastError = true)]

internal static extern Boolean DeviceIoControl(

IntPtr hFile,

串口通信测试方法

串口通信测试方法 LELE was finally revised on the morning of December 16, 2020

串口通信测试方法 1关于串口通信的一些知识: RS-232C是目前最常用的串行接口标准,用来实现计算机和计算机之间、计算机和外设之间的数据通信。 在PC机系统中都装有异步通信适配器,利用它可以实现异步串行通信。而且MCS-51单片机本身具有一个全双工的串行接口,因此只要配以电平转换的驱动电路、隔离电路就可以组成一个简单可行的通信接口。 由于MCS-51单片机的输入和输出电平为TTL电平,而PC机配置的是RS-232C 标准串行接口,二者电气规范不一致,因此要完成PC机与单片机的数据通信,必须进行电平转换。 注明:3)RS-232C上传送的数字量采用负逻辑,且与地对称 逻辑1:-3~-15V 逻辑0:+3~+15V 所以与单片机连接时常常需要加入电平转换芯片: 2实现串口通信的三个步骤: (1)硬件连接 51单片机有一个全双工的串行通讯口,所以单片机和计算机之间可以方便地进行串口通讯。进行串行通讯时要满足一定的条件,比如计算机的串口是RS232电平的,而单片机的串口是TTL电平的,两者之间必须有一个电平转换电路,我们采用了专用芯片MAX232进行转换。我们采用了三线制连接串口,也就是说和计算机的9针串口只连接其中的3根线:第5脚的GND、第2脚的RXD、第3脚的TXD。电路如下图所示,MAX232的第10脚和单片机的11脚连接,第9脚和单片机的10脚连接,第15脚和单片机的20脚连接。 使用MAX232串口通信电路图(9孔串口接头) (2)串行通信程序设计 ①通信协议的使用 通信协议是通信设备在通信前的约定。单片机、计算机有了协议这种约定,通信双方才能明白对方的意图,以进行下一步动作。假定我们需要在PC机与单片机之间进行通信,在设计过程中,有如下约定: 0x31:PC机发送0x31,单片机回送0x01,表示选择本单片机; 0x**:PC机发送0x**,单片机回送0x**,表示选择单片机后发送数据通信正常; 在系统工作过程中,单片机接收到PC机数据信息后,便查找协议,完成相应的操作。 ②串行通信程序设计主要有微机发送接收程序和单片机发送接收程序,微机上的发送和接收程序主要采用计算机高级语言编写,如C语言,因为了能够在计算机端看到单片机发出的数据,我们必须借助一个WINDOWS软件进行观察,这里利用如下图标的一个免费计算机串口调试软件,故而这一块计算机通信的程序可不写!

C语言串口通信助手代码

该程序全部由C写成没有C++ 更没用MFC 完全是自娱自乐给需要的人一个参考 #include "stdafx.h" #include #include "resource.h" #include "MainDlg.h" #include #include #include HANDLE hComm;//用于获取串口打开函数的返回值(句柄或错误值)OVERLAPPED m_ov; COMSTAT comstat; DWORD m_dwCommEvents;

TCHAR cRecs[200],cSends[100]; //接收字符串发送字符串 char j=0,*cCom; //接收用统计数据大小变量端口选择 BOOL WINAPI Main_Proc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { switch(uMsg) { HANDLE_MSG(hWnd, WM_INITDIALOG, Main_OnInitDialog); HANDLE_MSG(hWnd, WM_COMMAND, Main_OnCommand); HANDLE_MSG(hWnd,WM_CLOSE, Main_OnClose); } return FALSE; } /*系统初始化函数*/ BOOL Main_OnInitDialog(HWND hwnd, HWND hwndFocus, LPARAM lParam) { HWND hwndCombo1=GetDlgItem(hwnd,IDC_COMBO1); ComboBox_InsertString(hwndCombo1,-1,TEXT("COM1")); ComboBox_InsertString(hwndCombo1,-1,TEXT("COM2"));

常用通讯测试工具使用

常用通讯测试工具 鉴于很多MCGS用户和技术人员对通讯测试工具并不很熟悉,本文档将针对实际的测试情况,对串口、以太网通讯调试过程中所涉及到的常用的测试软件进行相关的讲解。 1. 串口测试工具: 串口调试工具:用来模拟上下位机收发数据的串口工具,占用串口资源。如:串口调试助手,串口精灵,Comm等。 串口监听工具:用来监听上下位机串口相关操作,并截获收发数据的串口工具。不占用串口资源。如:PortMon,ComSky等。 串口模拟工具:用来模拟物理串口的操作,其模拟生成的串口为成对出现,并可被大多数串口调试和监听软件正常识别,是串口测试的绝好工具。如:Visual Serial Port等。 下面将分别介绍串口调试助手、Comm、PortMon和Visual Serial Port的使用。

1.1. 串口调试助手: 为最常用的串口收发测试工具,其各区域说明及操作过程如下: 串口状态 打开/关闭串口 十六进制/ASCII 切换 串口数据 接收区 串口参数 设置区 串口数据 发送区 串口收发计数区 发送数据功能区 保存数据功能区 操作流程如下: ? 设置串口参数(之前先关闭串口)。 ? 设置接收字符类型(十六进制/ASCII 码) ? 设置保存数据的目录路径。 ? 打开串口。 ? 输入发送数据(类型应与接收相同)。 ? 手动或自动发送数据。 ? 点击“保存显示数据”保存接收数据区数据到文件RecXX.txt。 ? 关闭串口。 注:如果没有相应串口或串口被占用时,软件会弹出“没有发现此串口”的提示。

1.2. PortMon 串口监听工具: 用来监听上下位机串口相关操作,并截获收发数据的串口工具。不占用串口资源, 但在进行监听前,要保证相应串口不被占用,否则无法正常监听数据。 连接状态 菜单栏 工具栏 截获数据显示区 PortMon 设置及使用: 1). 确保要监听的串口未被占用。 如果串口被占用,请关闭相应串口的应用程序。比如:要监视MCGS 软件与串口1设备通讯,应该先关闭MCGS 软件。 说明:PortMon 虽不占用串口资源,但在使用前必须确保要监听的串口未被占用,否则无法进行监视。 2). 运行PortMon,并进行相应设置。 ? 连接设置: 在菜单栏选择“计算机(M)”->“连接本地(L)”。如果连接成功,则连接状态显示为“PortMon 于\\计算机名(本地)”。如下图:

c语言串口通信范例

一个c语言的串口通信程序范例 分类:技术笔记 标签: c语言 串口通信 通信程序 it 最近接触一个项目,用HL-C1C激光位移传感器+易控组态软件完成生产线高度跳变检测,好久没有接触c c#,一些资料,找来做个记录,也许大家用的着 #include #include #include #include #define COM232 0x2f8 #define COMINT 0x0b #define MaxBufLen 500 #define Port8259 0x20 #define EofInt 0x20 static int comportaddr; static char intvectnum; static unsigned char maskb; static unsigned char Buffer[MaxBufLen]; static int CharsInBuf,CircIn,CircOut; static void (interrupt far *OldAsyncInt)();

static void interrupt far AsyncInt(void); void Init_COM(int ComPortAddr, unsigned char IntVectNum, int Baud, unsigned char Data, unsigned char Stop, unsigned char Parity) { unsigned char High,Low; int f; comportaddr=ComPortAddr; intvectnum=IntVectNum; CharsInBuf=0;CircIn=0;CircOut=0; f=(Baud/100); f=1152/f; High=f/256; Low=f-High*256; outp(ComPortAddr+3,0x80); outp(ComPortAddr,Low); outp(ComPortAddr+1,High); Data=(Data-5)|((Stop-1)*4); if(Parity==2) Data=Data|0x18; else if(Parity==1) Data=Data|0x8; outp(ComPortAddr+3,Data); outp(ComPortAddr+4,0x0a);

串口通信实验

实验报告(附页) 一、实验内容 1、串口通信设置: 波特率为115200bps, 数据位为8位,停止位为1位; 2、按键传输数据到串口助手显示; (1)按1,串口显示:“This is Key 1”; D5亮 (2)按2,串口显示:“This is Key 2”; D6亮 (3)按3,串口显示:“This is Key 3”; D7亮 (4)按4,串口显示:“This is Key 4”; D8亮 (5)按“*”Key ,串口显示“All LEDs is Closed” ; 灯全灭; (6)按其它Key,串口显示:”Wrong Key” 3、通过串口小肋手,向实验设备发送信息: 发送字符:”D5”、”D6”、”D7”、”D8” ,则对应的D5、D6、D7、D8亮;若发送“5”、“6”、“7”、“8”则对应的D5、D6、D7、D8灭,如发送其它字符,则在串口助手中显示:“Error Code”; 二、实验方法 (1)利用参考代码构建工程。 (2)编写实验要求的实现实验要求的功能。 (3)连接实验箱,写入程序,测试代码。 三、实验步骤 1)正确连接JLINK 仿真器到PC 机和stm32 板,用串口线一端连接STM32 开发板,另一端连接PC 机串口。 2)用IAR 开发环境打开实验例程:在文件夹05-实验例程\第2 章\2.3-uart 下双击打开工程uart.eww,Project->Rebuild All 重新编译工程。 3)将连接好的硬件平台通电(STM32 电源开关必须拨到“ ON”),接下来选择Project->Download and debug 将程序下载到STM32 开发板中。4)下载完后可以点击“Debug”->“Go”程序全速运行;也可以将STM32 开发板重新上电或者按下复位按钮让刚才下载的程序重新运行。 5)通过串口小助手检验实验结果 四、实验结果 Main函数 #include"stm32f10x.h"

单片机串口通信C程序及应用实例

一、程序代码 #include//该头文件可到https://www.doczj.com/doc/8012122176.html,网站下载#define uint unsigned int #define uchar unsigned char uchar indata[4]; uchar outdata[4]; uchar flag; static uchar temp1,temp2,temp3,temp; static uchar R_counter,T_counter; void system_initial(void); void initial_comm(void); void delay(uchar x); void uart_send(void); void read_Instatus(void); serial_contral(void); void main() { system_initial(); initial_comm(); while(1) { if(flag==1) { ES = 0; serial_contral(); ES = 1; flag = 0; } else read_Instatus(); } } void uart_send(void) { for(T_counter=0;T_counter<4;T_counter++) { SBUF = outdata[T_counter]; while(TI == 0);

TI = 0; } T_counter = 0; } uart_receive(void) interrupt 4 { if(RI) { RI = 0; indata[R_counter] = SBUF; R_counter++; if(R_counter>=4) { R_counter = 0; flag = 1; } } } void system_initial(void) { P1M1 = 0x00; P1M0 = 0xff; P1 = 0xff; //初始化为全部关闭 temp3 = 0x3f;//初始化temp3的值与六路输出的初始值保持一致 temp = 0xf0; R_counter = 0; T_counter = 0; } void initial_comm(void) { SCON = 0x50; //设定串行口工作方式:mode 1 ; 8-bit UART,enable ucvr TMOD = 0x21; //TIMER 1;mode 2 ;8-Bit Reload PCON = 0x80; //波特率不加倍SMOD = 1 TH1 = 0xfa; //baud: 9600;fosc = 11.0596 IE = 0x90; // enable serial interrupt TR1 = 1; // timer 1 RI = 0; TI = 0; ES = 1; EA = 1; }

串行通信接口标准详解

几种串行通信接口标准详解 在数据通信、计算机网络以及分布式工业控制系统中,经常采用串行通信来交换数据和信息。1969年,美国电子工业协会(EIA)公布了RS-232C作为串行通信接口的电气标准,该标准定义了数据终端设备(DTE)和数据通信设备(DCE)间按位串行传输的接口信息,合理安排了接口的电气信号和机械要求,在世界范围内得到了广泛的应用。但它采用单端驱动非差分接收电路,因而存在着传输距离不太远(最大传输距离15m)和传送速率不太高(最大位速率为20Kb/s)的问题。远距离串行通信必须使用Modem,增加了成本。在分布式控制系统和工业局部网络中,传输距离常介于近距离(<20m=和远距离(>2km)之间的情况,这时RS-232C(25脚连接器)不能采用,用Modem又不经济,因而需要制定新的串行通信接口标准。 1977年EIA制定了RS-449。它除了保留与RS-232C兼容的特点外,还在提高传输速率,增加传输距离及改进电气特性等方面作了很大努力,并增加了10个控制信号。与RS-449同时推出的还有RS-422和RS-423,它们是RS-449的标准子集。另外,还有RS-485,它是RS-422的变形。RS-422、RS-423是全双工的,而RS-485是半双工的。 RS-422标准规定采用平衡驱动差分接收电路,提高了数据传输速率(最大位速率为10Mb/s),增加了传输距离(最大传输距离1200m)。 RS-423标准规定采用单端驱动差分接收电路,其电气性能与RS-232C几乎相同,并设计成可连接RS-232C和RS-422。它一端可与RS-422连接,另一端则可与RS-232C连接,提供了一种从旧技术到新技术过渡的手段。同时又提高位速率(最大为300Kb/s)和传输距离(最大为600m)。 因RS-485为半双工的,当用于多站互连时可节省信号线,便于高速、远距离传送。许多智能仪器设备均配有RS-485总线接口,将它们联网也十分方便。 串行通信由于接线少、成本低,在数据采集和控制系统中得到了广泛的应用,产品也多种多样 一.RS-232-C详解 串行通信接口标准经过使用和发展,目前已经有几种。但都是在RS-232标准的基础上经过改进而形成的。所以,以RS-232C为主来讨论。RS-323C标准是美国EIA(电子工业联合会)与BELL等公司一起开发的1969年公布的通信协议。它适合于数据传输速率在0~20000b/s范围内的通信。这个标准对串行通信接口的有关问题,如信号线功能、电器特性都作了明确规定。由于通行设备厂商都生产与RS-232C制式兼容的通信设备,因此,它作为一种标准,目前已在微机通信接口中广泛采用。 在讨论RS-232C接口标准的内容之前,先说明两点: 首先,RS-232-C标准最初是远程通信连接数据终端设备DTE(Data Terminal Equipment)与数据通信设备DCE(Data Communication Equipment)而制定的。因此这个标准的制定,并未考虑计算机系统的应用要求。但目前它又广泛地被借来用于计算机(更准确的说,是计算机接口)与终端或外设之间的近端连接标准。显然,这个标准的有些规定及和计算机系统是不一致的,甚至是相矛盾的。有了对这种背景的了解,我们对RS-232C 标准与计算机不兼容的地方就不难理解了。 其次,RS-232C标准中所提到的“发送”和“接收”,都是站在DTE立场上,而不是站在DCE的立场来定义的。由于在计算机系统中,往往是CPU和I/O设备之间传送信息,两者都

c语言串口通信范例

c语言串口通信范例 This manuscript was revised by the office on December 22, 2012

一个c语言的串口通信程序范例 标签:分类: 最近接触一个项目,用HL-C1C激光位移传感器+易控组态软件完成生产线高度跳变检测,好久没有接触c c#,一些资料,找来做个记录,也许大家用的着 #include <> #include <> #include <> #include <> #define COM232 0x2f8 #define COMINT 0x0b #define MaxBufLen 500 #define Port8259 0x20 #define EofInt 0x20

static int comportaddr; static char intvectnum; static unsigned char maskb; static unsigned char Buffer[MaxBufLen]; static int CharsInBuf,CircIn,CircOut; static void (interrupt far *OldAsyncInt)(); static void interrupt far AsyncInt(void); void Init_COM(int ComPortAddr, unsigned char IntVectNum, int Baud, unsigned char Data, unsigned char Stop, unsigned char Parity) { unsigned char High,Low; int f; comportaddr=ComPortAddr; intvectnum=IntVectNum; CharsInBuf=0;CircIn=0;CircOut=0; f=(Baud/100);

C语言串口通信-源代码

#include #include #include #include #define COM232 0x2f8 #define COMINT 0x0b #define MaxBufLen 500 #define Port8259 0x20 #define EofInt 0x20 static int comportaddr; static char intvectnum; static unsigned char maskb; static unsigned char Buffer[MaxBufLen]; static int CharsInBuf,CircIn,CircOut; static void (interrupt far *OldAsyncInt)(); static void interrupt far AsyncInt(void); void Init_COM(int ComPortAddr, unsigned char IntVectNum, int Baud, unsigned char Data, unsigned char Stop, unsigned char Parity) { unsigned char High,Low; int f; comportaddr=ComPortAddr; intvectnum=IntVectNum; CharsInBuf=0;CircIn=0;CircOut=0; f=(Baud/100); f=1152/f; High=f/256; Low=f-High*256; outp(ComPortAddr+3,0x80); outp(ComPortAddr,Low); outp(ComPortAddr+1,High); Data=(Data-5)|((Stop-1)*4); if(Parity==2) Data=Data|0x18; else if(Parity==1) Data=Data|0x8; outp(ComPortAddr+3,Data);

串口通信测试方法

串口通信测试方法 1 关于串口通信的一些知识: RS-232C是目前最常用的串行接口标准,用来实现计算机和计算机之间、计算机和外设之间的数据通信。 在PC机系统中都装有异步通信适配器,利用它可以实现异步串行通信。而且MCS-51单片机本身具有一个全双工的串行接口,因此只要配以电平转换的驱动电路、隔离电路就可以组成一个简单可行的通信接口。 由于MCS-51单片机的输入和输出电平为TTL电平,而PC机配置的是RS-232C 标准串行接口,二者电气规范不一致,因此要完成PC机与单片机的数据通信,必须进行电平转换。 注明:3)RS-232C上传送的数字量采用负逻辑,且与地对称 逻辑1:-3 ~-15V 逻辑0:+3~+15V 所以与单片机连接时常常需要加入电平转换芯片: 2 实现串口通信的三个步骤: (1)硬件连接 51单片机有一个全双工的串行通讯口,所以单片机和计算机之间可以方便地进行串口通讯。进行串行通讯时要满足一定的条件,比如计算机的串口是RS232电平的,而单片机的串口是TTL电平的,两者之间必须有一个电平转换电路,我们采用了专用芯片MAX232进行转换。我们采用了三线制连接串口,也就是说和计算机的9针串口只连接其中的3根线:第5脚的GND、第2脚的RXD、第3脚的TXD。电路如下图所示,MAX232的第10脚和单片机的11脚连接,第9脚和单片机的10脚连接,第15脚和单片机的20脚连接。 使用MAX232串口通信电路图(9孔串口接头) (2)串行通信程序设计 ①通信协议的使用 通信协议是通信设备在通信前的约定。单片机、计算机有了协议这种

约定,通信双方才能明白对方的意图,以进行下一步动作。假定我们需要在PC 机与单片机之间进行通信,在设计过程中,有如下约定:

测试电脑的串口是否是好的 最完整最可靠的方法 就是 连接一个真实 的串口通信线路

测试电脑的串口是否是好的最完整最可靠的方法就是连接一个真实的串口通信线路,2 端用相应软件,如串口调试助手之类的,相互发送发送数据,看另外一端是否能正常接收! 当然,也可以简单的单台机器测试,即短接串口的2、3 两针,用相应软件,如串口调试助手,发送数据,看能否回显发送的数据 串口测试工具使用说明之一——串口调试工具 回复 6 | 人气1387 | 收藏 | 打印 | 推荐给版主 分享文章到: ye_w 个人主页给TA发消息加TA为好友发表于:2010-09-30 19:52:48 楼主 使用串口实现网络通讯,不仅仅需要熟悉控制双方的指令和相关的协议,而且还需要善于使用串口测试工具。在串口测试工具中,最常用的就是串口调试工具。这个串口调试工具网络上一大把,大家百度一下就能下载到(包括我逐步发布的调试工具,都不会提供资源,请大家直接去网络上查找),常用的包括:串口调试助手,串口精灵,Comm等。我也一直使用串口调试助手,下面就是用图形并茂的方式来介绍,请大家指出不足,以便共同进步。 串口调试助手,网络上的版本也有不少,我截2个不同版本的图,但本质没有区别 版本一 怎样测试串口和串口线是否正常 一步:把串口线或者USB转串口线插到计算机上。 二步:打开串口调试助手

接着选择串口,串口线和USB转串口的端口号查看路径: 电脑上--右键--属性--硬件--设备管理器-端口(COM和LPT),点 开端口前面的+号查看即可。 注释:1、USB-SERIAL CH340(COM4)就是USB转串口的端口号 2、通讯端口(COM1)是计算机原来自带的端口号 第三步:设置串口调试助手(见下图) 1、串口:COM4是和串口线或者USB转串口线在上述路径中查看到的端口号。 2、发送的字符/数据:图片上输入的是59,你可以随便输入2位数字。 3、其余设置按照下图。

RS-485串行接口标准

RS-485串行接口标准 1、平衡传输 RS-485数据信号采用差分传输方式,也称作平衡传输,它使用一对双绞线,将其中一线定义为A,另一线定义为B,通常情况下,发送驱动器A、B之间的正电平在+2~+6V,是一个逻辑状态,负电平在-2~6V,是另一个逻辑状态。另有一个信号地C,在RS-485中还有一“使能”端,而在RS-422中这是可用可不用的。“使能”端是用于控制发送驱动器与传输线的切断与连接。当“使能”端起作用时,发送驱动器处于高阻状态,称作“第三态”,即它是有别于逻辑“1”与“0”的第三态。 接收器也作与发送端相对的规定,收、发端通过平衡双绞线将AA与BB对应相连,当在收端AB之间有大于+200mV的电平时,输出正逻辑电平,小于-200mV时,输出负逻辑电平。接收器接收平衡线上的电平范围通常在200mV至6V之间。 2、RS-485电气规定 由于RS-485是从RS-422基础上发展而来的,所以RS-485许多电气规定与RS-422相仿。如都采用平衡传输方式、都需要在传输线上接终接电阻等。RS-485可以采用二线与四线方式,二线制可实现真正的多点双向通信,而采用四线连接时,与RS-422一样只能实现点对多的通信,即只能有一个主(Master)设备,其余为从设备,但它比RS-422有改进,无论四线还是二线连接方式总线上可多接到32个设备。 RS-485与RS-422的不同还在于其共模输出电压是不同的,RS-485是-7V至+12V之间,而RS-422在-7V至+7V之间,RS-485接收器最小输入阻抗为12k剑 鳵S-422是4k健; 旧峡梢运礡S-485满足所有RS-422的规范,所以RS-485的驱动器可以用在RS-422网络中应用。 RS-485与RS-422一样,其最大传输距离约为1219米,最大传输速率为10Mb/s。平衡双绞线的长度与传输速率成反比,在100kb/s速率以下,才可能使用规定最长的电缆长度。只有在很短的距离下才能获得最高速率传输。一般100米长双绞线最大传输速率仅为1Mb/s RS-485需要2个终接电阻,其阻值要求等于传输电缆的特性阻抗。在矩距离传输时可不需终接电阻,即一般在300米以下不需终接电阻。终接电阻接在传输总线的两端。 在MCU之间中长距离通信的诸多方案中、RS-485因硬件设计简单、控制方便、成本低廉等优点广泛应用于工厂自动化、工业控制、小区监控、水利自动报测等领域、但RS-485总线在抗干扰、自适应、通信效率等方面仍存在缺陷、一些细节的处理不当常会导致通信失败甚至系统瘫痪等故障、因此提高RS-485总线的运行可靠性至关重要、 1 RS-485接口电路的硬件设计

实验9指导书:串口通信实验

实验指导书:串口通信实验 实验目的: 通过程序,理解并验证串口通信的编程方法和机制。 本次实验分两个环节,第一环节为用程序发送字符串,用linux命令在另一窗口直接从串口读取; 第二环节为用发送程序发送字符串,用接收程序在另一窗口读取串口并显示。 要求必须完成第一环节,而第二环节为选作。 本实验在虚拟机环境下完成,利用虚拟机创建两个虚拟串口,基于这两个虚拟串口完成串口通信实验。 实验内容: 本次实验需要在linux环境下,用vi工具输入对应的程序,并编译通过,运行后观察结果是否正确。 一、设置虚拟机串口 1.1 VMware的串口: 一个虚拟机最多可以添加四个虚拟串口,有如下3个方法配置虚拟串口: (1) 连接一个虚拟串口到宿主机的物理串口。 (2) 连接一个虚拟串口到宿主机上的一个文件。 (3) 在两个虚拟机之间建立一个直接的连接,或者将虚拟机的串口与宿主机的应用程序连接。 1.2 为虚拟机添加串口 首先要保证虚拟机下的linux处于关机(power off)状态, (1) 选择菜单中的虚拟机 设置(英文版为:VM -> Settings),在硬件(Hardware)标签页中,如 果已有串行端口(serial port),则选中该串口,并点选移除。

(2) 点击Add按钮,在Add Hardware Wizard对话框中选择Serial Port,点击next,分两次添加两 个串口,具体的选项如下图: 串口2的设置:

注意两个串口都使用了命名管道方式,但一个是服务器端,一个是客户端。 (3) 启动linux操作系统,测试两个串口是否设置成功 在linux桌面空白处点击右键,打开两个终端窗口。在其中一个窗口(称为窗口A)中,建立工作目录,并进入该目录。即,执行下述命令: [1]cd /home [2]mkdir src [3]cd src [4]cat /dev/ttyS1 //注意是大写的S 在另一个窗口(称为窗口B)执行下述命令:

串口测试方法和步骤

串口测试方法和步骤Prepared on 21 November 2021

信号测试与分析 版号:xxx 编写:xxx 1、232串口信号: 要点:RS232采用三线制传输分别为TXD\RXD\GND,其中TXD为发送信号,RXD 为接收信号。 全双工,在RS232中任何一条信号线的电压均为负逻辑关系。即: -15v ~ -3v 代表1 +3v ~ +15v 代表0 测试结果与分析: 如图所示,以传输一个8位二进制数值“01101010”为例,异步传输数据的一般格式为:起始位+校验位+数据位+停止位。其中,校验位为可选项。因为 RS232电平为负逻辑,当电压为时,发送逻辑‘0’;当电压为时,发送逻辑 ‘1’。空闲状态为负电压(逻辑1)。 波特率计算:如图,传输9bit(1起始位+8数据位)花费的时间为79us。1s 传输的数据量为1/*9 = 113924,可以推测波特设置的波特率为115200。RS485的波特率计算同理。(二进制系统中,波特率等于比特率) 图示为发送端的波形,接收端波形与接收端波形大同小异,符合RS232电平要求。 (TTL波形暂时不进行分析) 2、485串口信号: 要点:RS485采用差分传输(平衡传输)的方式,半双工,一般有两个引脚A、B。AB间的电势差U为UA-UB: 不带终端电阻AB电势差:+2 ~+6v 逻辑‘1’; -2 ~-6v 逻辑‘0’; 带终端电阻 AB电势差:大于+200mv 逻辑‘1’; 小于-200mv 逻辑‘0’;注意:AB之间的电压差不小于200mv。 不带终端电阻 以传输一个8位二进制数值“01101010”为例: 测试结果与分析: 空闲状态:A=, B=0V,为逻辑‘1’。 发送逻辑‘1’时,A=,B=0V,A-B= ; 发送逻辑‘0’时,A=,B=3V,A-B=; 图示为发送端的波形,接收端波形与接收端波形大同小异,符合RS485电平要求。 (TTL波形暂时不进行分析)

RS485串行通信电路设计

RS485串行通信接口电路的总体设计 在电参数仪的设计中,数据采集由单片机AT89C52负责,上位PC机主要负责通信(包括与单片机之间的串行通信和数据的远程通信),以及数据处理等工作。在工作中,单片机需要定时向上位PC机传送大批量的采样数据。通常,主控PC机和由单片机构成的现场数据采集系统相距较远,近则几十米,远则上百米,并且数据传输通道环境比较恶劣,经常有大容量的电器(如电动机,电焊机等)启动或切断。为了保证下位机的数据能高速及时、安全地传送至上位PC机,单片机和PC机之间采用RS485协议的串行通信方式较为合理。 实际应用中,由于大多数普通PC机只有常用的RS232串行通信口,而不具备RS485通信接口。因此,为了实现RS485协议的串行通信,必须在PC机侧配置RS485/RS232转换器,或者购买适合PC机的RS485卡。这些附加设备的价格一般较贵,尤其是一些RS485卡具有自己独特的驱动程序,上位PC机的通信一般不能直接采用WINDOW95/98环境下有关串口的WIN32通信API函数,程序员还必须熟悉RS485卡的应用函数。为了避开采用RS485通信协议的上述问题,我们决定自制RS485/RS232转换器来实现单片机和PC机之间的通信。 单片机和PC机之间的RS485通信硬件接口电路的框图,如下图1所示。 从图1可看出,单片机的通信信号首先通过光隔,然后经过RS485接口芯片,将电平信号转换成电流环信号。经过长距离传输后,再通过另一个RS485接口芯片,将电流环信号转换成电平信号。 图1单片机与PC机之间的RS485通信硬件接口电路的框图(略) 该电平信号再经过光电隔离,最后由SR232接口芯片,将该电平信号转换成与PC机RS232端口相兼容的RS232电平。由于整个传输通道的两端均有光电隔离,故无论是PC机还是单片机都不会因数据传输线上可能遭受到的高压静电等的干扰而出现“死机”现象。 2接口电路的具体设计 2-1单片机侧RS485接口电路的设计 单片机侧RS485接口电路如图2所示。 AT89C52单片机的串行通信口P3 0(RXD)和P3 1(TXD)的电平符合TTL/CMOS标准(逻辑“0”的电平范围为0V~0.8V,逻辑“1”的电平为2 4V~VCC),它们首先通过光电隔离器件6N137隔离,以保护单片机不受传输通道的干扰影响,其中T01和?T02是为了增加光隔输入端的驱动能力。光隔6N137的左侧电源与单片机相同,右侧必须采用另一组独立的+5V电源,且两组电源不能供电。 图2单片机侧RS485接口电路

用C编写的RS232串口通信程序

void main() { delayms(100); init(); //初始化系统 delayms(100); init_wdt(); //初始化看门狗 while(1) { while(!RI_0) //是否收到数据 { clr_wdt(); } RI_0=0; //清除接收中断标志 buffer=S0BUF; if(buffer==0x5a) //检测祯头0 start0=1; if(buffer==0x54) //检测祯头1 start1=1; if(buffer==0x5a) //检测祯尾0 end0=1; if(buffer==0xfe) //检测祯尾1 end1=1; if((start0==1)&(start1==1)) { buff[i]=buffer; //从祯头1开始存储数据 i++; } if((end0==1)&(end1==1)) //是否已经接收祯尾 { count=i; //数据长度为count个 i=1; if((buff[2]==0x03)&(count==107)) //是否422指令 { buff[0]=0x5a; //重填祯头0 buff[count-4]=0; //校验和清零 for(k=2;k<(count-4);k++) //计算校验和 { buff[count-4]+=buff[k]; } for(k=0;k

S0BUF=buff[k]; while(!TI_0); //等待发送完成 TI_0=0; //清除发送中断标志 } reset(); } else if((buff[2]==0x05)&(count==7)) //是否AD测试指令 { sendad(); reset(); } else if((buff[2]==0x18)&(count==7)) //是否发送时序信号指令 { sendpaulse(); reset(); } else //如果接收错误,则恢复各标志位为初始状态以便下次接收 { reset(); } } } } void reset() { start0=0; //祯头祯尾标志位清零 start1=0; end0=0; end1=0; for(k=0;k

串口通信测试方法

串口通信测试方法 1关于串口通信的一些知识: RS-232C就是目前最常用的串行接口标准,用来实现计算机与计算机之间、计算机与外设之间的数据通信。 在PC机系统中都装有异步通信适配器,利用它可以实现异步串行通信。而且MCS-51单片机本身具有一个全双工的串行接口,因此只要配以电平转换的驱动电路、隔离电路就可以组成一个简单可行的通信接口。 由于MCS-51单片机的输入与输出电平为TTL电平,而PC机配置的就是RS-232C标准串行接口,二者电气规范不一致,因此要完成PC机与单片机的数据通信,必须进行电平转换。 注明:3)RS-232C上传送的数字量采用负逻辑,且与地对称 逻辑1:-3 ~-15V 逻辑0:+3~+15V 所以与单片机连接时常常需要加入电平转换芯片: 2 实现串口通信的三个步骤: (1) 硬件连接 51单片机有一个全双工的串行通讯口,所以单片机与计算机之间可以方便地进行串口通讯。进行串行通讯时要满足一定的条件,比如计算机的串口就是RS232电平的,而单片机的串口就是TTL电平的,两者之间必须有一个电平转换电路,我们采用了专用芯片MAX232进行转换。我们采用了三线制连接串口,也就就是说与计算机的9针串口只连接其中的3根线:第5脚的GND、第2脚

的RXD、第3脚的TXD。电路如下图所示,MAX232的第10脚与单片机的11脚连接,第9脚与单片机的10脚连接,第15脚与单片机的20脚连接。 使用MAX232串口通信电路图(9孔串口接头) (2)串行通信程序设计 ①通信协议的使用 通信协议就是通信设备在通信前的约定。单片机、计算机有了协议这种约定,通信双方才能明白对方的意图,以进行下一步动作。假定我们需要在PC 机与单片机之间进行通信,在设计过程中,有如下约定: 0x31:PC机发送0x31,单片机回送0x01,表示选择本单片机; 0x**:PC机发送0x**,单片机回送0x**,表示选择单片机后发送数据通信正常; 在系统工作过程中,单片机接收到PC机数据信息后,便查找协议,完成相应的操作。 ②串行通信程序设计主要有微机发送接收程序与单片机发送接收程序,微机上的发送与接收程序主要采用计算机高级语言编写,如C语言,因为了能够在计算机端瞧到单片机发出的数据,我们必须借助一个WINDOWS软件进行观察,这里利用

串口通讯测试程序的源代码

using System; using System.Drawing; using System.Collections; using https://www.doczj.com/doc/8012122176.html,ponentModel; using System.Windows.Forms; using System.Data; using System.Threading; namespace BusApp { ///

/// Form1 的摘要说明。 /// public class Form1 : System.Windows.Forms.Form { private https://www.doczj.com/doc/8012122176.html,bel label1; private https://www.doczj.com/doc/8012122176.html,bel label2; private System.Windows.Forms.Button button1; private System.Windows.Forms.GroupBox groupBox1; private https://www.doczj.com/doc/8012122176.html,bel label3; private https://www.doczj.com/doc/8012122176.html,bel label4; private https://www.doczj.com/doc/8012122176.html,bel label5; private https://www.doczj.com/doc/8012122176.html,bel label6; private System.Windows.Forms.Button button2; private System.Windows.Forms.Button button3; private System.Windows.Forms.Button button4; private System.Windows.Forms.TextBox textBox8; private https://www.doczj.com/doc/8012122176.html,bel label7; public int iPort=1; //1,2,3,4 public int iRate=9600; //1200,2400,4800,9600 public byte bSize=8; //8 bits public byte bParity=0; // 0-4=no,odd,even,mark,space public byte bStopBits=1; // 0,1,2 = 1, 1.5, 2 public int iTimeout=1000; public mycom mycom1=new mycom(); public byte[] recb; private System.Windows.Forms.TextBox msg; private System.Windows.Forms.TextBox t_port; private System.Windows.Forms.TextBox t_rate; private System.Windows.Forms.TextBox t_bytesize; private System.Windows.Forms.TextBox t_stopbyte; private System.Windows.Forms.TextBox t_parity; private System.Windows.Forms.TextBox t_send; private System.Windows.Forms.Button button5; //readTimeOut ///

相关主题
文本预览
相关文档 最新文档