How can I input/output from/to a complete port


is there a way to output to a complete port at once. Not bitwise.

I want to output a nibble (a half byte) to D0…D3.
It is essential that all bits were set at the same time.

Is that possible?

On an AVR I would do this like that:

PORTA=0x0f // set bit 0…3 to High


PORTA=(PORTA&0xf0) | 0x05; // output ‘5’ to bits 0…3 and leave bits 4…7 unchanged.


Yes there is, but unfortunately the pins on the Core (and even e on the Photon) are scattered over several ports.
Have a look at this pinout

Strange: The part of how to read all 16bit of a port via e.g. uint16_t x = GPIOB->IDR; has vanished from this post :question:

But a full port write could be done with these makros

  // fast pin access
  #define pinLO(_pin)	(PIN_MAP[_pin].gpio_peripheral->BRR = PIN_MAP[_pin].gpio_pin)
  #define pinHI(_pin)	(PIN_MAP[_pin].gpio_peripheral->BSRR = PIN_MAP[_pin].gpio_pin)
  #define pinSet(_pin, _hilo) (_hilo ? pinHI(_pin) : pinLO(_pin))
  // even faster port based multi pin access
  #define portSet(_port, _word) (_port->ODR = _word)
  #define portSetMasked(_port, _word, _mask) (_port->BSRR = (_mask << 16) | (_word & _mask))

Ok, thank you. So it’s a bit tricky. I connected an adress decoder 74hc138 to pins D4…6 and it’s enable pin to A2.
I use the adress decoder to generate several CS for different SPI device connected to A3…5.

So I have to do the following:

  • convert the desired device adress to the two port masks and data
  • write the words to the port using the portSetMasked macro
  • enable the '138 by setting A2 to low.
  • do the SPI transfer
  • disable the '138 by setting A2 to high.

Maybe I should build some constants for the eight possible masks and data during the initialization phase, so I don’t have to do it everytime I want to transfer something.

Or maybe it is faster writing the three bits one at a time by using the pinSet macro.

I guess speed is not that much of an issue with your setup, so I’d rather go for the “easiest” approach, and building up scattered masks doesn’t seem to be the “easiest” way :wink:

And since you have the A2 pin to “latch” the set address you don’t need to set all the address pins at once, so pinSet would be easy enough.

On the other hand, if you had the possibility to rewire the 74HC138 and don’t need Serial1 pins TX/RX you could go for GPIOA0..A3 (A0, A1, RX, TX) that would be a complete nibble that can easily be written at once.
Another thing is that the SPI pins are also located on GPIOA (high nibble low byte) so GPIOA high byte and complete GPIOB would be free for other use.

BTW: To use these macros you’d still have to set the pinMode(.., OUTPUT) for the respective pins.


at the weekend I tried the macros. Wow is that fast. My display refresh using softSPI with these macros is about 10 times faster!

If all that called stuff in digitalWrite is so extremely slow, I wonder why this is not implemented as such a macro. I will newer again use digitalWrite on this platform.

My SPI select stuff I will check in the next days.

Thank you very much for clearing that IO stuff. It will help me alot, even with another ARM platform I use.

There are some good reasons for using digitalWrite, too.

  • One is compatibility.
  • Another is relative “fool proveness” :wink:
  • It provides some sort of abstraction layer e.g. D0 may be placed on a different port on the Photon. By use of abstraction you can use your code there without further ado, but with these macros you’d need to change the code accordingly, or introduce some abstraction yourself, which may slow you down again.
  • With these macros you could mess things up quite easily aswell :heavy_exclamation_mark:

As long you know what you do and how they actually work, you’ll be fine tho’

@Bluescreen, as @ScruffR pointed out, the digitaRead/Write (and analogInput/Write) functions provide “safety” checking. This means checking that the specified pin is not conflicting with a previous setting for that pin (eg. trying to output digital to a pin configured as an analog input). In a “Core only” environment, you manage and control the Core resources so using the macros makes sense. When developing non-specific portable code, it is better to use the “safe/common” functions. :smile:


Is there a version of this for the Photon? I currently get :

error: 'struct GPIO_TypeDef' has no member named 'BRR'

@mihaigalos, if you compile for the Photon or Electron you can use the low level GPIO commands. I believe these are also available on Core firmware versions 0.4.3 or greater.

1 Like