常州市网站建设_网站建设公司_Photoshop_seo优化
2026/1/8 20:29:29 网站建设 项目流程

STM32嵌入式:如何使用keil 来获取flash块数据并转换成可视化的数据 来判断源头数据是否错误

比较实用的实战步骤,分三部分讲:

  • 在 Keil 里怎么看到/导出 Flash 数据
  • 怎么把原始 16 位补码数据“转成”我们能看懂的波形
  • 怎么对比“Flash 源头数据”和“你解析出来的数据”,判断解析是否错误
    中间用一点伪命令,你按自己芯片型号和工程改一下就行。

一、整体流程示意(先有个整体感)

简单来说,你可以按下面这个思路来:

1. Keil 进入调试模式
2. 在 Memory 窗口查看 Flash 数据
3. 用 SAVE 命令导出 Flash 块到 HEX 文件
4. HEX 转 数组/CSV
5. 用脚本做补码转换(16 位)
6. 用 Excel/Matlab/Python 画波形
7. 对比 Flash 源头数据 与 代码解析后数据
判断源头/解析是否错误

二、在 Keil 中查看并导出 Flash 数据

1. 调试状态下打开 Memory 窗口

  • 在 Keil 中:
    • 点击 “Debug” → “Start/Stop Debug Session”(或 Ctrl+F5)进入调试
    • 菜单 “View” → “Memory Windows” → “Memory 1/2/3/4”,打开一个内存窗口
  • 在 Memory 窗口的 “Address” 输入栏里填你要看的那块 Flash 地址,例如:
    • 0x08000000(STM32 的 Flash 起始地址,按你芯片的实际情况来)
  • 回车后,下面就会显示一段原始字节内容,形如:
    • 0x08000000 03 1F 03 3B 01 AD 01 15 ...
      如果你的 Flash 数据已经是一些“采样数据”写死在里面(比如 const 数组),你会在 Memory 窗口里看到它们以字节形式排布。

2. 确认数组/变量的地址

如果数据是以某个常量数组存在代码里,比如:

  • 代码中定义:
    • const int16_t flash_wave[128] = { ... };
      那么在调试时:
  • 打开 “View” → “Watch Windows” → “Watch 1”
  • 在 Watch 窗口里输入flash_wave,Keil 会显示:
    • 这个数组的起始地址(比如0x08001234
    • 数组里各个位置的值(如果显示格式对的话)
      你可以记下这个起始地址和长度,然后直接用 Memory 窗口看同一块区域。

3. 使用 SAVE 命令导出一段 Flash 到文件(重点)

Keil 的调试命令行(Debug → Command 窗口)支持 SAVE 命令,可以把一段内存内容导出为 Intel HEX 文件:

  • 在 Command 窗口输入(示例):
    SAVE flash_block.hex 0x08000000, 0x08000400
    参数含义:
    • flash_block.hex:你要保存的文件名(默认在工程目录)
    • 0x08000000:起始地址
    • 0x08000400:结束地址(导出0x08000000~0x080003FF这一段)
      注意:这里写的是“结束地址”,不是“长度”。
  • SAVE 命令说明文档里讲的是:将内存区域以 HEX386 格式写入文件。
    这样你就有了一份“从 Flash 里原封不动导出来”的数据文件。

三、把 HEX 转成数组/CSV,并做 16 位补码转换

现在你拿到了flash_block.hex,但它是 HEX 格式,不方便直接画图,一般做法是:

  • 要么用在线工具 / 小工具把 HEX 转成二进制 / C 数组 / CSV
  • 要么直接用 Python/C 脚本解析 HEX 文件并做补码转换
    这里给你一个最通用、可自动化的做法:用 Python 脚本一次性做完“解析 HEX + 补码转换 + 生成 CSV”。
    假设:
  • 你的原始采样数据是 16 位,按“小端模式(Little Endian)”存在 Flash 中(STM32 这类常见)
  • 地址0x08000000开始是:
    • 0x03 0x1F 0x03 0x3B 0x01 0xAD ...
  • 对应的 16 位有符号值是:
    • 0x1F030x3B030xAD01

示例:Python 脚本解析 HEX + 转 16 位有符号 + 生成 CSV

你可以建一个parse_hex.py

importintelheximportcsv# 输入 Keil 导出的 HEX 文件hex_file="flash_block.hex"csv_file="flash_wave.csv"start_addr=0x08000000end_addr=0x08000400# 和 SAVE 命令的结束地址一致ih=intelhex.IntelHex(hex_file)values=[]addr=start_addrwhileaddr<end_addr:# 小端模式:低字节在前,高字节在后low=ih[addr]high=ih[addr+1]u16=(high<<8)|low# 组合成 16 位无符号整数# 转为 16 位有符号(补码)ifu16&0x8000:i16=u16-0x10000else:i16=u16 values.append(i16)addr+=2# 每次跳 2 字节# 写入 CSV(只有一列,就是转换后的值)withopen(csv_file,"w",newline="")asf:writer=csv.writer(f)writer.writerow(["Index","Value"])# 表头fori,vinenumerate(values):writer.writerow([i,v])print(f"Done. Written{len(values)}samples to{csv_file}.")

需要先安装intelhex库:

pipinstallintelhex

运行脚本后,你会得到flash_wave.csv,里面形如:

Index,Value 0,192 1,315 2,429 3,533 ...

这个Value就是你“Flash 源头数据 + 16 位补码转换”之后的真实波形值。

四、可视化成波形,和你的解析结果对比

有了 CSV 之后,你可以用三种常用方式可视化。

1)用 Excel 快速看趋势

  • 直接用 Excel 打开flash_wave.csv
  • 选中两列数据,插入“折线图”
  • 看一下:
    • 波形是否类似正弦/三角/你预期的信号
    • 有没有奇怪的跳变(比如从几百突然跳到几千)
      这一步主要用来判断“源头数据本身是不是就乱”。

2)用 Python + Matplotlib 画更漂亮的波形

importcsvimportmatplotlib.pyplotasplt xs=[]ys=[]withopen("flash_wave.csv")asf:reader=csv.DictReader(f)forrowinreader:xs.append(int(row["Index"]))ys.append(int(row["Value"]))plt.figure(figsize=(10,4))plt.plot(xs,ys,marker='o',markersize=3,linestyle='-')plt.title("Flash Waveform (signed 16-bit)")plt.xlabel("Sample Index")plt.ylabel("Amplitude")plt.grid(True)plt.tight_layout()plt.show()

这样你可以很清楚地看到:

  • 是否是连续平滑的波形
  • 在 0 附近是否正确跨越正负(例如从几十到负几十,而不是从几十跳到 65471)

3)和“你的代码解析结果”对比(判断是否解析错误)

你前面有一段从data里解析通道数据并做twos_comp的代码。你可以:

  • 在 Keil 调试时:
    • 在 Watch 窗口添加wavedata.channelValue[curchanneltmp][0]lenOfChannel等,实时查看解析后的数组。
    • 或在调试过程中执行类似的SAVE命令,把解析后的数组所在内存也导出一份 HEX/CSV。
  • 然后画在同一张图上对比:
    • 曲线 A:直接从 Flash 导出 + 正确补码转换(“标准答案”)
    • 曲线 B:你的代码解析出来的数据
      对比时看几个点:
  • 形状是否一致(正弦/方波/三角等)
  • 幅值是否一致
  • 有没有“多出一些奇怪的点”或“整体平移/翻转”
  • 特别检查从正到负的过渡区域(例如你之前那组 60 → 65471)
    如果形状明显不一样,大部分是你代码里:
  • 通道号/索引用错
  • 数据长度算错
  • 高低位字节搞反
  • 没有做补码转换或转换方式不对

五、几个常见坑和检查点

1)大小端模式

  • 很多 ARM MCU(STM32 等)是小端:
    • 低字节在低地址,高字节在高地址
  • 如果你误用大端解析,波形会变得完全不对(幅值、噪声都异常)
  • 可以在 Memory 窗口先看几个典型点的字节分布:
    • 如果 Flash 中是01 FC,预期值大概是 0xFC01
    • 如果你解析出 0x01FC,说明大小端反了

2)数据类型 & 步长

  • 如果你的数据实际是:
    • 16 位有符号:用 int16_t,步长 = 2 字节
    • 32 位有符号/浮点:步长 = 4 字节
  • 步长错了,会导致解析错位(比如把高/低字拼到相邻采样上)

3)数组边界 / 通道切换

  • 你之前的代码里curchanneltmpmaxchannel等逻辑,如果在 Flash 里有多个通道连续排布:
    • 需要确认每个通道的起始地址和长度
    • 不然容易把两个通道的数据拼在一起,看起来像奇怪的折线

4)如果只是简单确认 Flash 数据是不是“写死”得对

  • 直接在 Keil 里:
    • 打开 Watch 窗口,添加数组变量
    • 看它的值是不是你预期
    • 再对比一下 Memory 窗口同一位置的字节
  • 如果两者都对,那问题基本就出在“接收/解析”逻辑,而不是 Flash 源头。

六、小结:推荐的实战步骤

给出一个简单可照抄的流程:

  1. 在 Keil 里调试,Memory 窗口定位到你的 Flash 数组起始地址(比如0x08001000
  2. 用 Command 窗口执行:
    SAVE flash_block.hex 0x08001000 0x08001200
    导出这块数据到 HEX 文件
  3. 用 Python 解析这个 HEX 文件,按 16 位小端 + 补码转换,生成flash_wave.csv
  4. 用 Excel/Matlab/Python 画出波形,确认是否像你预期的正弦/三角等信号
  5. 同时,在 Keil 调试中导出你代码解析出来的数组(也可以用 SAVE 或 watch+复制),按相同方式画出来
  6. 把两张图叠在一起对比:
    • 完全一致:说明解析没问题,源头数据也 OK
    • 不一致:根据差异点反推:
      • 波形整体平移/翻转 → 大小端或符号位有问题
      • 多出跳变、毛刺 → 通道/长度/索引处理有误
      • 某一段完全乱掉 → 可能是多通道混在一起或数组指针错

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

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

立即咨询