一个寄存器的bit2 bit3位由10修改成11,C示例

  • 方法1:
    如果需要将一个寄存器中的 bit2 和 bit3 两个位从 11 修改为 10,可以使用如下的 C 语言代码实现:
// 将寄存器的 bit2 和 bit3 位从 11 修改为 10
volatile uint32_t *reg_addr = (volatile uint32_t *)0x12345678; // 假设寄存器地址为 0x12345678
*reg_addr &= ~(0x3 << 2); // 先将 bit2 和 bit3 位清零
*reg_addr |= (0x2 << 2); // 使用按位或运算符将 bit2 和 bit3 位的值修改为 10

首先,使用指针 reg_addr 来指向该寄存器的地址,同样使用了 volatile 关键字来确保编译器不会对该寄存器的读写进行优化。

然后,使用按位与运算符 & 和按位取反运算符 ~ 将要修改的两个位清零。具体来说,0x3 << 2 表示二进制数 1100,将其取反得到 0011,然后使用按位与运算符将该值与原始寄存器值进行按位与运算,即可将 bit2 和 bit3 位清零。

最后,使用按位或运算符 | 将要修改的值与原始寄存器值进行按位或运算,将 bit2 和 bit3 位的值修改为 10。具体来说,0x2 << 2 表示二进制数 1000,左移 2 位得到 0010,然后将其与原始寄存器值进行按位或运算,即可将 bit2 和 bit3 位的值修改为 10。

需要注意的是,这里的代码仅仅是修改了寄存器的 bit2 和 bit3 两个位,如果需要修改其他位的值,需要根据具体情况进行修改。同时,为了保证修改寄存器的值不会对系统产生负面影响,需要了解该寄存器的具体作用和使用规范。

  • 方法2:
    还有一种比较简单的写法,可以使用位域来直接修改寄存器的值。具体实现如下:
// 将寄存器的 bit2 和 bit3 位从 11 修改为 10
volatile uint32_t *reg_addr = (volatile uint32_t *)0x12345678; // 假设寄存器地址为 0x12345678
struct {
    uint32_t bit0_1 : 2;
    uint32_t bit2_3 : 2;
    uint32_t bit4_31 : 27;
} *reg = (typeof(reg)) reg_addr;

reg->bit2_3 = 0x2; // 直接将 bit2 和 bit3 位的值修改为 10

首先,定义一个包含三个位域的结构体,分别表示寄存器中的 bit01、bit23 和 bit4~31 三个部分。使用指针 reg 指向该寄存器的地址,并将其类型转换为该结构体类型。

然后,直接将 bit2~3 位的值修改为 10,使用结构体成员访问符 -> 访问 reg 结构体的 bit2_3 成员,并将其赋值为 0x2,即二进制数 10

需要注意的是,使用位域直接修改寄存器的值可能会受到编译器的优化影响,因此需要确保编译器不会对代码进行优化。同时,为了保证修改寄存器的值不会对系统产生负面影响,需要了解该寄存器的具体作用和使用规范。

  • 方法3:
    也可以使用位掩码和位移操作来修改寄存器的值,实现比较简单。具体实现如下:
// 将寄存器的 bit2 和 bit3 位从 11 修改为 10
volatile uint32_t *reg_addr = (volatile uint32_t *)0x12345678; // 假设寄存器地址为 0x12345678
uint32_t mask = 0x3 << 2; // 定义位掩码,表示要修改的 bit2 和 bit3 位
uint32_t value = 0x2 << 2; // 定义新的值,表示要将 bit2 和 bit3 位修改为 10
*reg_addr = (*reg_addr & ~mask) | value; // 使用按位与和按位或运算符将寄存器的值修改为新值

首先,使用指针 reg_addr 来指向该寄存器的地址。

然后,定义一个位掩码 mask,表示要修改的 bit2 和 bit3 位。具体来说,0x3 << 2 表示二进制数 1100,左移 2 位得到 0011,即表示要修改的 bit2 和 bit3 位。

接着,定义新的值 value,表示要将 bit2 和 bit3 位修改为 10。具体来说,0x2 << 2 表示二进制数 1000,左移 2 位得到 0100,即表示要将 bit2 和 bit3 位修改为 10。

最后,使用按位与运算符 &、按位取反运算符 ~ 和按位或运算符 | 将原始寄存器值与新值进行按位与和按位或运算,从而将 bit2 和 bit3 位的值修改为 10。具体来说,*reg_addr & ~mask 表示将寄存器中要修改的位清零,| value 表示将新值按位或运算到寄存器中要修改的位上。

需要注意的是,这里的代码仅仅是修改了寄存器的 bit2 和 bit3 两个位,如果需要修改其他位的值,需要根据具体情况进行修改。同时,为了保证修改寄存器的值不会对系统产生负面影响,需要了解该寄存器的具体作用和使用规范。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是一个简单的STM32寄存器版从机I2C代码示例,使用的是STM32F407VG芯片,I2C2作为从机,代码中假设主机发送的数据为1字节: ``` #include "stm32f4xx.h" void I2C2_Configuration(void) { GPIO_InitTypeDef GPIO_InitStructure; I2C_InitTypeDef I2C_InitStructure; NVIC_InitTypeDef NVIC_InitStructure; // 使能 I2C2 时钟 RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C2, ENABLE); // 使能 GPIOB 时钟 RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB, ENABLE); // 配置 GPIOB 引脚 PB10 和 PB11 为 I2C2_SCL 和 I2C2_SDA GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10 | GPIO_Pin_11; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_InitStructure.GPIO_OType = GPIO_OType_OD; GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP; GPIO_Init(GPIOB, &GPIO_InitStructure); // 配置 PB10 和 PB11 的复用功能为 I2C2 GPIO_PinAFConfig(GPIOB, GPIO_PinSource10, GPIO_AF_I2C2); GPIO_PinAFConfig(GPIOB, GPIO_PinSource11, GPIO_AF_I2C2); // 配置 I2C2 I2C_InitStructure.I2C_Mode = I2C_Mode_SMBusSlave; // 采用 SMBusSlave 模式 I2C_InitStructure.I2C_DutyCycle = I2C_DutyCycle_2; // I2C 时钟占空比为 2 I2C_InitStructure.I2C_OwnAddress1 = 0x30; // 从机地址为 0x30 I2C_InitStructure.I2C_Ack = I2C_Ack_Enable; // 使能应答 I2C_InitStructure.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit; // 7 地址模式 I2C_InitStructure.I2C_ClockSpeed = 100000; // I2C 时钟速度为 100 kHz I2C_Init(I2C2, &I2C_InitStructure); // 使能 I2C2 I2C_Cmd(I2C2, ENABLE); // 配置 I2C2 中断 NVIC_InitStructure.NVIC_IRQChannel = I2C2_EV_IRQn; NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; NVIC_Init(&NVIC_InitStructure); // 使能 I2C2 中断 I2C_ITConfig(I2C2, I2C_IT_EVT, ENABLE); } void I2C2_EV_IRQHandler(void) { if (I2C_GetITStatus(I2C2, I2C_IT_EVT) == SET) { // 接收到主机发送的数据 if (I2C_GetFlagStatus(I2C2, I2C_FLAG_ADDR) == SET) { // 清除 ADDR 标志 (void)I2C2->SR2; // 等待接收数据完 while (I2C_GetFlagStatus(I2C2, I2C_FLAG_RXNE) == RESET); // 读取接收到的数据 uint8_t data = I2C_ReceiveData(I2C2); // 处理接收到的数据 // TODO: 在此处添加处理代码 // 发送应答 I2C_AcknowledgeConfig(I2C2, ENABLE); // 清除 ADDR 标志 (void)I2C2->SR2; // 等待数据发送完 while (I2C_GetFlagStatus(I2C2, I2C_FLAG_TXE) == RESET); // 发送数据 I2C_SendData(I2C2, data); } } // 清除事件标志 I2C_ClearITPendingBit(I2C2, I2C_IT_EVT); } int main(void) { I2C2_Configuration(); while(1) { // 主循环 } } ``` 需要注意的是,在使用I2C2作为从机时,需要将PB10、PB11引脚配置为复用功能,并且不要忘记在I2C2_EV_IRQHandler中处理接收到的数据。另外,需要根据实际情况修改从机地址、时钟速度等参数。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值