前言
和上一篇中的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则无法被用于串口通信,蓝牙功能失效。
硬件连接
我用了一对无线串口透传模块,一个连接在电脑上面,一个连接在树莓派上面(相当于无线串口调试器)来进行调试。
在树莓派上面,RX(GPIO15)接调试模块TX,TX(GPIO14)接调试模块RX。
编写程序
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为对于的串口数字。
运行截图如下:
参考资料
(1)树莓派UART说明 (2)https://www.jianshu.com/p/26409ddf6a9b (3)System.IO.Ports Namespace
文章评论