今天来说说电脑读取触摸屏的程序,ModbusTCP通讯协议是怎么样的可以看看别人的博客modbus TCP 示例报文
下面来看看我对modbus TCP的理解
先来看看如何从触屏上读取一个值
///
/// 创建一个按钮,用来发送查询命令
///
///
///
private void button2_Click(object sender, EventArgs e)
{
try
{
//先创建一个字节数组,大小是12个字节,都是16进制的
byte[] buffer = new byte[12];
//事务处理序号
buffer[0]= 0x00;
buffer[1] = 0x00;
//协议标识符
buffer[2] = 0x00;
buffer[3] = 0x00;
//随后字节数,06代表后面有6个字节
buffer[4] = 0x00;
buffer[5] = 0x06;
//单元标识符,这个就是我们之前在触屏上设置的设备地址了
buffer[6] = 0x01;//MBAP报文头
//功能码,03是用于读取4区的输出寄存器的(这个我是看触屏上的功能码说明)
buffer[7] = 0x03;
//寄存器起始地址,(触屏上的设备通道为4XXX0001)
buffer[8] = 0x00;
buffer[9] = 0x00;
//请求字节长度02代表了要读4个字节长度(触屏上代表了一个32位数)
buffer[10] = 0x00;
buffer[11] = 0x02;
//通过网口把请求命令发出去
socketSend.Send(buffer);
}
catch
{
}
}
下面看看怎么样接受从触屏返回的数据
///
/// 用于接受从触屏返回的数据
///
void Recive()
{
try
{
while (true)
{
//创建一个字节数组,用于接收从触屏返回的数据
byte[] buffer = new byte[258];
//接收从触屏返回的数据,并返回接收数据的个数
int r = socketSend.Receive(buffer);
//当就收的数据等于0,就跳出循环
if (r == 0) break;
//声明一个字符串,用于接收从字节数组转换成16进制数的字符串
string s="";
//接收到的事务处理序号
s += Convert.ToString(buffer[0], 16) + " ";
s += Convert.ToString(buffer[1], 16) + " ";
//接收到的协议标识符
s += Convert.ToString(buffer[2], 16) + " ";
s += Convert.ToString(buffer[3], 16) + " ";
//接收到的字节数,后面有多少数据
s += Convert.ToString(buffer[4], 16) + " ";
s += Convert.ToString(buffer[5], 16) + " ";
//接收到的单元标识符
s += Convert.ToString(buffer[6], 16) + " ";//之前的都是MBAP报文头
//接收到的功能码,就是我们发送的03
s += Convert.ToString(buffer[7], 16) + " ";
//接收到字节数,这里是4,就是我们之前写的02
s += Convert.ToString(buffer[8], 16) + " ";
//下面的数据就是我们要的数据了,前面的数据就没什么用
s += Convert.ToString(buffer[9], 16) + " ";
s += Convert.ToString(buffer[10], 16) + " ";
s += Convert.ToString(buffer[11], 16) + " ";
s += Convert.ToString(buffer[12], 16) + " ";
//下面我们来对数据进行处理
//如果要读取的数据是16位数据时,先要截取出我们需要的两位数据
byte[] buffer1 = buffer.Skip(9).Take(2).ToArray();
//接着对数据进行高低位数据交换,
byte bat = buffer1[0];
byte bat1 = buffer1[1];
buffer1[0] = bat1;
buffer1[1] = bat;
//这样就可以获得16位数据了
ushort sh = BitConverter.ToUInt16(buffer1, 0);
//如果要读取的数据是32位数据时,先要截取出我们需要的4位数据
buffer1 = buffer.Skip(9).Take(4).ToArray();
//接着对数据进行高低位数据交换,
bat = buffer1[0];
bat1 = buffer1[1];
buffer1[0] = bat1;
buffer1[1] = bat;
bat = buffer1[2];
bat1 = buffer1[3];
buffer1[2] = bat1;
buffer1[3] = bat;
//这样就可以获得32位数据了
int sh1 = BitConverter.ToInt32(buffer1, 0);
}
}
catch
{
}
}
如果要读取浮点数的话,就需要做浮点数转换,有大神已经做好了封装,可以直接使用,链接为MODBUS RTU协议中浮点数是如何存储,读到浮点数寄存器的数值如何转换成所需的浮点数
public static float GetFloat(ushort P1, ushort P2)
{
//如果浮点数时0时,直接返回0.0,不做转换
if (P1 == 0 && P2 == 0) return 0.0F;
int intSign, intSignRest, intExponent, intExponentRest;
float faResult, faDigit;
intSign = P1 / 32768;
intSignRest = P1 % 32768;
intExponent = intSignRest / 128;
intExponentRest = intSignRest % 128;
faDigit = (float)(intExponentRest * 65536 + P2) / 8388608;
faResult = (float)Math.Pow(-1, intSign) * (float)Math.Pow(2, intExponent - 127) * (faDigit + 1);
return faResult;
}
因为我读取的数据需要做高低位交换,所以就写了一个函数
///
/// 获得转换后的浮点数
///
/// 4个浮点数的字节数组
///
public float FloatingPointNumberObtained(byte[] byt)
{
try
{
byte[] buffer1 = byt.Skip(0).Take(2).ToArray();
HighLowBytEswitching(buffer1);
ushort sh = BitConverter.ToUInt16(buffer1, 0);
byte[] buffer2 = byt.Skip(2).Take(2).ToArray();
HighLowBytEswitching(buffer2);
ushort sh1 = BitConverter.ToUInt16(buffer2, 0);
float d = GetFloat(sh, sh1);
return d;
}
catch
{
return 0.0F;
}
}
///
/// 高低字节交换
///
///
public byte[] HighLowBytEswitching(byte[] byt)
{
try
{
byte bat = byt[0];
byte bat1 = byt[1];
byt[0] = bat1;
byt[1] = bat;
return byt;
}
catch { return byt; }
}
如果要读取字符串的话,看下面的代码
///
/// 创建一个按钮,用来发送查询命令
///
///
///
private void button2_Click(object sender, EventArgs e)
{
try
{
//先创建一个字节数组,大小是12个字节,都是16进制的
byte[] buffer = new byte[12];
//事务处理序号
buffer[0]= 0x00;
buffer[1] = 0x00;
//协议标识符
buffer[2] = 0x00;
buffer[3] = 0x00;
//随后字节数,06代表后面有6个字节
buffer[4] = 0x00;
buffer[5] = 0x06;
//单元标识符,这个就是我们之前在触屏上设置的设备地址了
buffer[6] = 0x01;//MBAP报文头
//功能码,03是用于读取4区的输出寄存器的(这个我是看触屏上的功能码说明)
buffer[7] = 0x03;
//寄存器起始地址,(触屏上的设备通道为4XXX0001)
buffer[8] = 0x00;
buffer[9] = 0x00;
//因为触屏上的字符串字节是128个
buffer[10] = 0x00;
buffer[11] = 0x40;
//通过网口把请求命令发出去
socketSend.Send(buffer);
}
catch
{
}
}
void Recive()
{
try
{
while (true)
{
//创建一个字节数组,用于接收从触屏返回的数据
byte[] buffer = new byte[258];
//接收从触屏返回的数据,并返回接收数据的个数
int r = socketSend.Receive(buffer);
//当就收的数据等于0,就跳出循环
if (r == 0) break;
string a = Encoding.ASCII.GetString(buffer, 0, r);
a = a.Remove(0,17);