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