对于“数据校验发送指令来控制下位机”的上位机,该模块主要有三个; (1)串口扫描,获取串口号,通过打开按钮来控制按钮是否打开。 (2)发送数据校验的函数,将数据发送个给相应的下位机和硬件设备。 (3)接收下位机的反馈状态。取反校验。 (4)定时器来简单直观的显示下位机是否将反馈信息发送出来,上位机有没有发送数据给下位机和接收到下位机的数据。 (5)定时器来显示状态还是不够显示,由visual basic power控件来显示更加直观。
1.窗体设计,这块涉及到visual basic power控件,如果自己的编译器没有,我之前的博客中有解决办法。 2.打开串口设计 2.1 扫描串口,详解见之前的串口控制上位机设计。通过扫描串口,可以获取电脑上可用的串口
public Form1()
{
InitializeComponent();
SearchAndSerialComboBox(serialPort1, comboBox1);
}
private void SearchAndSerialComboBox(SerialPort MyPort, ComboBox MyBox)
{
string Buffer;
MyBox.Items.Clear();
for (int i = 1; i < 20; i++)
{
try
{
Buffer = "COM" + i.ToString();
MyPort.PortName = Buffer;
MyPort.Open();
MyBox.Items.Add(Buffer);
MyPort.Close();
}
catch
{
}
}
}
2.2 打开串口和关闭串口在一个按钮上同时可以实现。
private void button1_Click(object sender, EventArgs e)
{
if (serialPort1.IsOpen)
{
try
{
serialPort1.Close();
button1.Text = "打开串口";
}
catch
{
}
}
else
{
try
{
serialPort1.PortName = comboBox1.Text;
serialPort1.Open();
button1.Text = "关闭串口";
}
catch
{
MessageBox.Show("串口打开失败", "提示");
}
}
}
3.发送数据校验的函数,由于N0.1、N0.2和N0.3三个组合中,发送数据校验的按钮作用都一样,因此在这进行了一个函数封装。 3.1 Form1.Designer.cs中的按钮属性都要进行修改。
this.button2.Click += new System.EventHandler(this.button_Click);
this.button3.Click += new System.EventHandler(this.button_Click);
this.button4.Click += new System.EventHandler(this.button_Click);
注意;这个就类似于c语言的声明。注意该处函数名要一样。
3.2 自定义的串口发送数据的函数
private void SendDataToSerialPort(SerialPort MyPort, byte DataToSend)
{
byte[] DataToWrite = new byte[] { DataToSend };
if (serialPort1.IsOpen)
{
try
{
MyPort.Write(DataToWrite, 0, 1);
}
catch
{
MessageBox.Show("串口数据写入错误", "错误提示");
}
}
}
1.自定义的串口发送数据的函数。里面有两个参数: (1)SerialPort是一个类,MyPort是一个对象, (2)byte是一个类, DataToSend是一个对象。由于传参的DataToSend是一个byte类型,因此这块也是byte类型的。 2.Write(): 使用缓冲区的数据将指定数量的字节写入串行端口。 参数: (1)buffer:包含要写入端口的数据的字节数组。 (2)offset:buffer 参数中从零开始的字节偏移量,从此处开始将字节复制到端口。 (3)count: 要写入的字节数。
3.3 控制哪个下位机进行发送数据
private void button_Click(object sender, EventArgs e)
{
Button my_button = (Button)sender;
DataSended = Convert.ToByte(my_button.Tag);
SendDataToSerialPort(serialPort1, DataToSend[DataSended - 1]);
}
将发送数据校验三个相同作用的控件封装在一个函数下面,以便之后方便调用。
4.上位机接收下位机大接收状态
这个上位机跟之前的串口控制上位机,最大的区别就是,串口控制上位机只能通过上位机发送指令来控制下位机。而数据校验的上位机不仅可以通过发送指令来控制下位机,而且下位机也要根据接收的数据校验来反馈自己的接收状态。
4.1 串口接收函数应该在串口控件事件中写
private void SerialPortDataReceived(object sender, SerialDataReceivedEventArgs e)
{
byte DataReceived = (byte)(~serialPort1.ReadByte());
if(DataSended == 0)
return ;
try
{
if (DataToSend[DataSended - 1] == DataReceived)
{
MessageBox.Show("数据校验成功", "提示");
}
else
{
MessageBox.Show("数据校验失败", "错误");
}
}
catch (Exception)
{
throw;
}
}
5.定时器事件 5.1 发送数据定时器开始
private void SendDataToSerialPort(SerialPort MyPort, byte DataToSend)
{
byte[] DataToWrite = new byte[] { DataToSend };
if (serialPort1.IsOpen)
{
try
{
MyPort.Write(DataToWrite, 0, 1);
timer1.Interval = 3 * 1000;
timer1.Start();
}
catch
{
MessageBox.Show("串口数据写入错误", "错误提示");
}
}
}
5.2 接收数据定时器停止
private void SerialPortDataReceived(object sender, SerialDataReceivedEventArgs e)
{
byte DataReceived = (byte)(~serialPort1.ReadByte());
try
{
timer1.Stop();
}
catch (Exception)
{
throw;
}
if(DataSended == 0)
return ;
try
{
if (DataToSend[DataSended - 1] == DataReceived)
{
MessageBox.Show("数据校验成功", "提示");
}
else
{
MessageBox.Show("数据校验失败", "错误");
}
}
catch (Exception)
{
throw;
}
}
5.3 定时器事件,定时3s后,还是没有反应,那就认为下位机数据校验超时,反馈失败。
private void timer1_Tick(object sender, EventArgs e)
{
string my_str = "第" + DataSended.ToString() + "路校验超时";
timer1.Stop();
MessageBox.Show("校验超时", "错误提示");
}
6.定时器虽然能反馈下位机的接收状态,但是还是不够明显。下来我们使用visual basic power控件来展示下位机的接收状态,和上位机的发送状态。
private void ovalShape_Click(int which)
{
switch (which)
{
case 0x01:
ovalShape1.FillColor = Color.Green;
break;
case 0x02:
ovalShape2.FillColor = Color.Green;
break;
case 0x03:
ovalShape3.FillColor = Color.Green;
break;
case 0x11:
ovalShape1.FillColor = Color.Red;
break;
case 0x12:
ovalShape2.FillColor = Color.Red;
break;
case 0x13:
ovalShape3.FillColor = Color.Red;
break;
case 0x04:
ovalShape1.FillColor = Color.Green;
ovalShape2.FillColor = Color.Green;
ovalShape3.FillColor = Color.Green;
break;
case 0x14:
ovalShape1.FillColor = Color.Red;
ovalShape2.FillColor = Color.Red;
ovalShape3.FillColor = Color.Red;
break;
default:
break;
}
}
private void SerialPortDataReceived(object sender, SerialDataReceivedEventArgs e)
{
byte DataReceived = (byte)(~serialPort1.ReadByte());
try
{
timer1.Stop();
}
catch (Exception)
{
throw;
}
ovalShape_Click(DataReceived);
if(DataSended == 0)
return ;
try
{
if (DataToSend[DataSended - 1] == DataReceived)
{
MessageBox.Show("数据校验成功", "提示");
}
else
{
MessageBox.Show("数据校验失败", "错误");
}
}
catch (Exception)
{
throw;
}
}
由于没有下位机,没有硬件设备,所以没有办法验证。
|