【问题标题】:Explanation of digitalWrite in Arduino: toggling LED of digital pinArduino中digitalWrite的解释:切换数字引脚的LED
【发布时间】:2014-12-16 03:05:51
【问题描述】:

我试图了解当您打开/关闭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;
}

这是怎么回事?

特别是函数末尾的位旋转位。

【问题讨论】:

  • 你有什么不明白的部分吗?

标签: c arduino hardware arduino-uno


【解决方案1】:

AVR 设备上的 I/O 排列在每个 8 个引脚的端口中。不同的设备有不同数量的端口,使用字母命名。端口一次写入 8 位。

例如,要写入 PORTA,您可以说 PORTA = 0xFF;,这将打开 PORTA 上的每个引脚。

现在 Arduino 平台也有引脚,这些引脚在所有可能的 AVR 芯片上都进行了编号和标准化。有一个从特定 AVR 设备引脚到 digitalWrite() 函数必须弄清楚的 Arduino 引脚的映射。查看特定芯片的数据表以了解端口和引脚是什么。例如Arduino Uno,Arduino数字引脚0对应PORTD上的0引脚。

digitalWrite() 顶部的两个函数决定了我们需要哪个 AVR 端口和引脚。

还可以将所需引脚连接到使用脉冲宽度调制或 PWM 将其打开和关闭的定时器。如果是这样,那么我们需要确保禁用此功能。

要在端口上写入引脚,我们使用一些位算术。例如,要将 PORTB 上的引脚 4 设置为高电平(Arduino 引脚 12),我们使用 PORTB = PORTB | (1<<4);PORTB |= (1<<4);。也就是说,保持所有其他引脚相同,但将引脚 4 设为高电平。

将引脚设置为低电平是类似的。我们想不理会其他位,因此我们 and 使用几乎全为 1 的数字。 PORTB &= ~(1<<4);.

最后一个魔法是我们不希望在设置端口位时被中断。为此,我们使用cli(); 禁用中断。但我们不只是想在完成后启用中断;当我们开始时,它们可能尚未启用。

诀窍是保存它们是否启用,这是状态寄存器 SREG 中的一个位。因此,程序是保存 SREG,如果尚未禁用中断,则禁用中断,执行我们想要的操作,然后将 SREG 恢复到我们(可能)更改 I 位之前的状态。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-01-22
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多