树莓派.Net Core Iot入门系列篇(4):UART串口通信

2,742次阅读
没有评论

前言

和上一篇中的I2C一样,UART也是一种非常常见通信方式。UART全称为通用异步收发传输器(Universal Asynchronous Receiver/Transmitter)。UART用于异步通信,该总线双向通信,可以实现全双工传输和接收。在嵌入式设计中,UART用于主机与辅助设备通信,如汽车音响与外接AP之间的通信,与PC机通信包括与监控调试器和其它器件,如EEPROM通信。

树莓派串口配置

从树莓派3代开始,树莓派默认将 ttyAMA0 分配给了蓝牙,直接导致了没法使用GPIO硬件串口,而GPIO硬件串口的性能优势是没办法替代的。所以我们的先把硬件串口空出来,留给编写的程序使用。当然,鱼与熊掌不可兼得,开启硬件串口后,蓝牙将无法使用。

(1)激活串口功能

sudo nano /boot/config.txt

修改参数:enable_uart=1。 若无此参数,则在最后一行添加:enable_uart=1

然后重启。

此时查看串口设备是这样的。

ls -l /dev/ser*

结果如下:

lrwxrwxrwx 1 root root 7 Aug 28 07:41 serial0 -> ttyS0 lrwxrwxrwx 1 root root 5 Aug 28 07:41 serial1 -> ttyAMA0

(2)禁用串口控制台功能

sudo raspi-config

选择Interfacing Options->P6 Serial,按照提示关闭串口

Would you like a login shell to be accessible over serial? –No Would you like the serial port hardware to be enabled? –Yes

退出,然后重启。

(3)交换串口

sudo nano /boot/config.txt

在最下面添加:dtoverlay=pi3-miniuart-bt 保存并重启。 此时查看串口别名则发现:

lrwxrwxrwx 1 root root 7 Aug 28 07:41 serial0 -> ttyAMA0 lrwxrwxrwx 1 root root 5 Aug 28 07:41 serial1 -> ttyS0

此时,ttyAMA0串口可以正常用于串口通信,ttyS0则无法被用于串口通信,蓝牙功能失效。

硬件连接

我用了一对无线串口透传模块,一个连接在电脑上面,一个连接在树莓派上面(相当于无线串口调试器)来进行调试。

树莓派.Net

在树莓派上面,RX(GPIO15)接调试模块TX,TX(GPIO14)接调试模块RX。

树莓派.Net
接线示例
树莓派.Net
树莓派GPIO

编写程序

C#操作串口需要用到类库System.IO.Ports,创建好控制台应用程序后,通过Nuget添加引用即可。通过System.IO.Ports编写少量代码就能完成串口信息的收发。

在串口控制台应用当中,我们要用到SerialPort类,此类中封装了大量的串口通信相关的方法。一般来说,用到的无非就是读和写操作的相关方法。下面直接贴上示例代码,接收数据通过DataReceived事件,避免了建立一个线程来专门读取数据。

class Program
{
    /// <summary>
    /// 树莓派串口操作,也可以用于Windows系统(COMx)
    /// </summary>
    /// <param name="args"></param>
    static void Main(string[] args)
        {
            //注册退出事件
            Console.CancelKeyPress += (object sender, ConsoleCancelEventArgs eventArgs) => { };

            string portName = "ttyAMA0";
            try
            {
                //查询系统中支持的串口列表
                var ports = SerialPort.GetPortNames();
                bool isTTY = false;
                if (ports.Length == 0)
                {
                    Console.WriteLine($"No serial port allow to use!");
                    return;
                }
                Console.WriteLine("Serial List:");
                foreach (var prt in ports)
                {
                    Console.WriteLine($"  {prt}");
                    if (prt.Contains(portName))
                        isTTY = true;
                }
                if (!isTTY)
                {
                    Console.WriteLine($"No {portName} serial port!");
                    return;
                }
                //Linux加上/dev
                if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
                {
                    portName = $"/dev/{portName}";
                }
                //开始使用串口
                using SerialPort serial = new SerialPort(portName, 115200);
                serial.DataReceived += DataReceived;
                serial.Encoding = Encoding.UTF8;
                serial.Open();
                if (serial.IsOpen)
                {
                    Console.WriteLine($"Port {portName} has opened!");
                }
                else
                {
                    Console.WriteLine($"Port {portName} cannot open!");
                    return;
                }
                while (true)
                {
                    //读取输入的数据,然后发送
                    string input = Console.ReadLine();
                    if (string.IsNullOrWhiteSpace(input))
                    {
                        continue;
                    }
                    serial.Write(input);
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
            }
        }

    private static void DataReceived(object sender, SerialDataReceivedEventArgs e)
    {
        try
        {
            if (!(sender is SerialPort))
            {
                return;
            }
            SerialPort serial = sender as SerialPort;
            string read = serial.ReadExisting();
            Console.WriteLine("-->" + read);
        }
        catch { }
    }
}

调试运行

在树莓派和计算机中分别运行程序。树莓派中运行需要将portName修改为ttyAMA0,电脑(Windows)中运行需要将portName修改COMx,x为对于的串口数字。

运行截图如下:

树莓派.Net
运行截图

参考资料

(1)树莓派UART说明 (2)https://www.jianshu.com/p/26409ddf6a9b (3)System.IO.Ports Namespace

afirefish
版权声明:本站原创文章,由afirefish2019-09-24发表,共计2754字。
转载提示:除特殊说明外本站文章皆由CC-4.0协议发布,转载请注明出处。
评论(没有评论)
载入中...