Go Down

Topic: How to setting Digital Pins Quickly in Arudino due (Read 5091 times) previous topic - next topic


As mentioned in Arduino Cook Book (chapter 18: Using the Controller Chip Hardware,
18.11 Setting Digital Pins Quickly), Arduino digitalWrite provides a safe and easy-to-use method of setting and clearing pins, but it is more than 30 times slower than directly accessing the controller hardware. And using bitSet and bitClear with the following codes were compiled successfully under Arduino Uno (I modified the origin code and test it).

Code: [Select]

const int sendPin = 2;
void setup()
pinMode(sendPin, OUTPUT);
void loop(){
    bitSet(PORTD, sendPin);
// PORTD is defined as the register of digital pins from 0 to 7
    bitClear(PORTD, sendPin);

And the problem is that "PORTD" is not defined in Arduino Due, can anybody who is familiar with Arduino Due give me some suggestions, what could be done to achieve the same target that is able to set or clear digital pins much faster than enabled by the Arduino digital Write command.

The definitions of bitSet and bitClear are as following in Arduino.h
Code: [Select]

#define bitRead(value, bit) (((value) >> (bit)) & 0x01)
#define bitSet(value, bit) ((value) |= (1UL << (bit)))
#define bitClear(value, bit) ((value) &= ~(1UL << (bit)))
#define bitWrite(value, bit, bitvalue) (bitvalue ? bitSet(value, bit) : bitClear(value, bit))

I would like to reach as fast as possible, typ. 100~250 ns delay to reach HIGH and LOW as square wave signals for controlling of high speed mux. The Due runs at 84MHz, and the SPI clock pin had been tested with 11.9 ns duration square wave. Is SPI clock pin the only pin to have the highest speed or not?
Please feel free to give any suggestion.

I hope that my problem is explained well, and feel free to ask me, if you have any doubts.


Jul 04, 2013, 03:31 pm Last Edit: Jul 04, 2013, 03:45 pm by Graynomad Reason: 1
None of that direct port manipulation stuff in the books and tutorials will work on the Due unless they have been rewritten to use the SAM registers.

The SAM has over 40 registers for each of the 4 ports, I haven't programmed on the SAM at all yet but reading the data sheet it looks like the regs you need are

PIO_SODR - Set Output Data Register
PIO_CODR - Clear Output Data Register

You write a word to these regs, any 1 bits written to PIO_SODR will set the corresponding pin, any 1 bits written to PIO_CODR will clear the corresponding pin. There are four ports and these regs are all memory-mapped, see section 32.7.19 and 32.7.11

This must all be documented somewhere, but it looks to me that you have to do something like this

Code: [Select]
Pio *myPio = (Pio*)0x400E0E00;   // create a pointer to a "structure" that is the PIO controller for port A

myPio->PIO_PER = 1u;        // allow the PIO controller to control pin 0
myPio->PIO_OER = 1u;             // set bit 0 to output
myPio->PIO_SODR = 1u;             // set bit 0
myPio->PIO_CODR = 1u;             // clear bit 0

Note I just got this from various files and data sheets, I may be way off the mark.

Note also that the first of these lines is probably already done by the Arduino startup code, and the second line by a pinMode(x,OUTPUT) call.

Hopefully there's someone here that can point to a tute or something as I need to learn more about this as well.

EDIT: Holy crap that actually compiled :), but that doesn't mean it will work and I don't have a board to try it on.


Rob Gray aka the GRAYnomad www.robgray.com


I'm using this:

Code: [Select]

static __inline__ void digitalWriteDirect(int pin, boolean val){
  if(val) g_APinDescription[pin].pPort -> PIO_SODR = g_APinDescription[pin].ulPin;
  else    g_APinDescription[pin].pPort -> PIO_CODR = g_APinDescription[pin].ulPin;

It's from another thread and is quite fast.  Just replace all calls of digitalWrite with digitalWriteDirect

Go Up