将unsigned存储在unsigned int的低16位中

时间:2011-09-16 14:32:25

标签: c embedded integer-promotion

我正在嵌入式系统上编程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之后,我最终存储了一个正值,因此我实际上并没有遇到我在测试中期待的问题。

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

4 个答案:

答案 0 :(得分:4)

而不是unsigned int,定义unsigned int和2个short signed int的联合。

这就是我在ARM系统中处理“有趣的硬件控制寄存器”的方式,在这种情况下,这里和那里的奇数位通常都是“不关心”或“不能写入1”。

RGDS, 马丁

答案 1 :(得分:4)

想想16位中的-16(例如)是什么样的:'0xFFF0',以及33位:'0xFFFFFFF0'。符号扩展正是您希望确保在正确的位置有一个符号位。由于鞋帮16不在乎,所以可以用1来填充它们。因此,创建一个带符号的32位值,然后将其转换为无符号32以放入您的寄存器:

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

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

答案 2 :(得分:0)

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

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

CTRL_REG = -2 * calibrationValue;

请注意,CTRL_REG现在被声明为签名整数。

答案 3 :(得分:0)

#define SS2L(sh,sl) ( ((sh) <<16) | ((sl) & 0xffff) )

将两个16位短路组合成一个32位长。

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