串口上位机和下位机的通信
这个章节会在上一节课的基础上进行修改
1. Form上的修改
和之前相比,主要修改了port_DataReceived 这个函数 将之前直接显示的操作,修改成了显示的同时,也将数据存储到SeriPortDataBuffer 这个缓存空间中,来使用。
C
public Form1()
{
InitializeComponent();
serialPort1.DataReceived += new SerialDataReceivedEventHandler(port_DataReceived); //串口数据接收事件
serialPort1.Encoding = Encoding.GetEncoding("GB2312");
//System.Windows.Forms.Control.CheckForIllegalCrossThreadCalls = false; // //
}
string SeriPortDataBuffer = "";
private void port_DataReceived(object sender, SerialDataReceivedEventArgs e) //串口接收事件
{
string ThisNumber = "";
try {
ThisNumber = serialPort1.ReadExisting();
} catch { }
if (ThisNumber != "") //传递非空数据。
{
SeriPortDataBuffer = SeriPortDataBuffer + ThisNumber;
this.BeginInvoke(new Action(() =>
{
richTextBox2.AppendText(ThisNumber); //串口类会自动处理汉字,所以不需要特别转换
}));
}
}
2. 获取B站粉丝按钮的实现
2.1 获取B站粉丝按键
按下按键后,创建一个新的线程:childThread,线程中启动发送字符的通信
之所以需要新建一个线程是,在通信的时候会因为在处理接收的信息,所以UI界面会卡住,解决方案就是新开一个,在新开的里面去处理。
C
Thread childThread;//发送线程
/// <summary>
/// 获取B站粉丝
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void button5_Click(object sender, EventArgs e)
{
if (childThread != null) { try { childThread.Abort(); } catch { } }
childThread = new Thread(sendthepath);
childThread.Start();
//childThread.Abort();//关进程
}
2.2 sendthepath
在这个sendthepath 函数中实现了指令的发送,以及信息的接收
C
private void sendthepath()
{
byte[] Data = new byte[1]; //单字节发数据
if (serialPort1.IsOpen)
{
//礼貌扫描一下wifi列表
serialPort1.Write("AT+WSCAN\r\n");
ReadAndCheckData("OK", 5);
//输入wifi密码,连接wifi
serialPort1.Write("AT+WJAP=super_2G,123456798\r\n");
ReadAndCheckData("OK", 20);
//输入API,获取粉丝数
serialPort1.Write("AT+HTTTPCLIENTLINE=2,2,\"text/html\",\"api.bilibili.com\",443,\"/x/relation/stat?vmid=2044983862\"\r\n");
ReadAndCheckData("OK", 5);
}
else
{
MessageBox.Show("请打开串口");
}
}
2.3 ReadAndCheckData
这函数实现了,从全局变量“SeriPortDataBuffer”中去读串口的值,判断是否读取到结束标志位“data”,同时也有延时等待的参数,因为只要接收完成就可以结束代码,所以延时可以将时间放长一点,也不会影响代码运行的时间。
C
//时间监控的申明
System.DateTime currentTime = new System.DateTime();
/// <summary>
/// 判断是否有“data”的数据, 超时退出
///备注:有防阻塞功能
/// </summary>
/// <param name="data"> 被判断的数据</param>
/// <param name="delay_S"> 延时时间,单位秒</param>
/// <returns> 如果return true,正常结束,return false 错误或者超时结束</returns>
bool ReadAndCheckData(string data, int delay_S)
{
Debug.WriteLine("进入循环判断");
SeriPortDataBuffer = "";
string SeriPortDataLast = "";
bool EXTFlag = false;
bool SpentFlag = false;
currentTime = System.DateTime.Now;//更新时间
int miao_last = currentTime.Second;//秒
int miao = currentTime.Second;//秒
int shijian = 0;
Debug.WriteLine("循环中...");
//下面的语句有几率崩溃
do
{
currentTime = System.DateTime.Now;//更新时间
miao = currentTime.Second;//秒
shijian = miao - miao_last;
if (shijian >= delay_S)//超时退出
{
Debug.WriteLine("ReadAndCheckData 超时退出 \n");
return false;
}
//因为之前读串口的数据的时候是一行一行读,所以将数据读断的问题应该不大
if (SeriPortDataLast != SeriPortDataBuffer)
{
SeriPortDataLast = SeriPortDataBuffer;
SeriPortDataBuffer = "";
try
{
string[] number= SeriPortDataLast.Split('\n');
foreach (string thsinnu in number)
{
try
{
if (thsinnu.Contains(data))
{
EXTFlag = true;
SpentFlag = true;
}
}
catch { Debug.WriteLine("Read And Check Data出现错误"); }
}
}
catch { Debug.WriteLine("Read And Check Data出现错误"); }
}
} while (!EXTFlag);
Debug.WriteLine("ReadAndCheckData 结束...");
return SpentFlag;
}