Go Down

Topic: Arduino due digital pins programming. (Read 5454 times) previous topic - next topic

EJLED

Hi, friends.

i am new to arduino due, i have around 40 digital inputs, i want to access 32 bit on single clock.

i am planning to use 40 pins of arduino due among 54 pins.  and want code that can access all 32 pins in single clock. i do not want to use SPI or any other communication protocol.

How can i do it...? can all 54 pins serve as digital input, and can it read 32 digital signal on single clock cyle..?

kindly help me.

thanks.

DVDdoug

FYI - There is a sub-forum for the Due.

It should be possible  but I've never used the Due and I don't know how to do it.   (I know there are port commands that allow you to read 8 bits with the regular Arduino.)

It is a 32-bit processor and the datasheet for the chip says:
Quote
Up to six 32-bit Parallel Input/Outputs (PIO)

cattledog

#2
Feb 05, 2016, 06:47 pm Last Edit: Feb 05, 2016, 06:48 pm by cattledog
Quote
code that can access all 32 pins in single clock
No.

If you take a look at the Due pin out information you will see that there is no port with a complete breakout of 32 pins.

You may be able to find 32 pins which can be read with two or three reads across several ports, but they may not be completely adjacent within the port, and you might need to perform some masking and shifting to isolate what you need.

You will need to define your pins and the the port read and selection code before before you can determine the exact number of clock cycles.

I agree with DVDdoug, that you might be better off in the Due section of the forum.

EJLED

Thank you so much DVDdoug and cattledog, I have already posted the same question http://forum.arduino.cc/index.php?topic=376827.0 on ARDUINO DUE forum.

Thank you once again. i will look the datasheet and then move further. if any one have done this kindly help me if possible.

Thanks

westfw

The SAM3X chip only has ONE "port" with the full 32bits brought out to pins.   This is PORTB, and it shares some of its pins with other important functions (JTAG, for instance), and doesn't have those pins connected to Arduino Pins.
So reading or writing 32 pins at once is going to be impossible.
OTOH, there are ONLY 4 "ports", so you should be able to read ANY combination of pins in less than 4 reads.  Which at 84MHz, isn't going to take very long!
Also note that the Arduino Pins are arranged in a "convenient" order WRT Arduino functionality (which does not include "wide" access), so that adjacent Pins will not usually be adjacent bits in a Port.

EJLED

Thanks everyone.

can anyone tell me how to read digital 0 and 1 from Arduino Due's pin 22 to 51. with trigger on simple interrupt on INT pin.?

then i want to save that data in to memory , but first i want to read it at 1 Mhz sample.

Thanks.

cattledog

#6
Feb 08, 2016, 09:25 pm Last Edit: Feb 08, 2016, 11:28 pm by cattledog
The command for reading the status of the ports is REG_PIOX_PDSR where X is the register.

Now its time for you to do some work. Go through the pin out data for the Due (linked on post 2) and make a list of your pins(22-51)broken down by PA n, PB n, PC n, PD n where n is the bit number on the "port" linked to the digital pin.

When you know which locations on which ports you want to read, you will then perform a series of port readings with masks and bitshifts. You should familiarize yourself with the bitwise AND & , bitwise OR | and the bitshift >> << operators. Then you need to combine what you extract from the 4 ports back together into the 32 bits.

What you are trying to do will make your head spin.

You may find it easier to break the port reads into several smaller chunks so that you are only reading contiguous bits at any time.

Here's an example of how I selected and reassembled 16 bits out of PortC on pins 34-41 and 44-51

Code: [Select]
long value = REG_PIOC_PDSR;
  value = value & 0xffffc; //clear top 11 and bottom 2 bits with mask
  value = value >> 2; //shift away the lower 2 cleared bits
  //remove the two junk bits from center of data
  int lo8 = value & 0xff; //mask and save lower 8 bits
  value = value >> 10; //shift away the lower 10 bits to clear middle two
  value = value << 8 | lo8; //reassemble continuous 16 bits


Once you have the port reading code worked out, calling a read function with an interrupt will be straightforward.

Why do you need to read 32 bits at 1MHz? What are you planning to do with the 32 bit values at 1MHz? Where are you going to put them?


EJLED

Thank you so much Cattledog, i am planning to make something like logic analyzer. which reads 0 and 1, at different sampling rate. then i want to plot data on the labview based display.

i have read twise about datasheet of SAM3X and due port manipulation but can not able to understand it,( if any Video you can give link) i m new to coding as well as ARM architecture, i have worked on 8051, but it was totally different core basic level. so i m facing big problem in coding this.


thank you.

epiception

#8
Feb 28, 2017, 08:46 am Last Edit: Feb 28, 2017, 08:53 am by epiception
Hey Guys,

I read cattledog's answer here on being able to read 16 bits from PortC Register on the Due. I was wondering if this is a truly parallel operation. I'm trying to read a high speed 10 bit absolute encoder and it is crucial that I can read the 10 bits in parallel. So I cannot rely on the UNO or Mega as it does not allow without reading from 2 different ports and aggregating the value. This has led to mistakes and bit shifts in the past. Also, I was hoping to get a quick fix rather than entering I2C or another interfacing operation, like a 10 bit parallel DAC that I could connect to an analog pin.

Can the Arduino Due solve my problem, considering the 32 bit architecture?

Thanks,

ard_newbie

#9
Feb 28, 2017, 10:11 am Last Edit: Feb 28, 2017, 12:07 pm by ard_newbie
A method to capture 10 bits in a row is to program a Timer Counter and enable an interrupt at the desired frequency on, e.g. Overflow or Up_RC (see timer counter datasheet section) and/or a DUE TC lib.
https://github.com/antodom/tc_lib

In your Timer Handler, you will make a copy of PIOx->PIO_PDSR in a 32_bit buffer, and in loop(), a state machine will be controlled by bit levels of your buffer.


Another method: program a memory-to-memory transfer under control of the AHB DMA with a linked list item LLI to repeat continuously a copy of PIOx->PIO_PDSR into a 32_bit buffer.

Using the DMA Controller removes processor overhead by reducing its intervention during the transfer. This significantly reduces the number of clock cycles required for a data transfer, which improves microcontroller performance.

1/ Reading the I/O line levels requires the clock of the PIO controller to be enabled

2/ Declare 10 pins of PIOx as input. Note that the DUE is 3.3 v compliant, use logic level shifters if necessary.

3/ Program a Linked List Item

4/ Program a DMA mem2mem using an LLI to copy continuously into your buffer, e.g. :
SADDR = (uint32_t) &PIOx->PIO_PDSR;  // x = A, B, C or D
uint32_t YourBuffer[1];
DADDR = (uint32_t) YourBuffer;

5/ Start your DMA process

6/ In loop(), you will have a state machine controlled by bit levels in your buffer.

See an example of DMA mem2mem:
https://github.com/manitou48/DUEZoo

westfw

Code: [Select]
long value = REG_PIOC_PDSR;


that reads all of the bits at one time, or as close as you can get with modern hardware.
The subsequent "moving bits around" isn't instantaneous, but it all operates on the bit values that have already been read, so it doesn't matter...

Aren't most encoders specifically set up so that some bits are know to change faster than others?  And if you read the slow-changing bits after you have a stable set of fast-changing bits, you can be pretty certain that your overall reading is OK?



epiception

Hey guys, Thank you for the prompt replies.

For my encoder, I actually was facing an issue on all pins, even  after shift operations earlier. While using direct port manipulation on the Arduino Uno did help, it wasn't a complete solution, and the values change too fast. Further, in my case I could'nt lose any of the resolution, so clearly that wasn't an option.

I haven't bought the Due yet, but it based on westfw's answer, it seems clear that the reading is similar to direct port access except its the entire 32 bit register. I will take ard_newbie's suggestions into account as well and get back here soon once it works.

Also could you'll suggest an easy to interface DAC as a fallback, just in case?

Thanks again,
:)

HermannSW

#12
Mar 02, 2017, 03:12 am Last Edit: Mar 02, 2017, 03:26 am by HermannSW
and want code that can access all 32 pins in single clock.
This posting shows that you can buy fully functional 24Msps logic analyzer for <5$ (see photo).
And that Arduino Due can read 32 pins of a port in 3 clock cycles which is 28Msps (Million samples per second). Capture length is restricted by 96KB ram size, so you can measure 32 channel up to 821μs (8 channel up to 3.3ms) @28Msps, not more:
https://forum.arduino.cc/index.php?topic=448222.msg3089305#msg3089305

Hermann.
https://forum.arduino.cc/index.php?topic=462107.msg3236016#msg3236016
http://stamm-wilbrandt.de/en/Raspberry_camera.html

epiception

Thanks for the suggestions,

The Due seems to be working, apart from a problem I'm currently facing. Is there any way to set the input register to 0 (setting the pull_up to 0) so that I can start with initial values of 0? Another device I'm interfacing (a new BCD Encoder) seems to give a LOW value of 2.5-3.5 V and high of 11+v? (This is after a resistor bridge circuit already).

Go Up