串口通讯协议——SerialPort详解
串行通信作为计算机通信方式之一,主要起到主机与外设以及主机之间的数据传输作用,串行通信具有传输线少、成本低的特点,主要适用于近距离的人-机交换、实时监控等系统通信工作当中,借助于现有的电话网也能实现远距离传输,因此串行通信接口是计算机系统当中的常用接口。SerialPort是一个串口传输的一个非常方便的控件,对从事上位机测试的人是一个很好的控件,很多做嵌入式开发的人,他们的大部分界面都是用C#写的
目录
串口通讯
串行通信作为计算机通信方式之一,主要起到主机与外设以及主机之间的数据传输作用,串行通信具有传输线少、成本低的特点,主要适用于近距离的人-机交换、实时监控等系统通信工作当中,借助于现有的电话网也能实现远距离传输,因此串行通信接口是计算机系统当中的常用接口。
硬件流控制(RTS/CTS)
RTS/CTS流控制是硬件流控制的一种,需要按下图连线:
串口设备A给串口设备B发送数据。B忙不过来时(B的串口输入缓冲区快满了)会设置自己的RTS为低电平,这样A的CTS也变为低电平。A发现自己的CTS为低电平后,会停止发送数据;B的串口输入缓冲区快空时,会设置自己的RTS为高电平,这样A的CTS也变为高电平。A发现自己的CTS为高电平后,会继续发送数据。
相同的道理,DTR/DSR也可以做硬件流控制。
为什么打开串口时需要设置DTR、RTS为高电平呢?原因就在于:如果对方设置了硬件流控制,而这边的DTR、RTS为低电平,那么对方就不会给这边发送数据。
SerialPort的使用
SerialPort是一个串口传输的一个非常方便的控件,对从事上位机测试的人是一个很好的控件,很多做嵌入式开发的人,他们的大部分界面都是用C#写的,难免会用到这个控件
SerialPort常用属性
PortName | 获取或设置通信端口,包括但不限于所有可用的 COM 端口(设置使用哪个串口) |
BaudRate | 设置或获取波特率 |
StopBits | 设置或获取数据停止位 |
DataBits | 设置或获取数据位 |
Parity | 获取或设置奇偶校验检查协议 |
BytesToRead | 获取缓冲区中读到数据的长度 |
ReadTimeout | 或者或设置读取操作的超时时间 |
WriteTimeout | 或者或设置写入操作的超时时间 |
SerialPort常用方法
public static string[] GetPortNames | 获取当前计算机的串行端口名的数组。 |
Open | 开串口连接 |
Close | 关闭串口连接 |
Read | 从 SerialPort 输入缓冲区中读取数据 |
Write | 向 SerialPort 写入数据 |
Open` 打开串口连接打开后一般要设置`DtrEnable、RtsEnable`为true,具体原因见下文
xxx.Open();
xxx.DtrEnable = true;
xxx.RtsEnable = true;
SerialPort事件
DataReceived | 指示已通过由 SerialPort 对象表示的端口接收了数据。 |
ErrorReceived | 指示由 SerialPort 对象表示的端口上发生了错误。 |
创建SerialPort对象以及配置参数
方式一
通过对应的属性进行配置
private SerialPort serialPort = new SerialPort();
public SerialPortExample()
{
serialPort.PortName = "COM3"; // 设置串口名称
serialPort.BaudRate = 9600; // 设置波特率
serialPort.Parity = Parity.None; // 设置奇偶校验
serialPort.DataBits = 8; // 设置数据位数
serialPort.StopBits = StopBits.One; // 设置停止位
serialPort.Handshake = Handshake.None; // 设置握手协议
serialPort.DataReceived += new SerialDataReceivedEventHandler(DataReceivedHandler); // 接收到数据时的事件
}
方式二
通过构造函数进行配置
SerialPort port = new SerialPort("COM2",9600,Parity.None,8,(StopBits)1);
SerialPort实现串口通信完整例子
public partial class Form1 : Form
{
// 创建一个全局的串口对象
readonly SerialPort port = new SerialPort();
public Form1()
{
InitializeComponent();
// 对串口添加一下配置
// 单位是bit/s,常见的波特率1s是9600bit,1Byte是8bit 9600bit/8 = 1200字节,也就是1s发送1200个字节
// 注意波特率不能太大 也不能太小,如果太大了传输的数据不稳定,如果俩端的波特率不一致会导致数据不一致,如果太小了反应太慢
port.BaudRate = 9600; // 设置波特率
// 2 StopBits停止位
// StopBits是一个枚举类型,可选择有1位,1.5位,2位,默认值是1位
port.StopBits = StopBits.One;
// 3 DataBits 数据位: 通信中真正的有效信息,数据位可以双方通过约定进行控制 一般可以5、6/7/8
// 默认值是8位
port.DataBits = 8;
// 4 Parity 奇数校检位 只占1位,指定是逻辑高位是奇数或者偶数个,高位就是1,地位就是0
// 可取值有Parity.None 不采用校检
// Parity.Odd 奇数校检,保证传输过程汇总高位个数是奇数个
// Parity.Even 偶数校检,保证传输过程中高位个数是偶数个
port.Parity = Parity.None;
// 5 PortName设置连接串口名
port.PortName = "COM1";
// 6 Encoding 编码格式,设置显示以什么格式显示
// 默认16进制格式
port.Encoding = Encoding.Default;
// 必须配置的 波特率 和 设置串口
// 11 接收数据的事件
port.DataReceived += Port_DataReceived;
}
bool isDefault = true; // 代表编码方式 true代表默认编码
/// <summary>
/// 接收数据的事件
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void Port_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
// 接收数据并且显示,
// 13 port.BytesToRead 从缓存区读取数据的长度
byte[] bs = new byte[port.BytesToRead];
// 14 Read 从缓存区读取数据
port.Read(bs, 0, bs.Length);
string value = null;
// 以哪种编码方式展示数据
this.Invoke((EventHandler)delegate
{
if (isDefault)
{
// 十六进制
foreach (var b in bs)
{
value += " " + b.ToString("X"); //X代表16进制
}
}
else
{
// GetEncoding("gb2312") 国标2312编码格式
value = Encoding.GetEncoding("gb2312").GetString(bs);
}
this.richTextBox1.AppendText(value+"\r\n");
this.richTextBox1.ScrollToCaret();
// DiscardInBuffer 清空缓存区
port.DiscardInBuffer(); // 清空缓存区
});
}
/// <summary>
/// 打开串口
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void button1_Click(object sender, EventArgs e)
{
// 7 IsOpen 当前串口是否是打开状态,
// true 为打开状态
// false 关闭状态
if (!port.IsOpen) // 没打开
{
// 8 打开串口
port.Open();
// 9 打开之后 要设置一下俩个属性为true
// DtrEnable 为true,启用数据终端就绪,发送一个dtr信号。
port.DtrEnable = true;
// RtsEnable 为true,证明请求可以发送了,发送一个rts信号
port.RtsEnable = true;
button1.Text = "关闭";
}
else
{
button1.Text = "打开";
// 10 关闭串口
port.Close();
}
}
/// <summary>
/// 发送数据
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void button3_Click(object sender, EventArgs e)
{
byte[] bs = Encoding.UTF32.GetBytes(this.textBox1.Text);
// 12 Write 发送数据
port.Write(bs,0,bs.Length);
}
/// <summary>
/// 检测串口
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void DetectionSerialButton_Click(object sender, EventArgs e)
{
// 获取电脑下所有串口端口
SerialList = System.IO.Ports.SerialPort.GetPortNames();
if (SerialList.Length!=0)
{
this.SerialComboBox.DataSource = SerialList;
this.SerialComboBox.SelectedIndex = 0;
}
else
{
MessageBox.Show("未获取到串口!!!","提示",MessageBoxButtons.OK,MessageBoxIcon.Warning);
}
}
}
本文部分借鉴网络,如有侵权请联系删除!!!
开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!
更多推荐
所有评论(0)