5

我正在嵌入式系统上编写 C 语言。处理器架构是 32 位(sizeof(int)就是 32 位,sizeof(short)就是 16 位)。有一个 32 位变量是一个内存映射控制寄存器 ( CTRL_REG),它被指定为仅使用的低 16 位,它们包含一个带符号的 16 位整数值(写入高位无效)。内存访问必须是 32 位对齐的,所以我不能只将指针撞到几个字节上,也不能假设字节序。我担心自动类型提升会通过将符号位扩展到第 31 位而不是将其留在我想要的第 15 位来弄乱我存储的任何内容。在这个位置存储东西的最佳方式是什么?

这是我的原始代码,我几乎可以肯定它是错误的:

#define CTRL_REG   *((volatile unsigned int *)0x4000D008u)
short calibrationValue;

CTRL_REG = -2 * calibrationValue;

然后我尝试了这个,但我认为它仍然可能在分配时受到整数提升:

CTRL_REG = (short)(-2 * calibrationValue);

然后最后我想到了这个:

CTRL_REG = (unsigned short)(short)(-2 * calibrationValue);

我不能很好地评估这些选项,因为它们都在我的测试中起作用,因为calibrationValue恰好是负数(它是每个设备特定的校准参数,因此在某些设备上可能是正数),所以在乘以 -2 后,我结束up 存储一个正值,因此我实际上并没有遇到我在测试中期望的问题。

非常感谢您的帮助,即使只是说“您想太多了”。

4

4 回答 4

4

代替无符号整数,定义一个无符号整数和 2 个短符号整数的并集。

这就是我在我的 ARM 系统上处理“有趣的硬件控制寄存器”的方式,其中经常出现“不关心”或“不能写入 1”的奇数位。

Rgds,马丁

于 2011-09-16T14:46:27.743 回答
4

想想 -16(例如)在 16 位:'0xFFF0' 和 33 位:'0xFFFFFFF0' 中的样子。符号扩展正是您想要确保您在正确的位置有一个符号位。由于上面的 16 位是无关紧要的,因此可以用 1 填充它们。因此,创建一个带符号的 32 位值,然后将其转换为无符号 32 以放入您的寄存器中:

  Int32 calreg= -2L * calibrationValue;
   CTRl_REG = (Uint32)calreg;

如果您希望将 0 写入高位,请在强制转换之前使用 0xFFFF 进行掩码。

于 2011-09-16T14:47:46.867 回答
0

如果写入最高有效 16 位的值被忽略,我认为您可以安全地依赖类型转换。总而言之,你不关心更高的位。

#define CTRL_REG   *((volatile signed int *)0x4000D008u)
short calibrationValue;

CTRL_REG = -2 * calibrationValue;

请注意,CTRL_REG 现在被声明为有符号整数。

于 2011-09-16T14:37:55.263 回答
0
#define SS2L(sh,sl) ( ((sh) <<16) | ((sl) & 0xffff) )

将两条 16 位短裤组合成一条 32 位长。

最好使用无符号类型来完成 bitops;提升到 int 可以抓住你。也许也可以在上面的宏中添加一些额外的强制转换。

于 2011-09-16T14:41:43.033 回答