I2C文件传输原理以及生成代码
2026/7/21 13:54:33 网站建设 项目流程

完整实现方案(WinForm C#,适配你手上的I2C时序日志txt)

一、整体需求梳理

1. 原始日志格式(txt每行逗号分割)

示例行:
66,1328180800.00,Data write: 80
字段规则:行号,时间戳,时序指令

2. I2C完整写时序固定流程

一条完整寄存器写入,固定时序顺序:
StartAddress write: 从机地址WriteACKData write: 寄存器地址WriteACKData write: 写入数据WriteACKStop

3. 转换输出格式要求

提取时序里:从机地址、寄存器地址、写入字节,输出:
【写】从机0xAC 寄存器0x80 写入:0x00

4. 界面功能需求

  1. 按钮「选择并解析I2C日志txt」;
  2. 弹窗选择本地txt文件;
  3. 逐行读取、按时序分组匹配完整I2C写帧;
  4. 自动生成格式化解析文本,展示/可复制保存;

二、I2C日志解析核心逻辑

1. 存储临时时序缓存

遍历每一行,把时序指令按顺序存入临时列表,遇到Stop代表一整段I2C传输结束,开始解析这一组。

2. 单组完整写时序提取规则

一组有效写帧必须包含:

  1. Start
  2. Address write: XX → 提取从机地址(十六进制字符串转数字)
  3. ACK(地址应答)
  4. Data write: REG → 提取寄存器地址
  5. ACK(寄存器应答)
  6. Data write: VAL → 提取要写入的数据
  7. ACK(数据应答)
  8. Stop

遇到NACK直接丢弃本组,判定通信失败,不生成解析文本。

3. 字符串提取工具

时序字符串拆分示例:

  • Address write: AC→ 截取冒号后内容AC0xAC
  • Data write: 80→ 截取冒后800x80

四、运行效果示例

原始txt时序片段

58,1327970600.00,Address write: AC 59,1328044200.00,Write 60,1328054600.00,NACK 61,1328072200.00,Stop 62,1328079000.00,Start 63,1328086200.00,Address write: A0 64,1328159800.00,Write 65,1328170200.00,ACK 66,1328180800.00,Data write: 80 67,1328264800.00,ACK 68,1328275400.00,Data write: 00 69,1328359400.00,ACK 70,132837700.00,Stop

程序解析输出(自动过滤NACK失败帧)

【写】从机0xA0 寄存器0x80 写入:0x00

五、拓展优化(按需添加)

  1. 新增导出按钮:增加保存解析结果按钮,将rtb里全部文本输出到新txt;
  2. 区分读/写帧:新增Address read:判断,增加【读】格式输出;
  3. 多字节写入支持:当前仅支持单字节写入,若一条时序多个Data write,可循环拼接多组数据;
  4. 异常日志:把NACK通信失败帧单独列出,方便调试硬件通信故障;
  5. 路径记忆:记录上次选择的txt文件夹,不用重复浏览。

六、操作步骤给上级汇报话术(简洁版)

  1. 使用VS新建WinForm C#项目,粘贴上述代码;
  2. 界面放置解析按钮+结果文本框;
  3. 点击按钮,弹窗选择I2C时序txt日志;
  4. 程序自动按Start~Stop分割每条I2C传输帧,提取从机、寄存器、写入数据;
  5. 过滤NACK通信失败记录,生成统一规范的【写】格式化文本,可直接复制/导出文件。

结论:这条I2C传输写入失败

一、逐行拆解这段时序完整流程

57,1327963400.00,Start // 发起I2C起始信号,准备通信 58,1327970600.00,Address write: AC // 主机发送从机地址0xAC(写指令) 59,1328044200.00,Write // 主机持续拉低SDA,传输地址字节 60,1328054600.00,NACK // 关键:从机0xAC没有回复应答 61,1328072200.00,Stop // 主机检测到无应答,直接终止本次传输

二、I2C基础规则说明

  1. 正常通信逻辑:
    主机发完从机地址后,从机必须拉低SDA发出ACK应答,代表:
    「我在线、收到地址,可以继续接收寄存器/数据」。
  2. NACK无应答代表几种故障:
  • 总线上不存在0xAC这个从机芯片;
  • 芯片供电/硬件损坏,无法响应I2C;
  • 总线SDA/SCL短路、接触不良;
  • 芯片被锁定、未上电,拒绝通信。

三、对你解析程序的影响

这段时序在代码里会被直接丢弃,不会生成【写】格式化输出
因为缺少ACK应答,没有后续寄存器地址、写入数据的传输动作,整条帧判定为无效失败帧。

补充对比(成功的写时序参考)

成功帧一定会在Address write: XX后紧跟ACK,之后才会发送寄存器、写入数据:

Start Address write: A0 Write ACK // 从机正常应答 Data write: 80 ACK Data write: 00 ACK Stop

超详细分步教程(零基础,VS WinForm C# I2C日志解析工具)

最终界面布局:

  1. 左侧文本框:显示选中的TXT文件完整路径
  2. 【选择日志文件】按钮:弹出窗口挑选i2c日志txt
  3. 【开始解析并导出结果】按钮:解析+自动生成解析txt保存到同目录I2C_解析结果文件夹
  4. 右侧大文本框:实时预览解析后的内容

一、前期准备:安装 Visual Studio

  1. 打开VS安装程序,勾选.NET Framework Windows 窗体应用(.NET Framework)
  2. 安装完成后启动VS,选择【创建新项目】

步骤1:新建Windows窗体应用项目

  1. 首页点击【创建新项目】
  2. 搜索:Windows 窗体应用 (.NET Framework)选中,下一步
  3. 项目名称自定义:I2CLogAnalyzer,选择存放文件夹,点击创建
  4. 等待自动生成默认Form1窗口

步骤2:拖拽界面控件(直接照着拖)

打开左侧【工具箱】,把下面控件拖到Form1窗体,调整位置:

控件类型控件名称(Name)显示文本(Text)作用
TextBoxtxtFilePath(空)左侧,展示选中文件路径
ButtonbtnSelectFile选择I2C日志txt打开文件选择框
ButtonbtnParseExport解析并导出结果执行解析+生成txt
RichTextBoxrtbResult(空)右侧预览解析内容

布局简单参考

[txtFilePath文本框] [btnSelectFile按钮] [btnParseExport按钮] [ rtbResult 大预览框 占下方大面积 ]

步骤3:替换窗体完整代码

  1. 双击窗体空白处,自动进入Form1_Load代码页面
  2. 全选系统自动生成的所有代码,全部删除
  3. 复制下面整套完整代码粘贴进去
usingSystem;usingSystem.Collections.Generic;usingSystem.IO;usingSystem.Windows.Forms;namespaceI2CLogAnalyzer{publicpartialclassForm1:Form{publicForm1(){InitializeComponent();}// 【选择日志文件】按钮点击事件privatevoidbtnSelectFile_Click(objectsender,EventArgse){OpenFileDialogopenDialog=newOpenFileDialog();openDialog.Filter="文本文件(*.txt)|*.txt|所有文件(*.*)|*.*";openDialog.Title="选择I2C时序日志txt文件";if(openDialog.ShowDialog()==DialogResult.OK){// 将选中文件路径填入左侧文本框txtFilePath.Text=openDialog.FileName;rtbResult.Clear();// 清空上次预览内容}}// 【解析并导出结果】按钮点击事件privatevoidbtnParseExport_Click(objectsender,EventArgse){stringsourceTxtPath=txtFilePath.Text.Trim();// 判断是否选择了文件if(string.IsNullOrEmpty(sourceTxtPath)||!File.Exists(sourceTxtPath)){MessageBox.Show("请先选择有效的I2C日志txt文件!","提示",MessageBoxButtons.OK,MessageBoxIcon.Warning);return;}// 1. 读取原始日志全部行string[]allLines=File.ReadAllLines(sourceTxtPath);List<string>singleFrameBuffer=newList<string>();// 缓存单段Start~Stop时序List<string>outputList=newList<string>();// 存储最终解析文本foreach(stringlineinallLines){stringtrimLine=line.Trim();if(string.IsNullOrWhiteSpace(trimLine))continue;// 按逗号分割:行号,时间戳,时序指令string[]splitData=trimLine.Split(',');if(splitData.Length<3)continue;stringcmdText=splitData[2].Trim();singleFrameBuffer.Add(cmdText);// 遇到Stop代表一整段I2C传输结束,开始解析if(cmdText=="Stop"){stringparseResult=ParseI2CFrame(singleFrameBuffer);if(!string.IsNullOrEmpty(parseResult)){outputList.Add(parseResult);}singleFrameBuffer.Clear();// 清空缓存,接收下一段时序}}// 2. 预览解析内容到右侧文本框rtbResult.Clear();foreach(variteminoutputList){rtbResult.AppendText(item+Environment.NewLine);}// 3. 自动创建导出文件夹:原文件同目录下 I2C_Analysis_OutputstringsourceDir=Path.GetDirectoryName(sourceTxtPath);stringsaveFolder=Path.Combine(sourceDir,"I2C_Analysis_Output");if(!Directory.Exists(saveFolder)){Directory.CreateDirectory(saveFolder);}// 拼接导出文件名称stringsourceFileName=Path.GetFileNameWithoutExtension(sourceTxtPath);stringexportFileName=$"{sourceFileName}_analysis_result.txt";stringfullExportPath=Path.Combine(saveFolder,exportFileName);// 写入txt文件File.WriteAllLines(fullExportPath,outputList);MessageBox.Show($"解析完成!\n文件已导出至:\n{fullExportPath}","导出成功",MessageBoxButtons.OK,MessageBoxIcon.Information);}/// <summary>/// 解析单段Start~Stop时序,区分读/写,成功返回格式化文本,失败返回空/// </summary>privatestringParseI2CFrame(List<string>frameCmds){stringslaveAddr=null;// I2C从机地址stringregAddr=null;// 寄存器地址stringdataVal=null;// 读出/写入的数据boolisReadOp=false;// true=读操作 false=写操作boolhasNack=false;foreach(stringcmdinframeCmds){// 出现NACK,本次传输直接失效if(cmd.Contains("NACK")){hasNack=true;break;}// 区分 读地址 / 写地址if(cmd.StartsWith("Address write:")){stringaddrStr=cmd.Split(':')[1].Trim();slaveAddr=addrStr;isReadOp=false;}elseif(cmd.StartsWith("Address read:")){stringaddrStr=cmd.Split(':')[1].Trim();slaveAddr=addrStr;isReadOp=true;}// 处理写数据 Data writeelseif(cmd.StartsWith("Data write:")){stringdataStr=cmd.Split(':')[1].Trim();// 第一条Data write = 寄存器地址if(regAddr==null)regAddr=dataStr;elsedataVal=dataStr;}// 处理读数据 Data readelseif(cmd.StartsWith("Data read:")){stringdataStr=cmd.Split(':')[1].Trim();dataVal=dataStr;}}// 存在NACK / 关键信息缺失 → 无效帧,不输出if(hasNack||slaveAddr==null||regAddr==null||dataVal==null)returnnull;// 区分读、写输出格式if(isReadOp){return$"【读】从机0x{slaveAddr}寄存器0x{regAddr}读出:0x{dataVal}";}else{return$"【写】从机0x{slaveAddr}寄存器0x{regAddr}写入:0x{dataVal}";}}}}

步骤4:绑定按钮点击事件(必须做,否则点击无反应)

  1. 返回窗体设计界面(顶部标签Form1[设计]
  2. 双击【选择I2C日志txt】按钮,自动生成绑定代码
  3. 再双击【解析并导出结果】按钮,自动绑定第二个事件
  4. 现在可以点顶部【启动调试】(绿色▶按钮)运行程序测试

步骤5:程序使用操作流程

  1. 运行程序,点击左侧【选择I2C日志txt】
  2. 找到你的I2C时序日志txt,选中打开 → 左侧文本框显示文件路径
  3. 点击【解析并导出结果】
  4. 右侧大框实时展示所有成功写入的记录,带NACK失败帧自动过滤
  5. 自动在原txt同一文件夹新建文件夹I2C_解析结果,生成原文件名_解析输出.txt
  6. 弹窗提示导出完成,直接打开文件夹就能拿到结果文件

测试样例验证

测试时序(失败帧,NACK会被过滤)

57,1327963400.00,Start 58,1327970600.00,Address write: AC 59,1328044200.00,Write 60,1328054600.00,NACK 61,1328072200.00,Stop

程序不会生成这条记录。

测试时序(成功帧,正常输出)

62,132807900.00,Start 63,1328086200.00,Address write: A0 64,1328159800.00,Write 65,1328170200.00,ACK 66,1328180800.00,Data write: 80 67,1328264800.00,ACK 68,1328275400.00,Data write: 00 69,1328359400.00,ACK 70,132837700.00,Stop

导出txt内输出:
【写】从机0xA0 寄存器0x80 写入:0x00

补充:打包成独立exe发给同事使用

  1. VS顶部菜单栏:【生成】→【发布I2C日志解析工具】
  2. 发布目标选择【文件夹】,下一步
  3. 配置选择【独立】(无需对方安装.NET框架)
  4. 完成发布,输出文件夹内exe就是独立程序,直接双击打开使用。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询