代码之家  ›  专栏  ›  技术社区  ›  jhe4x

C按位OR返回的值不正确

  •  0
  • jhe4x  · 技术社区  · 3 年前

    我有一个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分别对应于无符号int和无符号char。我尝试过使用onlinegdb,使用unsigned int和unsigned char,效果非常好。我的平台上的输出如下所示:

    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
    
    1 回复  |  直到 3 年前
        1
  •  1
  •   Andrew Henle    3 年前

    如果你想 设置 将最低阶8位转换为特定值(按位或按位),则不会执行此操作。按位or基本上是一个“一位累加器”——一旦一位被设置为一,所有按位or操作都将保留 1 位值。

    你需要 清楚的 低阶8位:

    u32 clearLowOrderBitsMask = ~( ( u32 ) 0xFF );
    spd_sel = reg_read & clearLowOrderBitsMask;
    

    这是通过使用位来实现的- 通过按位执行and操作,保持高位24位与之前一样,并对高位24位执行all 1. 位,它通过对所有零位执行按位and来清除低位8字节。

    然后可以设置位:

    spd_sel = reg_read | (u32) spd_val;