C 按位或返回不正确的值
C bitwise OR is returning incorrect value
我有一个 void 函数,它应该设置 32 位寄存器的前 8 位。但是,它一直返回不正确的值(仅 2 的幂)。
void ugvPwm_setSpeed(ugv_pwm *InstancePtr, u8 spd_val)
{
u32 reg_read;
u32 spd_sel;
reg_read = MOTORPWM_mReadReg(InstancePtr->RegBaseAddress,
MOTORPWM_S00_AXI_SLV_REG0_OFFSET); // read original register value
//
xil_printf("\r\n\nugvPwm_setSpeed: reg0 = %x\r\n", reg_read);
xil_printf("ugvPwm_setSpeed: duty = %x\r\n", (u32) spd_val);
spd_sel = reg_read | (u32) spd_val; // bitwise OR in new value; PROBLEM HERE!
xil_printf("ugvPwm_setSpeed: new reg0 (reg0 | duty) = %x\r\n\n", spd_sel);
//
InstancePtr->speedSelect = spd_val;
MOTORPWM_mWriteReg(InstancePtr->RegBaseAddress, MOTORPWM_S00_AXI_SLV_REG0_OFFSET, spd_sel);
}
我平台上的u32和u8分别对应unsigned int和unsigned char。我已经使用 unsigned int 和 unsigned char 使用 onlinegdb 进行了尝试,并且效果很好。我平台上的输出如下所示:
ugvPwm_setSpeed: reg0 = 300
ugvPwm_setSpeed: duty = 1
ugvPwm_setSpeed: new reg0 (reg0 | duty) = 301
ugvPwm_setSpeed: expected = 301
ugvPwm_setSpeed: reg0 = 301
ugvPwm_setSpeed: duty = 2
ugvPwm_setSpeed: new reg0 (reg0 | duty) = 303
ugvPwm_setSpeed: expected = 302
ugvPwm_setSpeed: reg0 = 303
ugvPwm_setSpeed: duty = 3
ugvPwm_setSpeed: new reg0 (reg0 | duty) = 303
ugvPwm_setSpeed: expected = 303
ugvPwm_setSpeed: reg0 = 303
ugvPwm_setSpeed: duty = 4
ugvPwm_setSpeed: new reg0 (reg0 | duty) = 307
ugvPwm_setSpeed: expected = 304
ugvPwm_setSpeed: reg0 = 307
ugvPwm_setSpeed: duty = 5
ugvPwm_setSpeed: new reg0 (reg0 | duty) = 307
ugvPwm_setSpeed: expected = 305
ugvPwm_setSpeed: reg0 = 307
ugvPwm_setSpeed: duty = 6
ugvPwm_setSpeed: new reg0 (reg0 | duty) = 307
ugvPwm_setSpeed: expected = 306
ugvPwm_setSpeed: reg0 = 307
ugvPwm_setSpeed: duty = 7
ugvPwm_setSpeed: new reg0 (reg0 | duty) = 307
ugvPwm_setSpeed: expected = 307
ugvPwm_setSpeed: reg0 = 307
ugvPwm_setSpeed: duty = 8
ugvPwm_setSpeed: new reg0 (reg0 | duty) = 30F
ugvPwm_setSpeed: expected = 308
ugvPwm_setSpeed: reg0 = 30F
ugvPwm_setSpeed: duty = 9
ugvPwm_setSpeed: new reg0 (reg0 | duty) = 30F
ugvPwm_setSpeed: expected = 309
如果您尝试将 lowest-order 8 位设置为特定值,bitwise-or 不会这样做。 Bitwise-or 基本上是一个“一位累加器”——一旦一位被设置为 1,所有 bitwise-or 操作将保留 1
位值。
您需要清除 low-order 8 位:
u32 clearLowOrderBitsMask = ~( ( u32 ) 0xFF );
spd_sel = reg_read & clearLowOrderBitsMask;
通过使用按位 和 来保持高 24 位,方法是对所有 1
的高 24 位执行 bitwise-and 来保持高 24 位。位,并通过对所有零位执行 bitwise-and 来清除 lower-order 8 个字节。
然后你可以设置位:
spd_sel = reg_read | (u32) spd_val;
我有一个 void 函数,它应该设置 32 位寄存器的前 8 位。但是,它一直返回不正确的值(仅 2 的幂)。
void ugvPwm_setSpeed(ugv_pwm *InstancePtr, u8 spd_val)
{
u32 reg_read;
u32 spd_sel;
reg_read = MOTORPWM_mReadReg(InstancePtr->RegBaseAddress,
MOTORPWM_S00_AXI_SLV_REG0_OFFSET); // read original register value
//
xil_printf("\r\n\nugvPwm_setSpeed: reg0 = %x\r\n", reg_read);
xil_printf("ugvPwm_setSpeed: duty = %x\r\n", (u32) spd_val);
spd_sel = reg_read | (u32) spd_val; // bitwise OR in new value; PROBLEM HERE!
xil_printf("ugvPwm_setSpeed: new reg0 (reg0 | duty) = %x\r\n\n", spd_sel);
//
InstancePtr->speedSelect = spd_val;
MOTORPWM_mWriteReg(InstancePtr->RegBaseAddress, MOTORPWM_S00_AXI_SLV_REG0_OFFSET, spd_sel);
}
我平台上的u32和u8分别对应unsigned int和unsigned char。我已经使用 unsigned int 和 unsigned char 使用 onlinegdb 进行了尝试,并且效果很好。我平台上的输出如下所示:
ugvPwm_setSpeed: reg0 = 300
ugvPwm_setSpeed: duty = 1
ugvPwm_setSpeed: new reg0 (reg0 | duty) = 301
ugvPwm_setSpeed: expected = 301
ugvPwm_setSpeed: reg0 = 301
ugvPwm_setSpeed: duty = 2
ugvPwm_setSpeed: new reg0 (reg0 | duty) = 303
ugvPwm_setSpeed: expected = 302
ugvPwm_setSpeed: reg0 = 303
ugvPwm_setSpeed: duty = 3
ugvPwm_setSpeed: new reg0 (reg0 | duty) = 303
ugvPwm_setSpeed: expected = 303
ugvPwm_setSpeed: reg0 = 303
ugvPwm_setSpeed: duty = 4
ugvPwm_setSpeed: new reg0 (reg0 | duty) = 307
ugvPwm_setSpeed: expected = 304
ugvPwm_setSpeed: reg0 = 307
ugvPwm_setSpeed: duty = 5
ugvPwm_setSpeed: new reg0 (reg0 | duty) = 307
ugvPwm_setSpeed: expected = 305
ugvPwm_setSpeed: reg0 = 307
ugvPwm_setSpeed: duty = 6
ugvPwm_setSpeed: new reg0 (reg0 | duty) = 307
ugvPwm_setSpeed: expected = 306
ugvPwm_setSpeed: reg0 = 307
ugvPwm_setSpeed: duty = 7
ugvPwm_setSpeed: new reg0 (reg0 | duty) = 307
ugvPwm_setSpeed: expected = 307
ugvPwm_setSpeed: reg0 = 307
ugvPwm_setSpeed: duty = 8
ugvPwm_setSpeed: new reg0 (reg0 | duty) = 30F
ugvPwm_setSpeed: expected = 308
ugvPwm_setSpeed: reg0 = 30F
ugvPwm_setSpeed: duty = 9
ugvPwm_setSpeed: new reg0 (reg0 | duty) = 30F
ugvPwm_setSpeed: expected = 309
如果您尝试将 lowest-order 8 位设置为特定值,bitwise-or 不会这样做。 Bitwise-or 基本上是一个“一位累加器”——一旦一位被设置为 1,所有 bitwise-or 操作将保留 1
位值。
您需要清除 low-order 8 位:
u32 clearLowOrderBitsMask = ~( ( u32 ) 0xFF );
spd_sel = reg_read & clearLowOrderBitsMask;
通过使用按位 和 来保持高 24 位,方法是对所有 1
的高 24 位执行 bitwise-and 来保持高 24 位。位,并通过对所有零位执行 bitwise-and 来清除 lower-order 8 个字节。
然后你可以设置位:
spd_sel = reg_read | (u32) spd_val;