Go Down

Topic: port maipulation (Read 1 time) previous topic - next topic

berga123123

Hallo,
I wrote the following code:

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;
}

inline int digitalReadDirect(int pin){
  return !!(g_APinDescription[pin].pPort -> PIO_PDSR & g_APinDescription[pin].ulPin);
}

void setup() {               
  pinMode(22, OUTPUT);     
  pinMode(11, INPUT);     
  Serial.begin(9600);
}

void loop() {
  digitalWriteDirect(22, HIGH);   
  delay(1000);           
  digitalWriteDirect(22, LOW);   
  delay(1000);         
  Serial.println(digitalReadDirect(11));

}


How can I write direkt 2 Ports at the same time ? for example Pin D23 and D24

MorganS

Not possible. Reassign your hardware to use pins on the same port if you absolutely must have parallel writes.

In 99.99% of all Arduino programs, using regular digitalWrite() or digitalWriteFast() sequentially will work. Parallel is only necessary 0.01% of the time.
"The problem is in the code you didn't post."

CrossRoads

That's not hard.
Read the port.
Change the 2 bits to what you want.
Write the port.
Designing & building electrical circuits for over 25 years.  Screw Shield for Mega/Due/Uno,  Bobuino with ATMega1284P, & other '328P & '1284P creations & offerings at  my website.

MorganS

Well, I didn't bother to check the first time but pin 23 and 24 are actually on the same port, so you can write synchronously to them. Another combination such as 24 and 25 are on different ports so synchronous writes aren't possible.

It is a little harder to 'just write' to the port on the Due. You would have to ensure that the related PIOx_OWER (output write enable register) was set to 0xFFFF, although you may be lucky that it defaults to that value. And no, you can't write directly to OWER, you have to set it through OWSR and OWDR.
"The problem is in the code you didn't post."

berga123123

Is that right ?

pinMode (23, OUTPUT);
pinMode (24, OUTPUT);

REG_PIOA_SODR =0b1100000000000000;    // High  D23 and D24
REG_PIOA_CODR =0b1100000000000000;    // LOW  D23 and D24

ghlawrence2000

UTFT_SdRaw now included in library manager!! ;) High speed image drawing from SD card to UTFT displays for Mega & DUE.
UTFT_GHL - a VASTLY upgraded version of UTFT_CTE. Coming soon to a TFT near you! 8) Shipping April 1 2016!

MartinL

Hi berga123123,

The issue with using the SAM3X8E's set (SODR) and clear (CODR) data registers, is that they don't allow you to output a binary sequence in one write operation. You either have to set then clear, or clear then set.

Writing to the Output Data Status Register (ODSR), allows the Due to revert back to how the AVR microcontrollers' PORTx registers work, except that the ports are 32-bits. Provided the port pins are set as outputs, any binary sequence (containing 0s or 1s) written to this register, is output on the port in one write operation.

The following code shows how to set up a binary sequence on port D. It sets only the lowest four bits as outputs, then cycles through the sequence 0001, 0010, 0100 and 1000:

Code: [Select]
void setup() {
  REG_PIOD_OWER = 0xFFFFFFFF;     // Enable writes to whole of PortD's 32-bit, Output Data Status (ODSR) register: (B11111111111111111111111111111111)
  REG_PIOD_OER =  0x0000000F;     // Set the lowest 4-bits of PortD to outputs: (B00000000000000000000000000001111)
}

void loop() {   
  // Using the register definition: REG_PIOD_ODSR, could also use pointer to register contents: PORTD->PIO_ODSR
  REG_PIOD_ODSR = PIO_ODSR_P0;   // Set the output on P0 (digital pin 25) high, other outputs low: (B00000000000000000000000000000001)
  REG_PIOD_ODSR = PIO_ODSR_P1;   // Set the output on P1 (digital pin 26) high, other outputs low: (B00000000000000000000000000000010)
  REG_PIOD_ODSR = PIO_ODSR_P2;   // Set the output on P2 (digital pin 27) high, other outputs low: (B00000000000000000000000000000100)
  REG_PIOD_ODSR = PIO_ODSR_P3;   // Set the output on P3 (digital pin 28) high, other outputs low: (B00000000000000000000000000001000)
}

berga123123

Hallo Martin,

thank you,

But I do not know how I set it high.
Can you write a example please
 
REG_PIOD_ODSR = PIO_ODSR_P0;

MartinL

#8
Nov 28, 2016, 10:10 am Last Edit: Nov 28, 2016, 10:28 am by MartinL
Hi berga123123,

The SAM3X8E microcontroller used on the Due has 4 ports: A, B, C and D each 32 bits wide.

The line:

Code: [Select]
REG_PIOD_ODSR = PIO_ODSR_P0;
...simply loads port D with the value defined by PIO_ODSR_P0.

PIO_ODSR_P0 definition in 32-bit binary is just: B00000000000000000000000000000001.

So, in this instance pin 0 of port D is set high with all other port D outputs being cleared to low.

To set two bits high, again with all other port D outputs being cleared to low, you can logically OR the PIO_ODSR_Px definitions, for example:

Code: [Select]
REG_PIOD_ODSR = PIO_ODSR_P3 | PIO_ODSR_P0;
As PIO_ODSR_P3 definition in 32-bit binary is just:  B00000000000000000000000000001000, the resulting output on port D is B00000000000000000000000000001001.

It's not necessary to use the definitions though, alternatively you could replace them with a number:

Code: [Select]
REG_PIOD_ODSR = 0x00000009;
If you're just setting or clearing bits then it's more efficient to use the SODR and CODR registers, but if however you're intending to output a binary sequence to the port in a single write operation then it's necessary to use the ODSR register.

As shown in the above example, the Output Enable Register (OER) can be used to select only those port pins that you'd like to be affected, in this case pins P0 to P3.

Go Up