Hey everyone,
I am not only new to programming the arduino due but to arduino in general, so I would be really happy if you could review my code real quick. Especially the direct port access parts (I/O, T/C, DAC). I would appreciate some feedback before I take my 1,5h journey to a place were I can test it with a function generator.
For the direct port access I kind of patched some code together which i found in different forum threads due to my lack of experience.
It's supposed to count the frequency of a non-periodic square wave input signal[1-6MHz] by counting the number of timer counter pulses inbetween the input pulses.
PS: It compiles without errors.
// This program calculates the frequency of TTL Pulses by measuring the time in between pulses
// The program reads in TTL Pulses via the I/O Pins and outputs the frequency by the DAC
// Operating system: Windows 10 Home
// Software: Arduino IDE
// Hardware: Arduino due, AT91SAM3X8E
// Version: 1.0
// Released: DD.MM.YYYY
//#define TC_PERIOD 0.00000002380952381 // 23,80952381 ns
#define TC_CLK 42 //timer counter clock is half of MCK (84MHz)--> 42MHz
#define freqNum 5 // number of frequencies to calculate the mean frequency
// global variables
int inputPin = 51; // Pin which reads in TTL signal (94/C.12/D51)(PC12 on SAM3X8E)
int outputPin = 66; // DAC0 PB15
uint32_t counterValue; // variable to store the current counter value
uint32_t lastFreq[freqNum]; // latest frequencies
uint32_t meanFreq; // mean frequency
uint8_t freqPos; // Frequency Position in Array
bool isHigh; // boolean variable for edge detection
bool p12; // boolean to check input pin state
void setup() { // put your setup code here, to run once
//*****************************************************************************************************************************************************************************************
// setup variables
freqPos = 0;
isHigh = true;
// setup I/O
pinMode(inputPin, INPUT); // set pin51 = PC12 to input
// setup T/C0
PMC->PMC_PCER0 = 1<<27; // Peripheral clock enable reg.: Enable Timer TC0
TC0->TC_CHANNEL[0].TC_CMR = 0; // Control mode reg.: set Clock to MCK/2 = 42 MHz
TC0->TC_CHANNEL[0].TC_CCR = 1; // Channel control reg.: activate Timer --> Start + Enable
// setup DAC
pinMode(outputPin, OUTPUT); // set pin66 = PB15 as output
analogWriteResolution(10); // set resolution to 10-bit (1024)
PMC->PMC_PCER1 = PMC_PCER1_PID38; // DACC power ON
DACC->DACC_CR = DACC_CR_SWRST ; // Reset DACC
DACC->DACC_MR = DACC_MR_TRGEN_DIS // Hardware trigger disable = free running mode
| DACC_MR_USER_SEL_CHANNEL0 // select channel 1
// | DACC_MR_REFRESH (1) // needed???
| DACC_MR_STARTUP_0 // zero seconds start up time
| DACC_MR_MAXS; // set DAC to max speed
DACC->DACC_CHER = DACC_CHER_CH0; // enable channel 0 = DAC0
}
void loop() { // put your main code here, to run repeatedly:
//*******************************************************************************************************************************************************************************************
// read I/O Pin
p12 = !!(PIOC->PIO_PDSR & PIO_PC12); //read pin 12 on port C
// if level change detected read TC
if((p12==true)&&(!isHigh)) {
// start/stop time
counterValue = TC0->TC_CHANNEL[0].TC_CV; // counter value reg.: read actual TC value
TC0->TC_CHANNEL[0].TC_CCR = 4; // reset TC value to zero and start clock (bit 3)
// calculate latest frequency
lastFreq[freqPos] = TC_CLK/counterValue; // divide timer counter clock by nuber of counts [MHz]
freqPos++; // increment array index
if(freqPos > 4) { // prevent overflow and update array with new frequencies
freqPos = 0;
}
// calculate mean frequency
meanFreq = (lastFreq[0]+lastFreq[1]+lastFreq[2]+lastFreq[3]+lastFreq[4])/freqNum; // [MHz]
// output the frequency from 0V-3.3V
DACC->DACC_CDR = meanFreq; // use [Frequency = 5454545.454545 * voltage - 3000000] to get Frequency in Hz
//analogWrite(outputPin, meanFreq); // multiply measured voltage with factor 3636363,6364 to get Frequency in Hz
isHigh = true; // change isHigh so if statement is only accessed once per pulse
}
//****************************************************************************************************************************************************************************************
// if pin changed to low reset boolean variable
if ((p12==false)&&(isHigh)) {
isHigh = false;
}
}