Hi,
I am using Due and need to send data on Port D and receive on Port C at a high rate ( >4 MHz ). Using the PIO registers I am able to get a maximum rate of about 1 MHz. The commands that I am using for writing and reading are:
PIOD->PIO_ODSR = A[ii];
ii = ii+1;
R[ii] = PIOC->PIO_PDSR;
Is there any way I can speed up this update rate, considering Due is 84 MHz.
I'll bet that bit of code is not the problem. Post it all. If it's too long to post, strip out all uneccessary parts, leaving just enough code to demonstrate the problem. And please, please read the forum guide in the sticky post before you post your code.
I do not think there is any issue with the code, I am receiving the expected data, the problem is that just the three lines of code is taking about 1 micro second, limiting my max sampling frequency to 1MHz. I kept the code very simple, I have two arrays of length 1024, which i initialized to alternating 1s and 0s, a for loop just runs these three commands i.e. (i) send data to port D, (ii) increment counter and (iii) read port C. When i see the result on a scope i find that these three instructions are taking 1usec. Which means the three instructions take about 84 clock cycles. Is this reasonable to take this long time? I would like to improve the sampling rate to at least 4 MHz which means I need to be able to do the three jobs in 250 ns. Is there a way to do that? Do I need to use assembly? if so can anyone guide me, I really appreciate your help.
Several methods can be leveraged to read/write to/from PIOs on a DUE (PIO_PDSR, PWM, DMA,...).
An overal description of the project would be much useful without describing solutions you can imagine : what exactely are you receiving in your final project (frequency ?, timelapse ?, always the same pattern ?), what exactely are you sending (how it depends from what you received ?, length of the pattern ?, frequency ?).
There are numerous threads which address this topic, a recent one:
Please read the first post in any forum entitled how to use this forum. http://forum.arduino.cc/index.php/topic,148850.0.html . Then look down to item #7 about how to post your code.
It will be formatted in a scrolling window that makes it easier to read.
Can you please post a copy of your circuit, in CAD or a picture of a hand drawn circuit in jpg, png?
What is the application that requires this sort of speed?
Hi Ard and Tom, thank you for the suggestions. The details of the project are as follows:
I need to excite a PZT sensor with max frequency of 400 kHz, the signal then travels to another PZT nearby and I need to read the output of that PZT with at least 10 samples per cycle. This means I need to be able to read at 4MHz. Arduino is connected to external 20 MHz ADC and DAC. PWM is being used to generate a clock signal for both the ADC and DAC at 20MHz. The excitation signal can change in frequency, number of cycles and amplitude which is done by a PC. The length of the excitation signal array and received signal array can be fixed to 256. The PC sends the excitation signal to Arduino, which is stored in an array. The main loop then sequently sends out one sample from the array to Port C (driving an external DAC) and reads Port D (connected to an external ADC). The received signal is stored in another array. Once 256 samples are done then Arduino sends the received data to PC.
The problem i am having is that the PIOD->PIO_ODSR = A[ii] and R[ii] = PIOC->PIO_PDSR; are a bit slow. Can you please help me out about how PWM and DMA can be used in this situation.
Here is a simple code that I am using at the moment just to verify the speed of the system and I get 1MHz sampling rate. I would love to see how PWM and DMA can be used to improve the speed, so I look forward for your replies, thanks again.
Aftab
const int N = 256; //length of signals
byte A[N]; //excitation signal
byte R[N]; //received signal
unsigned int i;
/////////////////////////////////////////////////////////
void setup() {
for (i=0;i<N;i++){ // initialize arrays
A*=i;*
}* // port D as output port PMC->PMC_PCER0 = PMC_PCER0_PID14; // PMC = power management controller, PIOC power on
//PCER0 = peripheral clock enable register 0.*
// PID14 is the peripheral identifier for port D where as PID13 is for port C* PIOD->PIO_PER = 0x00000FFF; // PIO = parallel input output
//PIO enable register* PIOD->PIO_OER = 0x00000FFF; // PIO output enable register PIOD->PIO_PUDR = 0x0000FFFF; // PIO pull-up disable register // Port C as input port PMC->PMC_PCER0 = PMC_PCER0_PID13; // PIOC power on PIOC->PIO_PER = 0x000001FF; // PIO enable register PIOC->PIO_ODR = 0x000001FF; // PIO output disable register PIOC->PIO_PUDR = 0x000001FF; // PIO pull-up disable register Serial.begin(9600); } ///////////////////////////////////////// void loop() {
for (ii=0;ii<N;ii++){*
PIOD->PIO_ODSR = A[ii]; //ourput data status register*
R[ii] = PIOC->PIO_PDSR; // pin data status register*
Hi Paul,
Sorry if I gave a wrong impression of ignoring your suggestion. I described my problem in more detail above, please take a look. Hope to hear from you.
You might find a part of the answer in the thread I listed in reply #6: Enclose your code in loop() with a while(true) because loop() does another process that you don't need at each iteration, it takes time.
There are several issues with your code, one of them:
The output mask is on 12 bits, however you declare A as an array of bytes.
The input mask is on 9 bits, however you declare R as an array of bytes.
Your project description is still unclear to me :o ...
aftab902:
Hi Paul,
Sorry if I gave a wrong impression of ignoring your suggestion. I described my problem in more detail above, please take a look. Hope to hear from you.
No. I pleaded with you to read the forum guide back in post #1. You continue to ignore my suggestions. I don't want to waste any more of my time.