I am trying to use the Arduino I/O registers directly. I have a switch connected to Arduino pin 5 (pin PD5) and an LED is connected to Arduino pin 2 (pin PD2). The objective is to have the LED glow when the switch is pressed. PD5 is configured as an input with internal pull-up resistor activated.
When I am coding with digitalRead() and digitalWrite() functions, the code works just fine. But when I am trying to use the internal registers DDRx, PORTx and PINx, the code is not working correctly. The LED remains ON even when the switch is not pressed. My code is given below.
uint8_t x;
void setup() {
// put your setup code here, to run once:
DDRD = (0<<DDD7)|(0<<DDD6)|(0<<DDD5)|(0<<DDD4)|(0<<DDD3)|(1<<DDD2); //PD5 input/ PD2 output
PORTD = 0b11111000; //pull up resistor activated for PD5
}
void loop() {
// put your main code here, to run repeatedly:
x = PIND;
if((x & (0b00100000)) == 0)
{
delay(20);
if((x & (0b00100000)) == 0)
{
PORTD = (1<<PORTD2);
}
}
else
{
PORTD = (0<<PORTD2);
}
}
6v6gt:
Try something like
PORTD |= (1<<PORTD2) ; sets 1 bit
That operation is non-atomic. Therefore, it is not interrupt-safe. Suppose an interrupt occurs after PORTD is read but before it is rewritten. If the ISR for that interrupt modifies the contents of PORTD, then after it exits your code will corrupt that change when it writes back the value with Bit 2 set.
On AVRs settings or clearing single bit in some registers (such as I/O related) is atomic.
Disabling interrupts is needed only when some interrupt changes the register.