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?
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)?
Yeah it is strange...here is the code:
#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);
system
July 16, 2007, 3:05pm
4
Use PINB to read the values of the pins. PORTB is used to write the values
system
July 18, 2007, 5:14pm
5
ahh thanks, I'll give that a try.