串口学习笔记
简介
串口学习笔记
一、什么是串口
串口通信(Serial Communication),是一种用于在计算机和外部设备之间传输数据的通信方式。它使用串行数据传输的方式,通过计算机的串口与外部设备进行数据交换。串口通信常用于连接各种设备,例如打印机、调制解调器、传感器等。它通过逐位传输数据,可以实现可靠的数据传输和通信。
二、常用的串口通信方式主要包括以下几种
RS-232:
RS-232是一种常见的串口通信标准,用于在计算机和外部设备之间传输数据。它使用DB-9或DB-25连接器,支持较短距离的数据传输。
RS-485:
RS-485是一种多点通信协议,可以实现多个设备之间的串口通信。它支持较长距离的数据传输,通常用于工业控制系统和远程监控等领域。
USB串口:
USB串口是通过USB接口进行串口通信的方式。它广泛应用于各种外部设备,如打印机、调制解调器、数码相机等。
TTL串口:
TTL串口是一种基于TTL电平的串口通信方式,常用于嵌入式系统和单片机开发中。
三、串口怎样通信
串口通信的基本原理是通过发送和接收数据位来实现。下面是串口通信的基本步骤:
确定串口参数:首先需要确定串口的参数,包括波特率(Baud Rate)、数据位(Data Bits)、停止位(Stop Bits)和校验位(Parity)等。这些参数需要在发送和接收端保持一致。
以下是一些常见的串口参数定义方式:
- 波特率(Baud Rate):指的是每秒传输的比特数。常见的波特率有9600、115200等。发送和接收数据的设备必须使用相同 的波特率才能正常通信。
- 数据位(Data Bits):指的是每个数据字节中所使用的位数。常见的数据位有5、6、7、8位。
- 停止位(Stop Bits):指的是每个数据字节之后的停止位数。常见的停止位有1位和2位。
- 校验位(Parity Bit):用于数据传输的错误检测。常见的校验位有无校验位、奇校验位和偶校验位。
串口参数的定义可以根据具体的应用需求进行配置,以确保设备之间的串口通信正常进行。
打开串口:在计算机或设备上,需要打开串口以进行通信。这可以通过编程语言或串口通信工具实现。
在C#中,你可以使用
System.IO.Ports
命名空间提供的SerialPort
类来打开和操作串口。下面是使用C#打开232和485串口的示例代码:打开232串口:
using System.IO.Ports; // 创建SerialPort对象 SerialPort serialPort = new SerialPort("COM1", 9600, Parity.None, 8, StopBits.One); // 打开串口 serialPort.Open(); // 串口打开后,可以进行数据的读取和写入操作 // 关闭串口 serialPort.Close();
打开485串口:
using System.IO.Ports; // 创建SerialPort对象 SerialPort serialPort = new SerialPort("COM1", 9600, Parity.None, 8, StopBits.One); // 设置485串口为半双工模式 serialPort.RtsEnable = true; serialPort.DtrEnable = false; // 打开串口 serialPort.Open(); // 串口打开后,可以进行数据的读取和写入操作 // 关闭串口 serialPort.Close();
请注意,上述代码中的参数值可能需要根据你的具体需求进行调整。同时,确保在使用完串口后及时关闭串口以释放资源。
点此查看SerialPort类说明:
发送数据:在发送端,将要发送的数据转化为二进制形式,并按照串口参数进行传输。通常是按照字节(8位)的形式发送数据。
// 要发送的数据 string data = "Hello, World!"; // 将数据转换为ASCII码 byte[] asciiBytes = System.Text.Encoding.ASCII.GetBytes(data); // 发送数据 serialPort.Write(asciiBytes, 0, asciiBytes.Length);
接收数据:在接收端,通过串口接收器接收数据,并将其转化为可读形式。接收端需要按照相同的串口参数配置进行接收。
// 设置接收事件处理程序 serialPort.DataReceived += SerialPort_DataReceived; private static void SerialPort_DataReceived(object sender, SerialDataReceivedEventArgs e) { SerialPort serialPort = (SerialPort)sender; // 读取接收缓冲区中的所有可用字节 byte[] buffer = new byte[serialPort.BytesToRead]; serialPort.Read(buffer, 0, buffer.Length); // 将接收到的字节数组转换为字符串 string receivedData = System.Text.Encoding.ASCII.GetString(buffer); }
数据校验:为了确保数据的完整性和准确性,可以使用校验位进行数据校验。常见的校验方式包括奇偶校验和循环冗余校验(CRC)等。
private static void SerialPort_DataReceived(object sender, SerialDataReceivedEventArgs e) { SerialPort serialPort = (SerialPort)sender; // 读取接收缓冲区中的所有可用字节 byte[] buffer = new byte[serialPort.BytesToRead]; serialPort.Read(buffer, 0, buffer.Length); // 按照串口参数规则与8位校验校验数据 if (buffer.Length == serialPort.DataBits / 8 + 1) { // 校验停止位 if (serialPort.StopBits == StopBits.One && buffer[buffer.Length - 1] != 0x00) { Console.WriteLine("停止位校验失败"); return; } else if (serialPort.StopBits == StopBits.Two && buffer[buffer.Length - 1] != 0xFF) { Console.WriteLine("停止位校验失败"); return; } // 校验奇偶校验位 if (serialPort.Parity == Parity.None) { // 无奇偶校验位,直接输出数据 Console.WriteLine("数据校验通过:" + BitConverter.ToString(buffer)); } else if (serialPort.Parity == Parity.Even) { // 偶校验 int parityBit = buffer[buffer.Length - 1]; int dataBits = serialPort.DataBits; bool isEvenParity = IsEvenParity(buffer, dataBits); if (isEvenParity && parityBit == 0x00) { Console.WriteLine("数据校验通过:" + BitConverter.ToString(buffer)); } else { Console.WriteLine("奇偶校验位校验失败"); } } else if (serialPort.Parity == Parity.Odd) { // 奇校验 int parityBit = buffer[buffer.Length - 1]; int dataBits = serialPort.DataBits; bool isOddParity = IsOddParity(buffer, dataBits); if (isOddParity && parityBit == 0x00) { Console.WriteLine("数据校验通过:" + BitConverter.ToString(buffer)); } else { Console.WriteLine("奇偶校验位校验失败"); } } } else { Console.WriteLine("数据长度校验失败"); } } private static bool IsEvenParity(byte[] data, int dataBits) { int count = 0; for (int i = 0; i < data.Length - 1; i++) { byte b = data[i]; while (b != 0) { count++; b &= (byte)(b - 1); } } return count % 2 == 0; } private static bool IsOddParity(byte[] data, int dataBits) { return !IsEvenParity(data, dataBits); }
数据处理:接收到数据后,可以根据需求进行相应的数据处理,如解析数据、执行相应的操作等。
void com_DataReceived(object sender, SerialDataReceivedEventArgs e) { // 使用二进制或字符串技术(但不能同时使用两者) // 缓冲和处理二进制数据 while (com.BytesToRead > 0) bBuffer.Add((byte)com.ReadByte()); ProcessBuffer(bBuffer); // 缓冲区字符串数据 sBuffer += com.ReadExisting(); ProcessBuffer(sBuffer); } private void ProcessBuffer(string sBuffer) { // 在字符串中查找有用信息 // 然后从缓冲区中删除有用的数据 } private void ProcessBuffer(List<byte> bBuffer) { // 在字节数组中查找有用的信息 // 然后从缓冲区中删除有用的数据 }
关闭串口:通信完成后,需要关闭串口以释放资源。
需要注意的是,串口通信需要发送端和接收端的串口参数保持一致,否则数据可能无法正确传输。同时,串口通信的稳定性和可靠性较差,对于长距离通信或高速通信,可能需要使用更可靠的通信方式。
参考资料
串口RS232和RS485
串口通信校验方式:奇偶校验、累加和校验
C#实现串口通信解析
C#实现串口通信的上位机开发