[英]Why a led in arduino uno is not toggling and is always in the "on" state?
[英]Explanation of digitalWrite in Arduino: toggling LED of digital pin
我试图了解当您打开/关闭Arduino Uno上的 LED 时“引擎盖下”会发生什么。
带有硬件项目的基本 Hello World 似乎在闪烁一个板载 LED。 对于 Arduino,有一个 LED 连接到引脚 12。
我查看了digitalWrite
的源代码:
void digitalWrite(uint8_t pin, uint8_t val)
{
uint8_t timer = digitalPinToTimer(pin);
uint8_t bit = digitalPinToBitMask(pin);
uint8_t port = digitalPinToPort(pin);
volatile uint8_t *out;
if (port == NOT_A_PIN)
return;
// If the pin that support PWM output, we need to turn it off
// before doing a digital write.
if (timer != NOT_ON_TIMER)
turnOffPWM(timer);
out = portOutputRegister(port);
uint8_t oldSREG = SREG;
cli();
if (val == LOW) {
*out &= ~bit;
}
else {
*out |= bit;
}
SREG = oldSREG;
}
这里发生了什么?
特别是函数末尾的位旋转位。
AVR 设备上的 I/O 排列在每个 8 引脚的端口中。 不同的设备有不同数量的端口,它们以字母命名。 端口一次写入 8 位。
例如,要写入 PORTA,您可以说PORTA = 0xFF;
,这将打开 PORTA 上的每个引脚。
现在 Arduino 平台也有引脚,这些引脚在所有可能的 AVR 芯片上都进行了编号和标准化。 有一个从特定 AVR 设备引脚到 Arduino 引脚的映射, digitalWrite()
函数必须弄清楚。 查看特定芯片的数据表,了解端口和引脚是什么。 例如,在Arduino Uno 上,Arduino 数字引脚 0 对应于 PORTD 上的 0 引脚。
digitalWrite()
顶部的两个函数决定了我们需要哪个 AVR 端口和引脚。
也可以将所需引脚连接到一个定时器,该定时器使用脉宽调制或 PWM 来打开和关闭它。 如果是这样,那么我们需要确保禁用此功能。
要在端口上写入引脚,我们使用一些位算法。 例如,要将 PORTB 上的引脚 4 设置为高电平(Arduino 引脚 12),我们使用PORTB = PORTB | (1<<4);
PORTB = PORTB | (1<<4);
或PORTB |= (1<<4);
. 也就是说,保持所有其他引脚相同,但将引脚 4 设为高电平。
将引脚设置为低电平与此类似。 我们想不理会其他位,所以我们and
一个几乎全是 1 的数字。 PORTB &= ~(1<<4);
.
最后一个魔法是我们不希望在端口中设置位时被中断。 为此,我们使用cli();
禁用中断cli();
. 但是我们不只是想在完成后启用中断; 当我们开始时,它们可能尚未启用。
诀窍是保存它们是否被启用,这是状态寄存器 SREG 中的一个位。 所以程序是保存 SREG,如果它们还没有被禁用,则禁用它们,做我们想做的事情,然后将 SREG 恢复到我们(可能)更改I
位之前的状态。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.