直连
串口转网口:通过请求帧写入波特率 或者地址位 或者温度 湿度等数据
读取时候 [0x01,0x03]
写入的时候[0x01,0x03]
写入波特率的时候请求帧 [0x01,0x06,0x07,0xD1,0x01,0x14] 把波特率改成0x01,0x14
namespace _01_HuaYun出口服务器
{
public partial class Form1 : Form
{
string[] botelvs;
public Form1()
{
InitializeComponent();
botelvs = new string[] { "2400", "4800", "9600", "19200" };
comboBox1.DataSource = botelvs;
}
NetworkStream stream;
TcpClient tcp;
private void button1_Click(object sender, EventArgs e)
{
// 连接网口
if (button1.Text == "连接")
{
try
{
tcp = new TcpClient();// 创建客户端对象
tcp.Connect(textBox1.Text, int.Parse(textBox2.Text));
stream = tcp.GetStream();// 获取网络基础流
button1.Text = "断开";
}
catch
{
MessageBox.Show("连接服务器失败");
}
}
else
{
if (tcp!=null&&tcp.Connected)
{
tcp.Close();
tcp = null;
stream = null;
}
button1.Text = "连接";
}
}
// 刷新功能
private void button2_Click(object sender, EventArgs e)
{
if (tcp == null || tcp.Connected == false)
{
MessageBox.Show("请先连接服务器");
return;
}
Task.Run(refresh);
}
async void refresh()
{
try
{
// 请求帧
byte[] buffer = null;
// 响应帧
byte[] res = null;
// 设置地址
byte address = Convert.ToByte(label12.Text);
// 相应数据的个数
int resCount = -1;
// 响应帧crc
byte[] crc;
// 读取PM2.5 PM10 湿度 温度数据 寄存器个数是4个
// 有效数组字节数8个字节
buffer = new byte[] { address,0x03,0x00,0x00,0x00,0x04 };
buffer = buffer.Concat(CRCCalc(buffer)).ToArray();
// 异步发请求 发送请求帧
await stream.WriteAsync(buffer, 0, buffer.Length);
// 接受数据 响应帧
res = new byte[13];
resCount = await stream.ReadAsync(res, 0, res.Length);
// 数据验证
// 数据解析 读取数据
int pm25 = res[3] * 256 + res[4];
int pm10 = res[5] * 256 + res[6];
double humidity = (res[7] * 256 + res[8])*0.1; // 湿度
double wendu = (res[9] * 256 + res[10]) * 0.1;// s
//更新界面
Invoke((Action)(() =>
{
textBox3.Text = pm25.ToString();
textBox4.Text = pm10.ToString();
textBox5.Text = humidity.ToString();
textBox6.Text = wendu.ToString();
}));
}
catch
{
MessageBox.Show("获取数据失败");
}
}
public static byte[] CRCCalc(byte[] data)
{
//crc计算赋初始值
int crc = 0xffff;
for (int i = 0; i < data.Length; i++)
{
//XOR
//(1) 0^0=0,0^1=1 0异或任何数=任何数
//(2) 1 ^ 0 = 1,1 ^ 1 = 0 1异或任何数-任何数取反
//(3) 1 ^ 1 = 0,0 ^ 0 = 0 任何数异或自己=把自己置0
//异或操作符是^。异或的特点是相同为false,不同为true。
crc = crc ^ data[i]; //和^表示按位异或运算。
//0x0fff ^ 0x01 Console.WriteLine(result.ToString("X"));
// 输出结果为4094,即十六进制数1001
for (int j = 0; j < 8; j++)
{
int temp;
temp = crc & 1; // & 运算符(与) 1 & 0 为 0 ;0 & 0 为0;1 & 1 为1
//右移 (>>) 将第一个操作数向右移动第二个操作数所指定的位数,空出的位置补0。右移相当于整除. 右移一位相当于除以2;右移两位相当于除以4;右移三位相当于除以8。
//int i = 7;
//int j = 2;
//Console.WriteLine(i >> j); //输出结果为1
crc = crc >> 1;
crc = crc & 0x7fff;
if (temp == 1)
{
crc = crc ^ 0xa001;
}
crc = crc & 0xffff;
}
}
//CRC寄存器的高低位进行互换
byte[] crc16 = new byte[2];
//CRC寄存器的高8位变成低8位,
crc16[1] = (byte)((crc >> 8) & 0xff);
//CRC寄存器的低8位变成高8位
crc16[0] = (byte)(crc & 0xff);
return crc16;
}
private void button4_Click(object sender, EventArgs e)
{
if (tcp == null || tcp.Connected ==false)
{
MessageBox.Show("未连接服务器");
return;
}
Task.Run((() =>
{
this.Invoke((Action)(() =>
{
// 获取选中的波特率
byte botelv = Convert.ToByte(comboBox1.SelectedIndex);
// 当前设备地址
byte address = Convert.ToByte(label12.Text);
// 询问帧
byte[] buffer = new byte[] { address, 0x06, 0x07, 0xD1, 0x00, botelv };
buffer = buffer.Concat(CRCCalc(buffer)).ToArray();
// 发送
stream.Write(buffer, 0, buffer.Length);
// 读取
byte[] bs = new byte[8];
int count = stream.Read(bs, 0, bs.Length);
// 数据验证
byte newBotelv = bs[5];
comboBox1.SelectedIndex = newBotelv;
MessageBox.Show(comboBox1.SelectedIndex + "" + newBotelv.ToString());
}));
}));
}
}
}