【YFIOs】用C#开发硬件之串口通信

YFIOs文档源链接:https://docs.yfios.net/docs/sdk/yfesp32s3-sdk/serial-communication

概述

串口通信是嵌入式系统中最常用的数据传输方式之一。YF3300-ESP32S3 开发板提供了 2 个串口:RS232 和 RS485,用于与外部设备进行数据通信。本章节将介绍如何使用 nanoFramework 进行串口编程。

所需 NuGet 包

在 nanoFramework 项目中使用串口需要引用以下包:

包名 说明
nanoFramework.CoreLibrary 基础类库(通常自动包含)
nanoFramework.System.IO.Ports 串口操作核心库
nanoFramework.Hardware.Esp32 ESP32 硬件配置库(用于引脚映射)

注意 :串口通信不需要 引用 nanoFramework.System.Device.Gpio 库。引脚映射通过 nanoFramework.Hardware.Esp32.Configuration.SetPinFunction() 完成,而非 GPIO 控制器。

核心概念

SerialPort 类

SerialPort 是 nanoFramework 中串口操作的核心类,主要属性和方法:

硬件连接说明

YF3300-ESP32S3 开发板提供 2 个串口

串口类型 端口名 TX 引脚 RX 引脚 默认波特率
RS232 COM2 GPIO11 GPIO12 9600
RS485 COM1 GPIO9 GPIO10 9600

串口使用示例

YF3300_ESP32S3.cs

csharp 复制代码
using System;

namespace YFSoft.Hardware.YF3300_ESP32S3
{
    public static class CPU
    {
        public static class Pins
        {
            public const int GPIO9 = 9;
            public const int GPIO10 = 10;
            public const int GPIO11 = 11;
            public const int GPIO12 = 12;
        }
    }

    public static class Mainboard
    {
        // RS485 串口定义
        public static class RS485
        {
            public const string PortName = "COM1";
            public const int DefaultBaudRate = 9600;
            public const int TxPin = CPU.Pins.GPIO9;        // UART1 TX (电路图: TX1=IO9)
            public const int RxPin = CPU.Pins.GPIO10;       // UART1 RX (电路图: RX1=IO10)
        }

        // RS232 串口定义
        public static class RS232
        {
            public const string PortName = "COM2";
            public const int DefaultBaudRate = 9600;
            public const int TxPin = CPU.Pins.GPIO11;       // UART2 TX (电路图: TX2=IO11)
            public const int RxPin = CPU.Pins.GPIO12;       // UART2 RX (电路图: RX2=IO12)
        }
    }
}

Program.cs

csharp 复制代码
using System;
using System.Diagnostics;
using System.Text;
using System.Threading;
using System.IO.Ports;
using YFSoft.Hardware.YF3300_ESP32S3;
using nanoFramework.Hardware.Esp32;

namespace SerialPortTest
{
    public class Program
    {
        // 串口实例
        private static SerialPort _rs232Port;
        private static SerialPort _rs485Port;

        public static void Main()
        {
            Debug.WriteLine("YF3300-ESP32S3 串口测试程序启动");

            try
            {
                // 初始化 RS232
                InitializeRS232();

                // 初始化 RS485
                InitializeRS485();

                // 发送打招呼消息
                SendGreeting();

                // 启动回显线程
                StartEchoLoop();

            }
            catch (Exception ex)
            {
                Debug.WriteLine($"初始化失败: {ex.Message}");
            }

            Thread.Sleep(Timeout.Infinite);
        }

        // 初始化 RS232 串口
        private static void InitializeRS232()
        {
            Debug.WriteLine($"配置 RS232 引脚: Tx={Mainboard.RS232.TxPin}, Rx={Mainboard.RS232.RxPin}");
            
            // 配置 RS232 串口引脚映射 (COM2)
            // 在创建 SerialPort 实例之前配置引脚
            Configuration.SetPinFunction(Mainboard.RS232.TxPin, DeviceFunction.COM2_TX);
            Configuration.SetPinFunction(Mainboard.RS232.RxPin, DeviceFunction.COM2_RX);

            Debug.WriteLine("创建 RS232 SerialPort 实例...");
            _rs232Port = new SerialPort(
                Mainboard.RS232.PortName,
                Mainboard.RS232.DefaultBaudRate,
                Parity.None,
                8,
                StopBits.One);

            Debug.WriteLine("打开 RS232 串口...");
            _rs232Port.Open();
            Debug.WriteLine($"RS232 已初始化: {Mainboard.RS232.PortName} @ {Mainboard.RS232.DefaultBaudRate}");
        }

        // 初始化 RS485 串口
        private static void InitializeRS485()
        {
            Debug.WriteLine($"配置 RS485 引脚: Tx={Mainboard.RS485.TxPin}, Rx={Mainboard.RS485.RxPin}");
            
            // 配置 RS485 串口引脚映射 (COM1)
            // 在创建 SerialPort 实例之前配置引脚
            Configuration.SetPinFunction(Mainboard.RS485.TxPin, DeviceFunction.COM1_TX);
            Configuration.SetPinFunction(Mainboard.RS485.RxPin, DeviceFunction.COM1_RX);

            Debug.WriteLine("创建 RS485 SerialPort 实例...");
            _rs485Port = new SerialPort(
                Mainboard.RS485.PortName,
                Mainboard.RS485.DefaultBaudRate,
                Parity.None,
                8,
                StopBits.One);

            Debug.WriteLine("打开 RS485 串口...");
            _rs485Port.Open();
            Debug.WriteLine($"RS485 已初始化: {Mainboard.RS485.PortName} @ {Mainboard.RS485.DefaultBaudRate}");
        }

        // 发送打招呼消息
        private static void SendGreeting()
        {
            string greeting = "Hello from YF3300-ESP32S3!\r\n";
            byte[] data = Encoding.UTF8.GetBytes(greeting);

            // RS232 发送
            _rs232Port.Write(data, 0, data.Length);
            Debug.WriteLine("RS232 打招呼消息已发送");

            // RS485 发送
            _rs485Port.Write(data, 0, data.Length);
            Debug.WriteLine("RS485 打招呼消息已发送");
        }


        // 启动回显循环
        private static void StartEchoLoop()
        {
            Debug.WriteLine("进入回显模式...");
            Debug.WriteLine("RS232 和 RS485 会回显收到的所有数据");

            // 启动 RS232 回显线程
            new Thread(RS232EchoLoop).Start();

            // 启动 RS485 回显线程
            new Thread(RS485EchoLoop).Start();
        }

        // RS232 回显循环
        private static void RS232EchoLoop()
        {
            byte[] buffer = new byte[256];
            Debug.WriteLine("RS232 回显线程已启动");

            while (true)
            {
                try
                {
                    int bytesAvailable = _rs232Port.BytesToRead;
                    
                    if (bytesAvailable > 0)
                    {
                        Debug.WriteLine($"RS232 有 {bytesAvailable} 字节待读取");
                        int bytesRead = _rs232Port.Read(buffer, 0, bytesAvailable);

                        if (bytesRead > 0)
                        {
                            // 回显数据
                            _rs232Port.Write(buffer, 0, bytesRead);

                            // 输出调试信息
                           string received = Encoding.UTF8.GetString(buffer, 0, bytesRead);
                           Debug.WriteLine($"RS232 收到 {bytesRead} 字节: {received}");
                        }
                    }

                    Thread.Sleep(10);
                }
                catch (Exception ex)
                {
                    Debug.WriteLine($"RS232 回显错误: {ex.Message}");
                }
            }
        }

        // RS485 回显循环
        private static void RS485EchoLoop()
        {
            byte[] buffer = new byte[256];
            Debug.WriteLine("RS485 回显线程已启动");

            while (true)
            {
                try
                {
                    int bytesAvailable = _rs485Port.BytesToRead;
                    
                    if (bytesAvailable > 0)
                    {
                        Debug.WriteLine($"RS485 有 {bytesAvailable} 字节待读取");
                        int bytesRead = _rs485Port.Read(buffer, 0, bytesAvailable);

                        if (bytesRead > 0)
                        {
                            // 回显数据(自动流向控制,无需手动切换)
                            _rs485Port.Write(buffer, 0, bytesRead);

                            // 输出调试信息
                           string received = Encoding.UTF8.GetString(buffer, 0, bytesRead);
                            Debug.WriteLine($"RS485 收到 {bytesRead} 字节: {received}");
                        }
                    }

                    Thread.Sleep(10);
                }
                catch (Exception ex)
                {
                    Debug.WriteLine($"RS485 回显错误: {ex.Message}");
                }
            }
        }
    }
}
相关推荐
Data_Journal9 小时前
如何将网页抓取用于机器学习
大数据·开发语言·数据库·python·scrapy
郝学胜-神的一滴9 小时前
Effective Python 条款 13:善用星号解包,告别下标切片拆分的坑
服务器·开发语言·数据结构·python·程序人生·pycharm
一水鉴天9 小时前
词、术语、概念:从特征集收束到统一拓扑变换的升格与降格模型 20260915(豆包)
开发语言·人工智能
weixin_3077791310 小时前
C++代码实现MATLAB中的ode45函数功能
开发语言·c++·算法·matlab
是立不是利10 小时前
大文件导致请求被拒的连锁反应
开发语言·前端·javascript
野生技术架构师11 小时前
1200 道 JAVA 面试题(各大企业常见面试题及答案)
java·开发语言
鱼听禅11 小时前
C# 学习笔记-使用 类型化客户端搭建HTTP客户端服务
学习·http·c#·工厂方法模式
“AI国潮设计-小江”11 小时前
【Python/SDXL实战】潮汕国潮IP视觉落地:普宁美食猫IP & 创意甜品设计(附ComfyUI工作流思路)
开发语言·人工智能·python·prompt·aigc
Yyyyyy~11 小时前
【java】类和对象
java·开发语言