本篇效果展示:
https://jhou-bucket.oss-cn-shanghai.aliyuncs.com/2019-10-18%20%E5%A3%81%E8%99%8E%E6%B5%8B%E8%AF%84/2019-10-30%20RS485/demo.mp4
曾在第一篇开箱中简要分析过壁虎的外设。在最下侧,配备有1路485,2路继电器和一路韦根。
我已经实现了2路继电器的控制,本篇将进行RS485的串口通讯测试。
首先是物理操作
这里我用到一个USB转485的转接模块,通过接上2根跳线
然后两根跳线跳到壁虎的接线端.接的时候注意AB序
然后基本上就是代码啦。
简单总结一下本篇遇到的问题
Xamarin工程下,对安卓的串口控制属于是安卓系统的特性,无法在.net standard项目,也就是xamarin.forms中去添加。
我的解决方案是:
在安卓工程下,制造主程序入口.然后通过Tab切换通用页和特性页
修改MainActivity,以使得安卓应用入口的Page为TabPage
protected override void OnCreate(Bundle savedInstanceState)
{
TabLayoutResource = Resource.Layout.Tabbar;
ToolbarResource = Resource.Layout.Toolbar;
base.OnCreate(savedInstanceState);
global::Xamarin.Forms.Forms.Init(this, savedInstanceState);
//主要修改在这
var app = new App();
app.MainPage = new TabPage();
LoadApplication(app);
}
TabPage主要就做了2页,第一页叫常规测试,包含了灯光和继电器控制(因为都是FILE IO操作)。第二页叫特殊测试(包含了安卓系统操作串口的操作器):
private void Button_Clicked(object sender, EventArgs e)
{
Container.Children.Clear();
Container.Children.Add(new MainPage());
}
private void Button_Clicked_1(object sender, EventArgs e)
{
Container.Children.Clear();
Container.Children.Add(new SerialView());
}
那本篇的重点就变成了:
如何在xamarin项目中使用安卓串口进行通讯!
up主强烈推荐nuget库:Xamarin.Android.SerialPort
该库依赖于monoAndroid,所以一定要在安卓项目下。
这里我新建了一个安卓类库(GoJhou.Gekko.Android.UART)
然后引入了该nuget库。封装了SerialController如下:
public class MessageEventArgs : EventArgs
{
public readonly string Message;
public MessageEventArgs(string msg)
{
Message = msg;
}
}
public class SerialController: BaseController
{
private SerialPort.SerialPortWrapper.SerialPort sp;
public delegate void OnMessageReceivedEventHandler(MessageEventArgs e);
public event OnMessageReceivedEventHandler MessageReceived;
private string Message=string.Empty;
public SerialController()
{
sp = new SerialPort.SerialPortWrapper.SerialPort("/dev/ttyS4", 9600, Stopbits.One, Parity.None, ByteSize.EightBits, FlowControl.None, Timeout.SimpleTimeout(-1));
sp.StartReceive();
sp.Flush();
sp.OnReceived += Sp_OnReceived;
}
public void SendMessage(string msg)
{
sp.WriteLine(msg);
sp.FlushOutput();
}
private void Sp_OnReceived(object sender, SerialPort.SerialPortWrapper.SerialPortEventArgs e)
{
var sp = sender as SerialPort.SerialPortWrapper.SerialPort;
string message = Encoding.UTF8.GetString(e.Data);
Message += message;
if(Message.Contains("|"))
{
var command = Message.Split('|');
Message = command[1];
string msg = command[0];
MessageReceived?.Invoke(new MessageEventArgs(msg));
}
}
}
由于研究不透彻,我发现这个库的OnReceived回调不稳定,接收字符长度有波动。只好手动定义了一个命令分隔符’|'来表示一个命令的正式结束。然后自己重新暴露一个MessageReceived的事件表示一个完整的消息。
有了操作类,其他基本上就和之前的一样啦!
在Android项目下新建一个View文件夹,负责放各种内容视图
SerialView:
[XamlCompilation(XamlCompilationOptions.Compile)]
public partial class SerialView : ContentView
{
public SerialController SerialPortController => SerialController.Instance;
private string sendMessage;
public string SendMessage
{
get => sendMessage; set
{
sendMessage = value;
OnPropertyChanged();
}
}
private string receivedMessage;
public string ReceivedMessage
{
get => receivedMessage; set
{
receivedMessage = value;
OnPropertyChanged();
}
}
public Command SendCommand
{
get => new Command(new Action(() =>
{
SerialPortController.SendMessage(SendMessage);
//SendMessage = string.Empty;
}));
}
public SerialView()
{
InitializeComponent();
SerialPortController.MessageReceived += (s) =>
{
ReceivedMessage +="|"+ s.Message;
};
}
}
最后算是实现了壁虎的RS485通讯测试。
ps:up主第一次触摸到xamarin项目,本篇写的着实有些凌乱,可能不符合xamarin的设计模式。希望up主会再接再厉,在后面的章节中完善他们。
感谢支持!