Go Down

Topic: PORTx vs. digitalRead() (Read 1 time) previous topic - next topic

breakdown

I have something that's mystifying me and I'm hoping someone can explain.

Background:
I'm using PORTB in this case.
I have DDRB = 0xFF; and PORTB = 0xFF;

I have an external chip that pulls down one of 6 pins on PORTB. Each one triggers a pin change interrupt. First thing I do in the ISR is check which was pulled low. Now when I just read in PORTB, they all appear high. When I use a for loop and use digitalRead(), it correctly tells me which one was low.

I could use the for loop method, but I'm wondering why just reading PORTB doesn't work.

I've looked at digitalRead, which after doing some checks returns this:

return (_SFR_IO8(port_to_input[digitalPinToPort(pin)]) >> digitalPinToBit(pin)) & 0x01;

Which I've managed to turn into this:

_SFR_IO8(port_to_input[2]); //PB is defined as 2 in pins_arduino.c

which successfully works as well.

SOO my question is can anyone explain why this SFR_IO8 trick works but simply reading PORTB does not?





mellis

Huh, strange; I don't have any ideas off of the top of my head.  Can you post the full source for your sketch (or a simplified version that illustrates the problem)?

breakdown

Yeah it is strange...here is the code:

Code: [Select]
#include <avr/portpins.h>
#include <avr/interrupt.h>

/*
Interupt-based QT300 1-WIRE driver
*/

#define TBR 200  //baud period in microseconds (110-200 allowed)
#define TWU 40  //wake up time
#define TSCK 40 //half period of clock (min 30)
#define TDS 80 //data spacing duration  (min 75)
#define TSAMP 15

#define CHAN 1 // number of channels to be sampled (not used yet)

//Connectors and corresponding arudino pins
#define       J1      2
#define       J2      3
#define       J3      4
#define       J4      5
#define       J5      6
#define       J6      7
#define       J7      8
#define       J8      9
#define       J9      10
#define       J10      11
#define       J11      12
#define       J12      13


//macros to disable pin change interrupts and mask/unmask them
#define DISABLE_INT  PCICR &= !(0x05)
#define ENABLE_INT PCICR |= 0x05
#define MASK0 PCMSK0 |= 0x3F
#define MASK2 PCMSK2 |= 0xFC
#define UNMASK0 PCMSK0 &= !(0x3F)
#define UNMASK2 PCMSK2 &= !(0xFC)

//states
#define DEFAULT 0
#define PRINT 1
#define SEND 2

//which PIN to send/recieve from:
int req = J4;

volatile uint16_t qt_data = 0;

volatile uint8_t state;
volatile byte portreading = 0;


int ch = 0;
int i = 0;
int bl = 0;                 // used to count the time of the acquisition burst

int dec_reading = 0;

void setup() {

 
 //disable PCinterrupts
 DISABLE_INT;
 UNMASK0;
 UNMASK2;

 //set PORTB to outputs
 DDRB = 0xFF;
 PORTB = 0xFF;
 
 DDRD = 0xFF;
 PORTD = 0xFF;
 
 
 Serial.begin(115200);      
 delay(500);                

 
  ENABLE_INT;
  MASK0;
  MASK2;

  state = SEND;


}//setup()

void loop(){
   
   switch (state) {
     
   case SEND:
 
   
    //send acquisition request
    send_req(req);
    state = DEFAULT;
    break;
     
   
    case PRINT:

    Serial.print(qt_data);
    Serial.println("");
    Serial.print(portreading,BIN);
    Serial.println("");
 
    state = SEND;
   
    break;
   
   
   default:
   
   
   break;
 
   }

}//loop()


uint16_t get_bytes(int pin) {
   

   static uint8_t qtMSB;
   static uint8_t qtLSB;
   
   qtMSB = 0;
   qtLSB = 0;
   
   //this delay needs to be determined by how long it takes to go through ISR
   delayMicroseconds(TBR);  //TBD
   delayMicroseconds(TBR/2);
   
   //first byte
   
   for (i = 0; i < 8; i++) {
   
   
     qtMSB |= (digitalRead(pin) << i);
     //qtMSB |= (PORTB1 << i);
     delayMicroseconds(TBR);
     

    }
 
   delayMicroseconds(85);
   
 
   while (digitalRead(pin)  != HIGH);
   while (digitalRead(pin) != LOW);
 
 
   delayMicroseconds(TBR);
   delayMicroseconds(TBR/2);
   
   //second byte
   for (i = 0; i < 8; i++) {
     
     qtLSB |= (digitalRead(pin) << i);
     //qtLSB |= PORTB1 << i;
     delayMicroseconds(TBR);
 
   }
 
 
 
 
  return qtLSB + (qtMSB << 8);

 
}

//send acquisition request to qt300 on selected pin
void send_req(int pin) {
 

   DISABLE_INT;
   UNMASK0;
   UNMASK2;
   
 
   DDRB |= 0xFF;
   DDRD |= 0xFF;
   
   //send wake up pulse
   digitalWrite(pin, LOW);
   delayMicroseconds(TWU);
   
   //send baud rate pulse
   digitalWrite(pin, HIGH);
   delayMicroseconds(TBR);
   digitalWrite(pin, LOW);
   
   
   delayMicroseconds(TWU); //twu
   digitalWrite(pin, HIGH);
 
   DDRB &= 0x00;
   DDRD &= 0x00;
   delayMicroseconds(TBR);
   
   ENABLE_INT;
   MASK0;
   MASK2;    
   
 
}

ISR(__vector_default)
{
   Serial.println("DEFAULT");
   state = PRINT;
}



ISR (PCINT0_vect) {
 
  DISABLE_INT;
  UNMASK0;
  UNMASK2;
 
  //portreadin = PORTB; //doesn't work, always gives all HIGH
  portreading = _SFR_IO8(port_to_input[2]);

  qt_data = get_bytes(req);  
 
  state = PRINT;

  ENABLE_INT;
  MASK0;
  MASK2;
 
}//ISR(PCINT0_vect);


ISR (PCINT2_vect) {

  DISABLE_INT;
  UNMASK0;
  UNMASK2;

  //portreading = PORTD;
  portreading = _SFR_IO8(port_to_input[4]);
 
  qt_data = get_bytes(req);  
 
  state = PRINT;

  ENABLE_INT;
  MASK0;
  MASK2;  
 
}//ISR(PCINT2_vect);

wandrson

Use PINB to read the values of the pins.  PORTB is used to write the values

breakdown

ahh thanks, I'll give that a try.

Go Up
 


Please enter a valid email to subscribe

Confirm your email address

We need to confirm your email address.
To complete the subscription, please click the link in the email we just sent you.

Thank you for subscribing!

Arduino
via Egeo 16
Torino, 10131
Italy