野火电子论坛

 找回密码
 注册

QQ登录

只需一步,快速开始

查看: 1117|回复: 3

书中的一个错误

[复制链接]
发表于 2026-8-2 14:28:05 | 显示全部楼层 |阅读模式
在点亮LED实验里的这行代码


//PB0输出低电平
GPIOB_ODR |= (0<<0)

|=0,没有任何作用啊。要把PB0设置低电平,这里应该改成&吧?

回复

使用道具 举报

发表于 2026-8-8 15:03:06 | 显示全部楼层
(0<<0)这是肯定有问题的,是1移位,不是0移位。 &= ~(1<<0)这是低电平,|= (1<<0)这是高电平
回复 支持 反对

使用道具 举报

发表于 4 天前 | 显示全部楼层
本帖最后由 LryCaulfield 于 2026-10-31 16:51 编辑

可以用GPIOB->ODR &= ~(1 << 0);
但这样有读、算、写3步,如果在读后写前ODR的值就改变了,那么用于计算的旧ODR值就不符合实际,算出的结果是旧ODR.bit0置1,在这读-写期间的改动就没有保留下来。
如(伪代码):
@ 开始时ODR = 0b01
ldr r0, =odr
ldr r0, [r0, #0] @取得ODR旧值0
mvn r1, #1 @取得~(1 << 0)
add r0, r1 @算得0b01 & ~(1 << 0) = 0b00   如果此时有中断处理将ODR改为0b11
ldr r1, =odr
str r0, [r1, #0] @将算得的0 & ~(1 << 0)写入ODR,中断处理做的工作被覆盖
最终我们得到ODR = 0b00,但我们其实希望中断也起作用,即结果为0b10

所以最好用BSRR寄存器GPIOB->BSRR = (1 << 16);或用位段宏GPIOB->BSRR = GPIO_BSRR_BR0;
这样只有1次写操作,由硬件置ODR的位,不会有过时旧值的问题
回复 支持 反对

使用道具 举报

发表于 4 天前 | 显示全部楼层
本帖最后由 LryCaulfield 于 2026-10-31 16:45 编辑

& 1没有效果,& 0可用来清0。而为了方便指定具体位,会用(1 << shift)得到1个只有1位为1的数如0b0100,取反后变成只有1位为0的数如0b1011,与目标数做&运算用于清0这1位
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则

联系站长|手机版|野火电子官网|野火淘宝店铺|野火电子论坛 ( 粤ICP备14069197号 ) 大学生ARM嵌入式2群

GMT+8, 2026-11-4 21:33 , Processed in 0.111742 second(s), 25 queries , Gzip On.

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

快速回复 返回顶部 返回列表