0

我有以下代码块:

// **** CONTROL REGISTER 4 SETUP ****
    ctrl|=(uint8_t)(LIS3DSH_InitStruct->CR4_Odr);
    if(LIS3DSH_InitStruct->CR4_Bdu)
        ctrl|=(1<<LIS3DSH_CR4_BDU_POSITION);
    if(LIS3DSH_InitStruct->CR4_Zen)
        ctrl|=(1<<LIS3DSH_CR4_Z_AXIS_POSITION);
    if(LIS3DSH_InitStruct->CR4_Yen)
        ctrl|=(1<<LIS3DSH_CR4_Y_AXIS_POSITION);
    if(LIS3DSH_InitStruct->CR4_Xen)
        ctrl|=(1<<LIS3DSH_CR4_X_AXIS_POSITION);
    LIS3DSH_Write(&ctrl,
                  LIS3DSH_CTRL_REG4_ADDR,
                  sizeof(ctrl));
    delay(1000000);
// **** END OF CONTROL REGISTER 4 SETUP ****

现在,我很确定这些 if 子句(因为这是嵌入式世界)可以用位操作技术代替,有人可以告诉我怎么做吗?我知道这是一个非常愚蠢的问题,但我只是忘记了这些事情......

这是具有结构的头文件:

#ifndef __STM32F4_DISCOVERY_LIS3DS_H
#define __STM32F4_DISCOVERY_LIS3DS_H

#include "stm32f4xx.h"

#define LIS3DSH_CTRL_REG1_ADDR  0x21
#define LIS3DSH_CTRL_REG2_ADDR  0x22
#define LIS3DSH_CTRL_REG3_ADDR  0x23
#define LIS3DSH_CTRL_REG4_ADDR  0x20
#define LIS3DSH_CTRL_REG5_ADDR  0x24
#define LIS3DSH_CTRL_REG6_ADDR  0x25

#define LIS3DSH_INFO1_REG_ADDR  0x0d
#define LIS3DSH_INFO2_REG_ADDR  0x0e
#define LIS3DSH_WHOAMI_REG_ADDR 0x0f

#define LIS3DSH_STATUS_REG_ADDR 0x27

#define LIS3DSH_TEMPERATURE_REG_ADDR    0x0c

#define LIS3DSH_OUT_X_L_REG_ADDR    0x28
#define LIS3DSH_OUT_X_H_REG_ADDR    0x29
#define LIS3DSH_OUT_Y_L_REG_ADDR    0x2a
#define LIS3DSH_OUT_Y_H_REG_ADDR    0x2b
#define LIS3DSH_OUT_Z_L_REG_ADDR    0x2c
#define LIS3DSH_OUT_Z_H_REG_ADDR    0x2d

#define LIS3DSH_FLAG_ZXYOR   ((uint8_t)0x00)
#define LIS3DSH_FLAG_ZOR     ((uint8_t)0x01)
#define LIS3DSH_FLAG_YOR     ((uint8_t)0x02)
#define LIS3DSH_FLAG_XOR     ((uint8_t)0x03)
#define LIS3DSH_FLAG_ZXYDA   ((uint8_t)0x04)
#define LIS3DSH_FLAG_ZDA     ((uint8_t)0x05)
#define LIS3DSH_FLAG_YDA     ((uint8_t)0x06)
#define LIS3DSH_FLAG_XDA     ((uint8_t)0x07)

#define DEVICE_ID   ((uint8_t)0x3f)

#define LIS3DSH_SM1_INT_TO_PIN_INT1 ((uint8_t)0x00)
#define LIS3DSH_SM1_INT_TO_PIN_INT2 ((uint8_t)0x01)

#define LIS3DSH_SM1_DISABLE ((uint8_t)0x00)
#define LIS3DSH_SM1_ENABLE  ((uint8_t)0x01)

#define LIS3DSH_SM2_INT_TO_PIN_INT1 ((uint8_t)0x00)
#define LIS3DSH_SM2_INT_TO_PIN_INT2 ((uint8_t)0x01)

#define LIS3DSH_SM2_DISABLE ((uint8_t)0x00)
#define LIS3DSH_SM2_ENABLE  ((uint8_t)0x01)

#define LIS3DSH_CR3_DREN_TO_INT1_DISABLE    ((uint8_t)0x00)
#define LIS3DSH_CR3_DREN_TO_INT1_ENABLE     ((uint8_t)0x01)

#define LIS3DSH_CR3_IEA_ACTIVE_LOW  ((uint8_t)0x00)
#define LIS3DSH_CR3_IEA_ACTIVE_HIGH ((uint8_t)0x01)

#define LIS3DSH_CR3_IEL_LATCHED ((uint8_t)0x00)
#define LIS3DSH_CR3_IEL_PULSED  ((uint8_t)0x01)

#define LIS3DSH_CR3_INT2_DISABLED   ((uint8_t)0x00)
#define LIS3DSH_CR3_INT2_ENABLED    ((uint8_t)0x01)

#define LIS3DSH_CR3_INT1_DISABLED   ((uint8_t)0x00)
#define LIS3DSH_CR3_INT1_ENABLED    ((uint8_t)0x01)

#define LIS3DSH_CR3_VFILT_DISABLED  ((uint8_t)0x00)
#define LIS3DSH_CR3_VFILT_ENABLED   ((uint8_t)0x01)

#define LIS3DSH_CR3_NO_SOFT_RESET   ((uint8_t)0x00)
#define LIS3DSH_CR3_SOFT_RESET      ((uint8_t)0x01)

#define LIS3DSH_CR4_ODR_POWER_DOWN  ((uint8_t)0x00)
#define LIS3DSH_CR4_ODR_3f125HZ     ((uint8_t)0x01)
#define LIS3DSH_CR4_ODR_6f25HZ      ((uint8_t)0x02)
#define LIS3DSH_CR4_ODR_12f5HZ      ((uint8_t)0x03)
#define LIS3DSH_CR4_ODR_25HZ        ((uint8_t)0x04)
#define LIS3DSH_CR4_ODR_50HZ        ((uint8_t)0x05)
#define LIS3DSH_CR4_ODR_100HZ       ((uint8_t)0x06)
#define LIS3DSH_CR4_ODR_400HZ       ((uint8_t)0x07)
#define LIS3DSH_CR4_ODR_800HZ       ((uint8_t)0x08)
#define LIS3DSH_CR4_ODR_1600HZ      ((uint8_t)0x09)

#define LIS3DSH_CR4_BDU_DISABLED    ((uint8_t)0x00)
#define LIS3DSH_CR4_BDU_ENABLED     ((uint8_t)0x01)
#define LIS3DSH_CR4_BDU_POSITION    ((uint8_t)0x04)

#define LIS3DSH_CR4_Z_AXIS_DISABLED ((uint8_t)0x00)
#define LIS3DSH_CR4_Z_AXIS_ENABLED  ((uint8_t)0x01)
#define LIS3DSH_CR4_Z_AXIS_POSITION ((uint8_t)0x05)

#define LIS3DSH_CR4_X_AXIS_DISABLED ((uint8_t)0x00)
#define LIS3DSH_CR4_X_AXIS_ENABLED  ((uint8_t)0x01)
#define LIS3DSH_CR4_X_AXIS_POSITION ((uint8_t)0x07)

#define LIS3DSH_CR4_Y_AXIS_DISABLED ((uint8_t)0x00)
#define LIS3DSH_CR4_Y_AXIS_ENABLED  ((uint8_t)0x01)
#define LIS3DSH_CR4_Y_AXIS_POSITION ((uint8_t)0x06)

#define LIS3DSH_CR5_BW_800HZ    ((uint8_t)0x00)
#define LIS3DSH_CR5_BW_400HZ    ((uint8_t)0x01)
#define LIS3DSH_CR5_BW_200HZ    ((uint8_t)0x02)
#define LIS3DSH_CR5_BW_50HZ     ((uint8_t)0x03)

#define LIS3DSH_CR5_FSCALE_2G   ((uint8_t)0x00)
#define LIS3DSH_CR5_FSCALE_4G   ((uint8_t)0x01)
#define LIS3DSH_CR5_FSCALE_6G   ((uint8_t)0x02)
#define LIS3DSH_CR5_FSCALE_8G   ((uint8_t)0x03)
#define LIS3DSH_CR5_FSCALE_16G  ((uint8_t)0x04)

#define LIS3DSH_CR5_ST_DISABLE      ((uint8_t)0x00)
#define LIS3DSH_CR5_ST_POSITIVE     ((uint8_t)0x01)
#define LIS3DSH_CR5_ST_NEGATIVE     ((uint8_t)0x02)
#define LIS3DSH_CR5_ST_NOT_ALLOWED  ((uint8_t)0x03)

#define LIS3DSH_CR5_MODE_4_WIRE_INTERFACE   ((uint8_t)0x00)
#define LIS3DSH_CR5_MODE_3_WIRE_INTERFACE   ((uint8_t)0x01)

#define LIS3DSH_CR6_FORCE_REBOOT_DISABLE    ((uint8_t)0x00)
#define LIS3DSH_CR6_FORCE_REBOOT_ENABLE     ((uint8_t)0x01)

#define LIS3DSH_CR6_FIFO_DISABLED   ((uint8_t)0x00)
#define LIS3DSH_CR6_FIFO_ENABLED    ((uint8_t)0x01)

#define LIS3DSH_CR6_WTM_DISABLED    ((uint8_t)0x00)
#define LIS3DSH_CR6_WTM_ENABLED     ((uint8_t)0x01)

#define LIS3DSH_CR6_ADDINC_DISABLED ((uint8_t)0x00)
#define LIS3DSH_CR6_ADDINC_ENABLED  ((uint8_t)0x01)

#define LIS3DSH_CR6_FIFO_EMPTY_TO_INT1_DISABLED ((uint8_t)0x00)
#define LIS3DSH_CR6_FIFO_EMPTY_TO_INT1_ENABLED  ((uint8_t)0x01)

#define LIS3DSH_CR6_FIFO_WTM_TO_INT1_DISABLED   ((uint8_t)0x00)
#define LIS3DSH_CR6_FIFO_WTM_TO_INT1_ENABLED    ((uint8_t)0x01)

#define LIS3DSH_CR6_FIFO_OVERRUN_TO_INT1_DISABLED   ((uint8_t)0x00)
#define LIS3DSH_CR6_FIFO_OVERRUN_TO_INT1_ENABLED    ((uint8_t)0x01)

#define LIS3DSH_CR6_BOOT_TO_INT2_DISABLED   ((uint8_t)0x00)
#define LIS3DSH_CR6_BOOT_TO_INT2_ENABLED    ((uint8_t)0x01)

#define LIS3DSH_SPI                       SPI1
#define LIS3DSH_SPI_CLK                   RCC_APB2Periph_SPI1

#define LIS3DSH_SPI_SCK_PIN               GPIO_Pin_5
#define LIS3DSH_SPI_SCK_GPIO_PORT         GPIOA
#define LIS3DSH_SPI_SCK_GPIO_CLK          RCC_AHB1Periph_GPIOA
#define LIS3DSH_SPI_SCK_SOURCE            GPIO_PinSource5
#define LIS3DSH_SPI_SCK_AF                GPIO_AF_SPI1

#define LIS3DSH_SPI_MISO_PIN              GPIO_Pin_6
#define LIS3DSH_SPI_MISO_GPIO_PORT        GPIOA
#define LIS3DSH_SPI_MISO_GPIO_CLK         RCC_AHB1Periph_GPIOA
#define LIS3DSH_SPI_MISO_SOURCE           GPIO_PinSource6
#define LIS3DSH_SPI_MISO_AF               GPIO_AF_SPI1

#define LIS3DSH_SPI_MOSI_PIN              GPIO_Pin_7
#define LIS3DSH_SPI_MOSI_GPIO_PORT        GPIOA
#define LIS3DSH_SPI_MOSI_GPIO_CLK         RCC_AHB1Periph_GPIOA
#define LIS3DSH_SPI_MOSI_SOURCE           GPIO_PinSource7
#define LIS3DSH_SPI_MOSI_AF               GPIO_AF_SPI1

#define LIS3DSH_SPI_CS_PIN                GPIO_Pin_3
#define LIS3DSH_SPI_CS_GPIO_PORT          GPIOE
#define LIS3DSH_SPI_CS_GPIO_CLK           RCC_AHB1Periph_GPIOE

#define LIS3DSH_SPI_INT1_PIN              GPIO_Pin_0
#define LIS3DSH_SPI_INT1_GPIO_PORT        GPIOE
#define LIS3DSH_SPI_INT1_GPIO_CLK         RCC_AHB1Periph_GPIOE
#define LIS3DSH_SPI_INT1_EXTI_LINE        EXTI_Line0
#define LIS3DSH_SPI_INT1_EXTI_PORT_SOURCE EXTI_PortSourceGPIOE
#define LIS3DSH_SPI_INT1_EXTI_PIN_SOURCE  EXTI_PinSource0
#define LIS3DSH_SPI_INT1_EXTI_IRQn        EXTI0_IRQn

#define LIS3DSH_SPI_INT2_PIN              GPIO_Pin_1
#define LIS3DSH_SPI_INT2_GPIO_PORT        GPIOE
#define LIS3DSH_SPI_INT2_GPIO_CLK         RCC_AHB1Periph_GPIOE
#define LIS3DSH_SPI_INT2_EXTI_LINE        EXTI_Line1
#define LIS3DSH_SPI_INT2_EXTI_PORT_SOURCE EXTI_PortSourceGPIOE
#define LIS3DSH_SPI_INT2_EXTI_PIN_SOURCE  EXTI_PinSource1
#define LIS3DSH_SPI_INT2_EXTI_IRQn        EXTI1_IRQn

#define LIS3DSH_CS_LOW()    GPIO_ResetBits(LIS3DSH_SPI_CS_GPIO_PORT, LIS3DSH_SPI_CS_PIN)
#define LIS3DSH_CS_HIGH()   GPIO_SetBits(LIS3DSH_SPI_CS_GPIO_PORT, LIS3DSH_SPI_CS_PIN)

#define LIS3DSH_FLAG_TIMEOUT    ((uint32_t)0x1000)

typedef struct
{
    // **** Control Register 1 ****
    uint8_t SM1_Hysteresis;
    uint8_t SM1_Pin;
    uint8_t SM1_Enable;
    // **** END OF Control Register 1 ****

    // **** Control Register 2 ****
    uint8_t SM2_Hysteresis;
    uint8_t SM2_Pin;
    uint8_t SM2_Enable;
    // **** END OF Control Register 2 ****

    // **** Control Register 3 ****
    uint8_t CR3_Dren;
    uint8_t CR3_Iea;
    uint8_t CR3_Iel;
    uint8_t CR3_Int2En;
    uint8_t CR3_Int1En;
    uint8_t CR3_Vfilt;
    uint8_t CR3_Strt;
    // **** END OF Control Register 3

    // **** Control Register 4 ****
    uint8_t CR4_Odr;
    uint8_t CR4_Bdu;
    uint8_t CR4_Zen;
    uint8_t CR4_Yen;
    uint8_t CR4_Xen;
    // **** END OF Control Register 4

    // **** Control Register 5 ****
    uint8_t CR5_Bw;
    uint8_t CR5_Fscale;
    uint8_t CR5_St;
    uint8_t CR5_Sim;
    // **** END OF Control Register 5

    // **** Control Register 6 ****
    uint8_t CR6_Boot;
    uint8_t CR6_FifoEn;
    uint8_t CR6_WtmEn;
    uint8_t CR6_AddInc;
    uint8_t CR6_P1Empty;
    uint8_t CR6_P1Wtm;
    uint8_t CR6_P1OverRun;
    uint8_t CR6_P2Boot;
    // **** END OF Control Register 6
} LIS3DSH_InitTypeDef;

typedef struct
{
    uint16_t x;
    uint16_t y;
    uint16_t z;
} accel_vector;

extern LIS3DSH_InitTypeDef deviceLIS3DSH;
extern GPIO_InitTypeDef portLIS3DSH;
extern SPI_InitTypeDef busLIS3DSH;
extern accel_vector accelData;

void LIS3DSH_Init(LIS3DSH_InitTypeDef* LIS3DSH_InitStruct);
uint32_t LIS3DSH_TIMEOUT_UserCallback(void);
void LIS3DSH_AccelInit(void);
void LIS3DSH_Read(uint8_t* pBuffer,
                  uint8_t ReadAddr,
                  uint16_t NumByteToRead);
void LIS3DSH_Write(uint8_t* pBuffer,
                   uint8_t WriteAddr,
                   uint16_t NumByteToWrite);
void LIS3DSH_FailureHandler(void);
accel_vector LIS3DSH_ReadData(void);
void LIS3DSH_SoftReset(void);

#endif

ctrl 是 uin8_t 类型,我正在使用带有 C 和 STM32F4Discovery 板的 IAR Embedded Workbench。这是 LIS3DSH_IniStruct 的一部分的代码:

deviceLIS3DSH.CR4_Odr=LIS3DSH_CR4_ODR_1600HZ;
deviceLIS3DSH.CR4_Bdu=LIS3DSH_CR4_BDU_ENABLED;
deviceLIS3DSH.CR4_Zen=LIS3DSH_CR4_Z_AXIS_ENABLED;
deviceLIS3DSH.CR4_Yen=LIS3DSH_CR4_Y_AXIS_ENABLED;
deviceLIS3DSH.CR4_Xen=LIS3DSH_CR4_X_AXIS_ENABLED;

并且 deviceLIS3DSH 被声明为:

LIS3DSH_InitTypeDef deviceLIS3DSH;
4

2 回答 2

3

相同的代码,但将 if 语句替换为纯位操作:

// **** CONTROL REGISTER 4 SETUP ****
    ctrl |= (LIS3DSH_InitStruct->CR4_Odr);
    ctrl |= (LIS3DSH_InitStruct->CR4_Bdu << LIS3DSH_CR4_BDU_POSITION);
    ctrl |= (LIS3DSH_InitStruct->CR4_Zen << LIS3DSH_CR4_Z_AXIS_POSITION);
    ctrl |= (LIS3DSH_InitStruct->CR4_Yen << LIS3DSH_CR4_Y_AXIS_POSITION);
    ctrl |= (LIS3DSH_InitStruct->CR4_Xen << LIS3DSH_CR4_X_AXIS_POSITION);
    LIS3DSH_Write(&ctrl,
                  LIS3DSH_CTRL_REG4_ADDR,
                  sizeof(ctrl));
    delay(1000000);
// **** END OF CONTROL REGISTER 4 SETUP ****
于 2013-11-02T20:05:41.517 回答
2

这些已经是位操作了。

if(LIS3DSH_InitStruct->CR4_Bdu)

这会测试里面的整数是否为 0。该测试是一个逻辑运算符,因此它会检查所有位。在内部,它可能是tst汇编指令。

    ctrl|=(1<<LIS3DSH_CR4_BDU_POSITION);

这是一些实际的位操作。ctrl有 8 位,我们想让其中一个为 1,即使它已经是 1。

所以我们取 00000001 的 1 并将位左移以使 1 进入我们关注的位置。这是哪个位置?它由LIS3DSH_CR4_BDU_POSITION在头文件中定义为从 0 到 7 的数字的宏给出。

所以右手边变成1<<400010000 或 0x10 或 16。

我们or这个数字与ctrlviactrl = ctrl | 0x10;有确保 ctrl 整数的第 5 位为 1 的效果。写起来更短ctrl |= (1<<4);

于 2013-11-02T17:26:24.797 回答