0

How would you go about checking if an input pin has been set using the entire bank? I am thinking that I need to use bit twiddling with a bit mask but I have not used this enough to figure out how to do what I want.

Basically I have the following code:

void setup() {
   DDRA = 0x00;
   PORTA = 0xff;
}

void loop(){
   //Check if any pin from Port A has been pressed
   if (PINA & 0xff){
      //do stuff
   }
}

But the code above is not working how I expected it to. Has anyone tried to use this approach before? Am I going about this the wrong way? I figured since I was using all 8 pins from one bank, it would be better to check if any of the pins on that bank have been set instead of checking each individual pin. My thinking on this was to prevent any user input from being skipped in case a button press was initiated while the program was running other code. This way I only check if anything in the bank has been set saving time (I think).

  • If you attached the buttont towards ground then the "pressed" state is the 0, so "any button pressed" is coded in the instruction if (PINA == 0xff) or if (~PINA & 0xff). – frarugi87 Nov 26 '15 at 13:20
2

The problem is here:

//Check if any pin from Port A has been pressed
if (PINA & 0xff){

Since the pullups are enabled, the default state of the pins is high. To detect a "press", they have to be pulled to ground. This changes the test to:

//Check if any pin from Port A has been pressed
if (~PINA) {

And for individual pins:

//Check if PA3 has been pressed
if (!(PINA & _BV(PA3))) {
  • When I run the code if (~PINA) it always enters the loop no matter what. Did this work for you, did you test this? – Andy Braham Nov 26 '15 at 16:27
  • I tried your code and it will always enter the loop but if you change the code to if(~PINA & 0xff){ ... } it works. – Andy Braham Nov 26 '15 at 16:35
  • ~PINA assumes that all 8 pins are being used for active-low input. If only part of the port is being used then you need to mask the pins in use. – Ignacio Vazquez-Abrams Nov 26 '15 at 19:34
0

The simplest way is to use DigitalRead in a loop. It makes your code more portable, and easier to read.

  • The whole point was so I didn't have to read each Pin individually, I will have many more Inputs eventually and the time spent checking each Input might not catch everything. – Andy Braham Nov 25 '15 at 23:03
  • There's a maximum of 20 inputs on the Uno; at 16 mhz, you would be checking them at hundreds of thousands of times per second (that gives you 8 instructions per pin). Sometimes you need that; often you don't. – AMADANON Inc. Nov 26 '15 at 1:01
0

I'm not really an expert in "plain avr code" but I've modified arduino blink and got (almost) a perfect example. Placed a jumper between 5v and pin 8 of arduino and uploaded the following code:

void setup() {
  // initialize digital pin 13 as an output.
  DDRB = 0b00100000;


}

// the loop function runs over and over again forever
void loop() {
  if (PINB & 0x1) {
    PORTB =  0b00100000;  // turn the LED on (HIGH is the voltage level)
    delay(500);              // wait for a second
    PORTB = 0;    // turn the LED off by making the voltage LOW
    delay(500);              // wait for a second
  }
}

according to following picture pin8 on arduino is PB0 and pin13 is PB5. So using DDRB I set PB5 as output and all others as input. Then in loop I check as you do PINB register and use bitmask to check first pin (the PB0). And it works... well not quite well. For some reason the loop goes a few times more before goes really low. I believe is because I just remove the jumper and do not actually ground pin 8 ( is left float) and maybe the extra loops are discharging some capacitance on that pin 8.

pinouts
(source: arduinoexperts.com)

So, to your specific question, your bitmask is right. This instruction PORTA = 0xff; is useless because, as far as I know, this settings are ignored because you set Pin direction in pins of PORTA to input. However, according to that image, atmega328 doesn't have a PORTA. Is that your error or are you using another microcontroller?

EDIT Capacitance thing is confirmed, maked it swing between gnd and vcc with a switch and all works fine.

  • "This instruction PORTA = 0xff; is useless" Incorrect. On modernish, largish AVRs this sets the state of the internal pullup resistor. – Ignacio Vazquez-Abrams Nov 26 '15 at 2:28
  • @IgnacioVazquez-Abrams Thanks for pointing that out. And reading your answear it all makes sense. Always learning :) – brtiberio Nov 26 '15 at 9:41

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.