c#串口读写威盟士空气净化器
·
WinForm页面





对应Combox按钮里面要书写对应数
搭建完页面代码后要搭建后端代码,编写完成之后即进行威盟士空气净化器
的数据读取。
后端代码书写
这里使用的是
Modbus协议,所以需要安装对应依赖包


默认窗口配置
private void Form1_Load(object sender, EventArgs e)
{
comboBox1.DataSource = SerialPort.GetPortNames();
comboBox2.Text = comboBox2.Items[1].ToString();
comboBox3.Text = comboBox3.Items[0].ToString();
comboBox4.Text = comboBox4.Items[1].ToString();
comboBox5.Text = comboBox5.Items[0].ToString();
}

编写打开端口按钮
private void button1_Click(object sender, EventArgs e)
{
if (button1.Text == "打开端口")
{
serialPort1.PortName = comboBox1.Text;
serialPort1.BaudRate = Convert.ToInt32(comboBox2.Text);
serialPort1.DataBits = Convert.ToInt32(comboBox3.Text);
serialPort1.StopBits = (StopBits)Enum.Parse(typeof(StopBits), comboBox4.Text);
serialPort1.Parity = (Parity)Enum.Parse(typeof(Parity), comboBox5.Text);
serialPort1.ReadTimeout = 5000; // 设置为5秒超时
try
{
serialPort1.Open();
button1.Text = "关闭端口";
button1.BackColor = Color.Red;
comboBox1.Enabled = false;
comboBox2.Enabled = false;
comboBox3.Enabled = false;
comboBox4.Enabled = false;
comboBox5.Enabled = false;
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
else
{
try
{
serialPort1.Close();
button1.Text = "打开端口";
button1.BackColor = Color.Lime;
comboBox1.Enabled = true;
comboBox2.Enabled = true;
comboBox3.Enabled = true;
comboBox4.Enabled = true;
comboBox5.Enabled = true;
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
}

编写连接设备按钮
private void button2_Click(object sender, EventArgs e)
{
// 创建 Modbus 工厂
var factory = new ModbusFactory();
// 创建 RTU 传输对象
var transport = factory.CreateRtuTransport(serialPort1);
var master = factory.CreateMaster(transport);
// 读取保持寄存器(功能码 0x03)
ushort startAddress = 0; // 起始地址
ushort numRegisters = 13; // 读取寄存器数量
ushort slaveId = 1; // 从站地址
ushort[] registers = master.ReadHoldingRegisters(1, startAddress, numRegisters);
//double pm25 = registers[0] / 10.0;
//double pm10 = registers[1] / 10.0;
double humidity = registers[2] / 10.0;
double temperature = registers[3] / 10.0;
//double co2 = registers[8];
double formaldehyde = registers[9] / 100.0;
Invoke(new Action(() =>
{
// 更新 UI
textBox1.Text = registers[0].ToString();
textBox2.Text = registers[1].ToString();
textBox3.Text = humidity.ToString();
textBox4.Text = temperature.ToString();
textBox5.Text = registers[8].ToString();
textBox6.Text = formaldehyde.ToString();
}));
string filePath = "TextFile.txt";
string data = string.Join(", ", registers);
using (StreamWriter sw = new StreamWriter(filePath, append: true, Encoding.UTF8))
{
// 添加分隔线
sw.WriteLine("======================================");
sw.WriteLine($"记录时间:{DateTime.Now:yyyy-MM-dd HH:mm:ss}");
sw.WriteLine($"位置 :{textBox7.Text}");
sw.WriteLine($"PM2.5 :{registers[0],6} μg/m³");
sw.WriteLine($"PM10 :{registers[1],6} μg/m³");
sw.WriteLine($"湿度 :{humidity,6} %RH");
sw.WriteLine($"温度 :{temperature,6} ℃");
sw.WriteLine($"二氧化碳 :{registers[9],6} ppm");
sw.WriteLine($"甲醛 :{formaldehyde,6} ppm");
sw.WriteLine("======================================");
sw.WriteLine(); // 空行分隔不同记录
Console.WriteLine("文本追加写入完成!");
}
string filePath2 = "TextFile.csv";
string data2 = string.Join(", ", registers);
// 首次写入时添加表头
bool isFirstWrite = !File.Exists(filePath2);
using (StreamWriter sw = new StreamWriter(filePath2, append: true, Encoding.UTF8))
{
if (isFirstWrite)
{
sw.WriteLine("时间,位置,PM2.5(μg/m³),PM10(μg/m³),湿度(%RH),温度(℃),二氧化碳(ppm),甲醛(ppm)");
}
// CSV格式一行完成记录
sw.WriteLine($"{DateTime.Now:yyyy-MM-dd HH:mm:ss},{textBox7.Text},{registers[0]},{registers[1]},{humidity},{temperature},{registers[9]},{formaldehyde}");
Console.WriteLine("文本追加写入完成!");
}
string filePath3 = "TextFile.json";
string data3 = string.Join(", ", registers);
using (StreamWriter sw = new StreamWriter(filePath3, append: true, Encoding.UTF8))
{
// 构建JSON对象
var record = new
{
时间 = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"),
位置 = textBox7.Text,
PM25 = $"{registers[0]} μg/m³",
PM10 = $"{registers[1]} μg/m³",
湿度 = $"{humidity} %RH",
温度 = $"{temperature} ℃",
二氧化碳 = $"{registers[9]} ppm",
甲醛 = $"{formaldehyde} ppm"
};
// 写入JSON格式
sw.WriteLine(Newtonsoft.Json.JsonConvert.SerializeObject(record));
Console.WriteLine("文本追加写入完成!");
}
}

生成有关实时读取的事件函数:
private void timer1_Tick(object sender, EventArgs e)
private void checkBox1_CheckedChanged(object sender, EventArgs e)、private void button4_Click(object sender, EventArgs e)
进行代码编写:
private void timer1_Tick(object sender, EventArgs e)
{
// 创建 Modbus 工厂
var factory = new ModbusFactory();
// 创建 RTU 传输对象
var transport = factory.CreateRtuTransport(serialPort1);
var master = factory.CreateMaster(transport);
// 读取保持寄存器(功能码 0x03)
ushort startAddress = 0; // 起始地址
ushort numRegisters = 13; // 读取寄存器数量
ushort slaveId = 1; // 从站地址
ushort[] registers = master.ReadHoldingRegisters(1, startAddress, numRegisters);
//double pm25 = registers[0] / 10.0;
//double pm10 = registers[1] / 10.0;
double humidity = registers[2] / 10.0;
double temperature = registers[3] / 10.0;
//double co2 = registers[8];
double formaldehyde = registers[9] / 100.0;
Invoke(new Action(() =>
{
// 更新 UI
textBox1.Text = registers[0].ToString();
textBox2.Text = registers[1].ToString();
textBox3.Text = humidity.ToString();
textBox4.Text = temperature.ToString();
textBox5.Text = registers[8].ToString();
textBox6.Text = formaldehyde.ToString();
}));
string filePath = "TextFile.txt";
string data = string.Join(", ", registers);
using (StreamWriter sw = new StreamWriter(filePath, append: true, Encoding.UTF8))
{
// 添加分隔线
sw.WriteLine("======================================");
sw.WriteLine($"记录时间:{DateTime.Now:yyyy-MM-dd HH:mm:ss}");
sw.WriteLine($"位置 :{textBox7.Text}");
sw.WriteLine($"PM2.5 :{registers[0],6} μg/m³");
sw.WriteLine($"PM10 :{registers[1],6} μg/m³");
sw.WriteLine($"湿度 :{humidity,6} %RH");
sw.WriteLine($"温度 :{temperature,6} ℃");
sw.WriteLine($"二氧化碳 :{registers[9],6} ppm");
sw.WriteLine($"甲醛 :{formaldehyde,6} ppm");
sw.WriteLine("======================================");
sw.WriteLine(); // 空行分隔不同记录
Console.WriteLine("文本追加写入完成!");
}
string filePath2 = "TextFile2.csv";
string data2 = string.Join(", ", registers);
// 首次写入时添加表头
bool isFirstWrite = !File.Exists(filePath2);
using (StreamWriter sw = new StreamWriter(filePath, append: true, Encoding.UTF8))
{
if (isFirstWrite)
{
sw.WriteLine("时间,位置,PM2.5(μg/m³),PM10(μg/m³),湿度(%RH),温度(℃),二氧化碳(ppm),甲醛(ppm)");
}
// CSV格式一行完成记录
sw.WriteLine($"{DateTime.Now:yyyy-MM-dd HH:mm:ss},{textBox7.Text},{registers[0]},{registers[1]},{humidity},{temperature},{registers[9]},{formaldehyde}");
Console.WriteLine("文本追加写入完成!");
}
string filePath3 = "TextFile.json";
string data3 = string.Join(", ", registers);
using (StreamWriter sw = new StreamWriter(filePath3, append: true, Encoding.UTF8))
{
// 构建JSON对象
var record = new
{
时间 = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"),
位置 = textBox7.Text,
PM25 = $"{registers[0]} μg/m³",
PM10 = $"{registers[1]} μg/m³",
湿度 = $"{humidity} %RH",
温度 = $"{temperature} ℃",
二氧化碳 = $"{registers[9]} ppm",
甲醛 = $"{formaldehyde} ppm"
};
// 写入JSON格式
sw.WriteLine(Newtonsoft.Json.JsonConvert.SerializeObject(record));
Console.WriteLine("文本追加写入完成!");
}
}
private void checkBox1_CheckedChanged(object sender, EventArgs e)
{
if (checkBox1.Checked)
{
if (!serialPort1.IsOpen)
{
MessageBox.Show("请先连接,再实时显示数据", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
checkBox1.Checked = false;
return;
}
timer1.Interval = 1000;
timer1.Start();
}
else
{
timer1.Stop();
}
}
private void button4_Click(object sender, EventArgs e)
{
timer1.Interval = 1000;
timer1.Start();
}
编写完成之后即可在读取威盟士空气净化器对应设备数据
代码功能分析
环境监测设备串口通信程序综述
该代码是一个基于 C# WinForms 和 NModbus 库开发的串口通信应用,主要用于与环境监测设备进行数据交互,实现了环境参数的读取、显示和多格式记录功能。
核心功能模块
1. 串口配置与管理模块
- 程序启动时自动检测并加载可用串口列表
- 支持配置串口关键参数:波特率、数据位、停止位和校验位
- 提供 "打开 / 关闭端口" 按钮,实现串口连接状态切换
- 连接状态变化时,自动更新 UI 控件状态(启用 / 禁用参数配置项)
- 连接状态通过按钮文本和颜色直观展示(打开时红色,关闭时绿色)
2. 数据读取与解析模块
- 基于 NModbus 库实现 Modbus RTU 协议通信
- 支持手动读取和定时自动读取两种模式
- 读取保持寄存器(功能码 0x03)中的环境监测数据
- 解析并转换寄存器数据为实际物理量:
- 湿度和温度除以 10.0 获取实际值
- 甲醛浓度除以 100.0 获取实际值
- 线程安全地更新 UI 显示各环境参数(PM2.5、PM10、湿度、温度等)
3. 数据记录模块
- 支持三种格式的数据记录:
- 文本文件(TXT):格式化显示,包含分隔线和清晰标识
- 逗号分隔值文件(CSV):适合表格软件导入和数据分析
- JSON 格式文件:便于程序解析和处理的结构化数据
- 记录内容包含时间戳、监测位置和各项环境参数
- 首次写入 CSV 文件时自动添加表头信息
4. 实时监控模块
- 通过复选框控制是否启用实时数据监控
- 使用定时器实现固定间隔(1 秒)自动读取和记录数据
- 启动实时监控前验证串口是否已连接,确保操作有效性
技术实现特点
Modbus 协议实现:使用 NModbus 库简化 Modbus RTU 通信的开发,无需手动处理协议细节和 CRC 校验
多格式数据持久化:同时支持 TXT、CSV 和 JSON 三种格式的数据记录,满足不同场景需求
线程安全处理:在数据更新 UI 时使用 Invoke 方法,确保跨线程操作安全
用户体验优化:通过颜色变化直观展示连接状态,操作前验证状态避免错误
错误处理:包含基本的异常捕获机制,出错时显示错误信息
潜在问题与改进点
代码复用性:数据读取和记录的代码在 button2_Click 和 timer1_Tick 中重复,可提取为独立方法
资源管理:Modbus 相关对象(factory、transport、master)没有显式释放,可能导致资源泄漏
错误处理:异常处理不够细致,可增加对 Modbus 通信错误的专门处理
配置灵活性:数据记录路径和时间间隔当前是硬编码,可改为用户可配置
日志完善性:可增加详细的通信日志,便于调试和问题排查
该程序整体实现了环境监测设备的数据采集与记录功能,适合作为环境监测系统的基础应用,通过进一步优化可提升其可靠性和扩展性。
更多推荐


所有评论(0)