*pointer PINB1 ... is there a way?

is there a way to assign the address of a pin to a pointer?
works perfectly with data direction registers.

if not how does one make a function that asks for a pin number , with out having to resort to
if x ==1 then PINB1
if x = 2 then PINB2

one more question when compiling this line gives me a warning, it still works as desired but im just wondering what the warning means

int *test = &PORTB ;

"Warning 1 initialization from incompatible pointer type [enabled by default]"

what data type are the ports?? and where does one learn such things...? aside from trial and error

I'm prepared to be corrected here but on the AVR architecture the ports are IO mapped and that requires different instructions at the assembler level, therefore I think you can't have a pointer to IO although UI guess there's no reason the compiler can't work around that.

Hardware is generally a volatile byte, so if indeed ports have a data type I would think it would be uint8_t*.

This compiles

volatile uint8_t * test = &PORTB ;

whether or not it does what you want may be a different story.

where does one learn such things...? aside from trial and error

Trial and error I guess, and these days asking on forums :slight_smile:


Rob

I just noticed this thread. I've been trying to do something similar for the past couple of days, and it works if you define the pointer correctly. First, if I use < int* ptr = &PORTB; > I don't get a warning, I get a compile time error.

Secondly, use of the proper pointer works correctly - ie, all of the forms in loop() set the proper bit, and turn on the Led.

 // UNO uses PortB.5 for the Led.
#define ledPIN   13

//int* ptr = &PORTB;
volatile uint8_t* ptr = &PORTB;

void setup()
{
  Serial.begin(57600);
  pinMode(ledPIN, OUTPUT);
  
  Serial.print("PORTB: ");
  Serial.print(PORTB);
  Serial.print(", PORTD: ");
  Serial.print(PORTD);
}

void loop()
{
  // the following 8 forms all turn on the Led.
  //bitSet(*ptr, 5);
  //*ptr |= 0b100000; 
  *ptr |= 1 << 5;
  
  //PORTB |= 0x20;
  //PORTB |= 0b100000;
  //PORTB |= 1 << 5;
  //bitSet(PORTB, 5);
  //digitalWrite(ledPIN, HIGH);
  delay(100);

  digitalWrite(ledPIN, LOW);
  delay(500);
}

Thirdly, what I don't understand about this is that PORTB and PORTD do not print out correctly using Serial.print(). Here are the results of the above program, so ???

PORTB: 0, PORTD: 0

I also found the pointer method to be incredibly slow, for some unknown reason, so ???? on that too.
http://forum.arduino.cc/index.php?topic=181482.msg1347130#msg1347130

Having a pointer to a PORT works fine. Having a pointer to an individual pin of a port is not possible.
(well, you COULD think of the Arduino pin-numbers, as being pointers to individual pins, but as you know, they use quite a bit of code to implement that. Some of the digitalWrite alternatives go so far as to make individual pins into C++ "objects", which I think gives you the ability to say stuff like:

myled = pin(13);
  :
myled = 1;
delay(1000);
myled = 0;

But I think most of those are aimed at speed rather than doing the full set of reasonable operator overloading.
Fast digital I/O, software I2C, and software SPI libraries - Libraries - Arduino Forum for example.

Graynomad:
I'm prepared to be corrected here but on the AVR architecture the ports are IO mapped...

They're both. All registers are memory mapped. The first 32 are also I/O mapped. There are machine instructions for accessing individual bits in the first 32 registers. But all bits in all registers can be memory accessed using a read-modify-write sequence (typically three to four instructions).

When possible, adding const to the pointer allows the compiler to choose which instruction sequence can be used...

volatile uint8_t * const test = &PORTB ;

oric_dan:
Thirdly, what I don't understand about this is that PORTB and PORTD do not print out correctly using Serial.print(). Here are the results of the above program, so ???
PORTB: 0, PORTD: 0

Why do you believe zero and zero are not the correct values? What values were you expecting?

The values shown in sec 14.4 of the 328 d/s, maybe PORTB = 0x05, PORTD = 0x0B, etc. There's gotta be some difference when doing something like the following, but something is happening here, and I obviously don't know what it is (would be nice to see the assembler code).

PORTB |= 0x20;
PORTD |= 0x20;

Bill [westfw], thanks for the references, will check them out tomorrow.

oric_dan:
The values shown in sec 14.4 of the 328 d/s, maybe PORTB = 0x05, PORTD = 0x0B, etc.

  Serial.print("PORTB: ");
  Serial.println( _SFR_IO_ADDR( PORTB ) );
  Serial.print(", PORTD: ");
  Serial.println( _SFR_IO_ADDR( PORTD ) );

There's gotta be some difference when doing something like the following, but something is happening here, and I obviously don't know what it is (would be nice to see the assembler code).

PORTB |= 0x20;
sbi	0x05, 5
PORTD |= 0x20;
sbi	0x0b, 5

Create a structure to encompass the contents of the entire port, with each bit represented by a 1-bit integer. Then create a pointer of that struct and assign the address of the port to it:

struct port {
  union {
    unsigned char valuue;
    struct {
      unsigned p0:1;
      unsigned p1:1;
      unsigned p2:1;
      unsigned p3:1;
      unsigned p4:1;
      unsigned p5:1;
      unsigned p6:1;
      unsigned p7:1;
    } __attribute__((packed));
  } __attribute__((packed));
} __attribute__((packed));

struct port *myPort = (struct port *)&PORTB;

myPort.p3 = 1;
Serial.println(myPort.p7);

(untested, but something I do often)