本文主要介绍c#模拟串行通信串口的实现实例,通过实例代码详细介绍。对大家的学习或工作都有一定的参考价值。有需要的朋友下面跟边肖学习。
目录
一、领先知识实现串行通信的必要设置二。实验绘图窗口测试III。总结四。完整的代码附后。
一、前导知识
串口是计算机的标准接口。现在PC(个人电脑)一般至少有两个串口COM1和COM2。串口应用广泛。在数据通信、计算机网络和分布式工业控制系统中,经常使用串行通信来交换数据和信息。
电气标准和协议包括RS-232-C、RS-422、RS485、USB(通用串行总线)等。
实现串口通信的必要设置
串行通信最重要的参数是波特率、数据位、停止位和奇偶校验。
对于通过的两个端口,这些参数必须匹配:
波特率
这是一个衡量通信速度的参数。它代表* *每秒传输的位数* *。例如,300波特表示每秒发送300位,波特率与距离成反比。高波特率常用于距离很近的仪器之间的通信。一个典型的例子是GPIB设备的通信。
数据位
这是测量通信中实际数据位的参数。计算机发送一个包,实际数据不会是8位,标准值是5、7、8位。如何设置取决于你想发送的信息。比如标准的ASCII码是0 ~ 127 (7位)。扩展ASCII码为0 ~ 255 (8位)。如果数据使用简单文本(标准ASCII码),则每个数据包使用7位数据。每个包指一个字节,包括起始/停止位、数据位和奇偶校验位。由于实际的数据比特取决于通信协议的选择,所以术语“分组”指的是任何通信情况。
停止位
用于指示单个数据包的最后一位。的典型值为1、1.5和2位。因为数据是在传输线上计时的,每个设备都有自己的时钟,所以在通信中两个设备之间很可能会有一点不同步。因此,停止位不仅表示传输的结束,还为计算机提供了纠正时钟同步的机会。适合停止位的位数越多,不同时钟同步的容忍度越大,但数据传输速率越慢。
同等
串行通信中一种简单的错误检测方法。有四种错误检测方法:偶数、奇数、高和低。当然,没有校验位也可以。对于奇偶校验,串口会设置一个奇偶校验位(数据位后一位),用一个值来保证传输的数据有偶数或奇数的逻辑高位。例如,如果数据是011,那么对于偶数校验,校验位是0,逻辑高位数是偶数。如果是奇数校验,则校验位为1,因此有3个逻辑高位。并且简单地设置逻辑高或逻辑低检查。这样,接收设备可以知道一个比特的状态,并且有机会判断是否有干扰通信的噪声或者数据的发送和接收是否不同步。
二、实验
我们将通过模拟串行通信与pc上的两个串口(COM1、COM2)进行交互。
使用的软件:
启动虚拟串口驱动pro:虚拟串口。用它来模拟两个串口的连接。
绘制窗口
代码实现
1.使用SerialPort控制串口。
private serial port SP1=new serial port();
2.打开串行端口
私有void button2_Click(对象发送方,EventArgs e)
{
如果(!sp1。IsOpen)
{
尝试
{
//串行端口号
sp1。PortName=' COM1
//波特率
sp1。波德拉特=115200;
//数据位
sp1。数据位数=8;
//停止位
sp1。停止位=停止位。一;
//奇偶校验位
sp1。平价=平价。甚至;
//发送//DataReceived事件之前内部缓冲区中的字符数
sp1 .ReceivedBytesThreshold=1;
sp1 .RtsEnable=truesp1 .DtrEnable=truesp1 .读取超时=3000
//控件checkforillegalcrosthreadcalls=false;
//表示将处理系统10 . IO。港口。串行端口对象的数据接收事件的方法。
sp1 .数据接收=新系统10 . IO。港口。串行datareceivedeventhandler(SP1 _数据接收_ 1);
//打开串口
sp1 .open();
消息框.显示(“COM1打开成功!');
}
接住(例外ex)
{
消息框.显示(“COM1打开失败!');
}
}
其他
{
消息框.显示(“COM1打开成功!');
}
}
3.关闭串口
私有空的按钮3 _单击(对象发送方,EventArgs e)
{
如果(sp1 .IsOpen)
{
sp1 .close();
消息框.显示(“COM1关闭成功!');
}
}
串口2的打开和关闭同理串口一实现
4.发送
私有void button1_Click(对象发送方,EventArgs e)
{
如果(sp1 .IsOpen)
{
如果(!字符串IsNullOrEmpty(这个。文本框1。正文))
{
sp1 .WriteLine(这个。文本框1。text ' \ r \ n ');
}
其他
{
消息框.显示('发送数据为空');
}
}
其他
{
消息框.显示(“COM1未打开!');
}
}
5.接收
StringBuilder builder 1=new StringBuilder();
//在接收到了ReceivedBytesThreshold设置的字符个数或接收到了文件结束字符并将其放入了输入缓冲区时被触发
公共void sp1_DataReceived_1(对象发送方SerialDataReceivedEventArgs e)
{
控制台WriteLine('接收中.');
int n=sp1 .BytesToRead//先记录下来,避免某种原因,人为的原因,操作几次之间时间长,缓存不一致
字节[]缓冲区=新字节[n];//声明一个临时数组存储当前来的串口数据
sp1 .Read(buf,0,n);//读取缓冲数据
建筑工人1 .移除(0,builder1 .长度);//清除字符串构造器的内容
建筑工人1 .追加(编码ASCII码。GetString(buf));
string comdata=builder1 .ToString();
控制台WriteLine(' data:' comdata ');
这个Invoke(settextevent,com数据);
}
这里仅仅实现了一般的接收方式,并不严谨和健壮
测试
使用软件模拟串口连接
打开两个程序
在一程序中打开串口1,在二程序中打开串口2,发送消息
在一程序中输入字符'你好,憨憨城!',发现在二程序中接收到,同样,在二程序中输入,在一中也能收到
三、总结
1.由于是异步线程接收,在接收中需要使用委托来跨线程调用组件
公共委托空settext(字符串文本);
公共事件settext settextevent
公共空集(字符串文本)
{
这个。文本框2。text=文本;
}
//再注册
settextevent=set
2.数据接收事件触发条件需要注意,可能在实现时,无法触发导致无法接收。
触发条件是:在接收到了ReceivedBytesThreshold设置的字符个数或接收到了文件结束字符并将其放入了输入缓冲区时被触发
四、附件完整代码
使用系统;
使用系统。集合。泛型;
使用系统。组件模型;
使用系统。数据;
使用系统。绘图;
使用系统100 . Linq
使用系统。文本;
使用系统窗户。形式
使用系统10 . IO。端口;
命名空间培训_USBCOM
{
公共分部类表单1:表单
{
公共表单1()
{
初始化组件();
settextevent=set
}
私有串口SP1=新串口();
StringBuilder builder=new StringBuilder();
私有void button1_Click(对象发送方,EventArgs e)
{
如果(sp1 .IsOpen)
{
如果(!字符串IsNullOrEmpty(这个。文本框1。正文))
{
sp1 .WriteLine(这个。文本框1。text ' \ r \ n ');
}
其他
{
消息框.显示('发送数据为空');
}
}
其他
{
消息框.显示(“COM1未打开!');
}
}
公共委托空settext(字符串文本);
公共事件settext settextevent
公共空集(字符串文本)
{
这个。文本框2。text=文本;
}
StringBuilder builder 1=new StringBuilder();
//在接收到了ReceivedBytesThreshold设置的字符个数或接收到了文件结束字符并将其放入了输入缓冲区时被触发
公共void sp1_DataReceived_1(对象发送方SerialDataReceivedEventArgs e)
{
控制台WriteLine('接收中.');
int n=sp1 .BytesToRead//先记录下来,避免某种原因,人为的原因,操作几次之间时间长,缓存不一致
字节[]缓冲区=新字节[n];//声明一个临时数组存储当前来的串口数据
sp1 .Read(buf,0,n);//读取缓冲数据
建筑工人1 .移除(0,builder1 .长度);//清除字符串构造器的内容
建筑工人1 .追加(编码ASCII码。GetString(buf));
string comdata=builder1 .ToString();
控制台WriteLine(' data:' comdata ');
这个Invoke(settextevent,com数据);
}
私有void button2_Click(对象发送方,EventArgs e)
{
如果(!sp1 .IsOpen)
{
尝试
{
//串口号
sp1 .PortName=' COM1
//波特率
sp1 .波德拉特=115200;
//数据位
sp1 .数据位数=8;
//停止位
sp1 .停止位=停止位。一;
//奇偶校验位
sp1 .平价=平价。甚至;
//数据接收事件发送前,内部缓冲区里的字符数
sp1 .ReceivedBytesThreshold=1;
sp1 .RtsEnable=truesp1 .DtrEnable=truesp1 .读取超时=3000
//控件checkforillegalcrosthreadcalls=false;
//表示将处理系统10 . IO。港口。串行端口对象的数据接收事件的方法。
sp1 .数据接收=新系统10 . IO。港口。串行datareceivedeventhandler(SP1 _数据接收_ 1);
//打开串口
sp1 .open();
消息框.显示(“COM1打开成功!');
}
接住(例外ex)
{
消息框.显示(“COM1打开失败!');
}
}
其他
{
消息框.显示(“COM1打开成功!');
}
}
私有空的按钮3 _单击(对象发送方,EventArgs e)
{
如果(sp1 .IsOpen)
{
sp1 .close();
消息框.显示(“COM1关闭成功!');
}
}
私有空的按钮5 _单击(对象发送方,EventArgs e)
{
如果(!sp1 .IsOpen)
{
尝试
{
//串口号
sp1 .PortName=' COM2
//波特率
sp1 .波德拉特=115200;
//数据位
sp1 .数据位数=8;
//停止位
sp1 .停止位=停止位。一;
//奇偶校验位
sp1 .平价=平价。甚至;
sp1 .ReceivedBytesThreshold=1;
sp1 .RtsEnable=truesp1 .DtrEnable=truesp1 .读取超时=3000
控制checkforillegalcrosthreadcalls=false;
//表示将处理系统10 . IO。港口。串行端口对象的数据接收事件的方法。
sp1 .数据接收=新系统10 . IO。港口。串行datareceivedeventhandler(SP1 _数据接收_ 1);
//打开串口
sp1 .open();
消息框.显示(“COM2打开成功!');
}
接住(例外ex)
{
消息框.显示(“COM2打开失败!');
}
}
其他
{
消息框.显示(“COM2打开成功!');
}
}
私有空的按钮4 _点击(对象发送方,EventArgs e)
{
如果(sp1 .IsOpen)
{
sp1 .close();
消息框.显示(“COM2关闭成功!');
}
}
}
}
到此这篇关于c#模拟串口通信串行端口的实现示例的文章就介绍到这了,更多相关c#模
郑重声明:本文由网友发布,不代表盛行IT的观点,版权归原作者所有,仅为传播更多信息之目的,如有侵权请联系,我们将第一时间修改或删除,多谢。