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;