应用程序配置的保存
1 右键应用设置 → 属性 → 添加键值对和用户范围,应用程序和用户范围
2 获取配置参数:Properties.Settings.Default.参数名
3 修改修改参数 roperties.Settings.Default["A"] = 10 最后调用 save进行保存
1.什么是modbus? 包含的内容
包含的三种协议: modbus-RTU: modbus-ASCII: modbus-TCP:
大部分的硬件都支持modbus-RTU(远程终端设备)协议,对数据在传输过程和接收过程格式的规定
2.modbus作用?
用来通信; 如果没有协议:发送数据,接收方不知道这些数据的作用
协议方就是指定数据的准则的
3 modbus-RTU: 协议是一种开放的串行协议,广泛应用于当今的工业监控设备中。该协议使用 RS-232 或 RS-485 串行接口进行通信,并得到市场上几乎所有商业 SCADA、HMI、OPC 服务器和数据采集软件程序的支持。因此,很容易将 Modbus 兼容设备集成到新的或现有的监控应用程序中,并具有即时的软件支持。
4 modbus 的主从技术()?
Modbus RTU 协议使用主/从技术在设备之间进行通信。这意味着,任何使用 Modbus RTU 协议的应用程序都将有一个 Modbus 主站和至少一个 Modbus 从站。Modbus Master 通常是一台运行软件的主机监控计算机,它将与一个或多个 Modbus Slave 设备进行通信。Modbus 从设备是执行系统参数测量和控制系统中的开/关设备的设备。为了执行这些任务,主站向 Modbus 从站发送消息,请求执行特定任务。
modbus中的帧结构?
帧就是系统 Master和Slave 设备之间发送的信息,master发送的叫做命令帧,Slave返回的叫做应答帧
帧的结构 = 地址位 + 功能码 + 数据 + CRC校验地址: 占用一个字节,范围0-255,其中有效范围是1-247,其他有特殊用途
功能码:占用一个字节,功能码的意义就是,知道这个指令是干啥的,比如你可以查询从机的数据,也可以修改数据,
所以不同功能码对应不同功能。数据:根据功能码不同,有不同结构,在下面的实例中有说明。
校验:为了保证数据不错误,增加这个,然后再把前面的数据进行计算看数据是否一致,如果一致,就说明这帧数据是正确的,我再回复;
如果不一样,说明你这个数据在传输的时候出了问题,数据不对的,所以就抛弃了Modbus-RTU协议一般我们用的最多功能码就是`03`和`06`,大部分都是用modbus来查询传感器上的信息用`03`查询功能码(读寄存器),
如果需要修改传感器寄存器的值就用`06`修改功能码(写寄存器),其他的不需要过多关注
6 上位机需要选择合适的 Modbus 协议栈、配置 Modbus 通信参数、建立 Modbus 通信连接、发送 Modbus 命令帧、接收 Modbus 响应帧和关闭 Modbus 通信连接等步骤。
应用程序配置的读取,保存
#region ① 读取,修改 // 读取setting配置的参数// Properties.Settings.Default.参数名this.Text = Properties.Settings.Default.A; // 修改窗体标题this.BackColor = Properties.Settings.Default.B;// 修改窗体背景// 修改参数 应用程序范围参数 不能在运行的时候修改:用户范围的参数可以在运行时候修改Properties.Settings.Default["A"] = "31马赫的威慑力,奥特之王都追不上";Properties.Settings.Default["B"] = Color.PaleGreen;Properties.Settings.Default.Save(); // 保存修改#endregion
Modbus协议
// 初始化串口参数配置serialPort1.PortName = "COM5"; // 串口名字serialPort1.BaudRate = 4800; // 波特率serialPort1.Parity = System.IO.Ports.Parity.None;// 无奇偶校检serialPort1.DataBits = 8; // 数据位置serialPort1.StopBits = System.IO.Ports.StopBits.One; // 停止位serialPort1.Open(); // 开放serialPort1.DataReceived += serialPort1_DataReceived;}// 接收到数据的方法 private void serialPort1_DataReceived(object sender, SerialDataReceivedEventArgs e){byte[] body = new byte[20];serialPort1.Read(body, 0, body.Length);// 读取应答帧// 01 03 02 06 C3 FB B5 // 01 地址码// 03 功能码// 02 长度// 06 C3 数据位// FB B5 校检码// 将数据位解析为10进制Console.WriteLine(body[3] * 256 + body[4]);// 06C3 真正的值// 06 C3, C#是小端模式,这个数组被传递进去之后会被认为06为低位,C3为高位,按照C306进行计算// 先获取中间的两个字节, 再反转,使低位在前,高位在后byte[] value = body.Skip(3).Take(2).Reverse().ToArray();Console.WriteLine(BitConverter.ToUInt16(value, 0));BeginInvoke(new Action(() =>{label1.Text = BitConverter.ToUInt16(value, 0).ToString();}));}public static byte[] CRCCalc(byte[] data){//crc计算赋初始值int crc = 0xffff;for (int i = 0; i < data.Length; i++){crc = crc ^ data[i];for (int j = 0; j < 8; j++){int temp;temp = crc & 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 button1_Click(object sender, EventArgs e){// 组织回答帧CO2byte[] bs = new byte[]{0x01,// 地址码 占1个字节0x03,// 功能码 读取 查询功能 占1个字节0x00,0x08, // 起始地址,占2个字节0x00,0x01,// 数据长度 1个长度 占2个字节// 校检码 2个字节};// 2 通过crc进行计算校检码byte[] abc = CRCCalc(bs); // 0x05,0xc8bs = bs.Concat(abc).ToArray();// 把bs和校检码进行合并//3 发送serialPort1.Write(bs, 0, bs.Length);}}
}