繁体   English   中英

Arduino中digitalWrite的解释:切换数字引脚的LED

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM