【发布时间】:2019-04-27 14:38:20
【问题描述】:
我正在为光谱学编写嵌入式代码。 为了构建我的光谱,我需要将一个区间(动态范围由问题的物理/规格给出)线性映射到另一个。基本上在处理数据后,我有一系列样本(峰值),每个样本都会对频谱有所贡献(即会增加直方图中特定 bin 的计数器)。 这是一个草图: 所以在 C 语言中,我需要将每个峰值映射到 [0:4095] 中,并且我在 MCU (LPC4370) 上实时执行此操作,因此我需要快速进行。 问题是我的愚蠢实现将所有内容都压缩为 0。 这就是我所做的:
#define MCA_SIZE 4096
#define PEAK_MAX 1244672762
#define PEAK_MIN 6000000
int32_t mca[MCA_SIZE];
int32_t peak_val;
int32_t bin_val;
[...]
if(peak_val > PEAK_MIN)
{
bin_val = (int)(MCA_SIZE*(peak_val-PEAK_MIN)/(PEAK_MAX-PEAK_MIN));
/*Increment corrispondent multi channel bin*/
mca[bin_val]+=1;
};
如果是小写,每个数量都是 int32,#define 是大写。问题是相信这个
(peak_val-PEAK_MIN)/(PEAK_MAX-PEAK_MIN)
经常接近于零。 所以我最终只装满了前一两个箱子。
这是正在研究的代码的分解视图,以及断点处的寄存器状态。
处理此类问题的最佳/最快方法是什么?
【问题讨论】:
-
为什么在计算
bin_val之后使用mca[peak_val/1000]+=1;?我本来期望像++mca[bin_val];这样的东西。 -
你做得对。但是您正在寻找错误的错误位置。您的计算首先完成 MCA_SIZE*(peak_val-PEAK_MIN),然后是 /(PEAK_MAX-PEAK_MIN)。该顺序由标准保证,否则您将始终得到零。如果有疑问,您可以检查它的汇编代码。 (顺便说一句。如果你限制你的峰值也限制上限。)
-
@EOF 是的,抱歉我编辑了答案
-
对数范围是不可能的吗?您似乎可以使用 FPU。如果做不到这一点,那么 log2 函数在 ALU 上的速度相当快。
-
嗨@JohnMcFarlane,我需要线性映射。来自datasheet ARM Cortex-M4 实现了一个支持八个区域的内存保护单元、一个硬件浮点单元 (FPU)、调试功能和一个系统滴答计时器。 所以 FPU 就在那里.
标签: c embedded fixed-point integer-division