C#与Arduino字节串口通信异常及3字节双向收发实现求助
问题分析与解决方案
核心问题原因
你看到的5650是因为Arduino代码里用了Serial.print(data)——这个函数会把字节的十进制数值转换成ASCII字符串发送。比如你发送的0x52是十进制82,Serial.print(82)会输出字符'8'(ASCII码0x38,十进制56)和'2'(ASCII码0x32,十进制50),C#端收到这两个字节后直接拼接,就显示成了5650。
要发送原始字节,必须用Serial.write()替代Serial.print()。
修正后的代码实现
Arduino 代码(支持3字节双向收发)
void setup() { Serial.begin(9600); // 等待USB串口连接完成 while (!Serial); } void loop() { // 检查是否收到完整的3字节数据 if (Serial.available() >= 3) { byte buffer[3]; // 一次性读取3字节 Serial.readBytes(buffer, 3); // 直接回发收到的3字节,也可根据需求修改后再发送 Serial.write(buffer, 3); // 可选延迟,避免数据堆积,按需调整 delay(100); } }
C# WinForm 代码(完整实现3字节收发)
前提:窗体已添加SerialPort控件(命名serialPort1,提前配置好端口号、波特率9600等参数)、发送按钮、RichTextBox用于显示数据。
发送按钮点击事件
private void button1_Click(object sender, EventArgs e) { // 构造3字节发送数据,示例为0x52、0x1A、0x0F byte[] sendData = new byte[] { 0x52, 0x1A, 0x0F }; if (serialPort1.IsOpen) { serialPort1.Write(sendData, 0, sendData.Length); } }
串口数据接收事件
private void serialPort1_DataReceived(object sender, System.IO.Ports.SerialDataReceivedEventArgs e) { // 等待足够的3字节数据再读取,避免粘包 if (serialPort1.BytesToRead >= 3) { byte[] receiveData = new byte[3]; serialPort1.Read(receiveData, 0, 3); // 跨线程更新UI,将字节转为十六进制字符串显示(更直观) this.Invoke(new Action(() => { string hexStr = BitConverter.ToString(receiveData).Replace("-", " "); richTextBox1.Text += $"收到:{hexStr}\r\n"; // 若要显示十进制值,替换为: // string decStr = string.Join(" ", receiveData); // richTextBox1.Text += $"收到:{decStr}\r\n"; })); } }
额外注意事项
- 确保C#端
SerialPort的参数(波特率、数据位、停止位、奇偶校验)与Arduino完全一致,默认配置为9600波特率、8数据位、1停止位、无校验。 - 固定长度收发(如3字节)是避免串口粘包的可靠方案,接收时必须等待足够字节数再读取。
- 若需调试,可在两端分别打印收发的原始字节值,定位数据传输问题。
内容的提问来源于stack exchange,提问作者Rehan Faisal
相关产品推荐
相关产品推荐

