cat*_*ure 2 c hardware arduino arduino-uno
我试图了解当您打开/关闭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;
}
Run Code Online (Sandbox Code Playgroud)
这里发生了什么?
特别是,在函数末尾的位比特位.
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 |= (1<<4);.也就是说,保持所有其他引脚相同,但将引脚4设为高电平.
将引脚设置为低电平是类似的.我们想留下其他位,所以我们and的数字几乎都是1.PORTB &= ~(1<<4);.
最后一个魔力是我们不希望在端口中设置位时被中断.为此,我们禁用中断cli();.但是我们并不只是想在完成后启用中断; 我们开始时可能没有启用它们.
诀窍是保存它们是否被启用,这是状态寄存器SREG中的一个位.因此,程序是保存SREG,如果它们没有被禁用则禁用中断,执行我们想要的操作,然后将SREG恢复到我们(可能)更改I位之前的状态.