Hi all. I've implemented Sebastian Vik & cmaglie's timer code. I've got it working as is, with the LED. And I also tried a Serial.println and that works fine too.
However after transplanting the code to something more meaty (RGB Pixel light string) - the TC3_Handler only executes once.
The LEDs driver is using the hardware SPI channel - could it be anything to do with that? To rule out a clash of interrupts with the LED driver, I tried TC4/5 then TC0, but I still only get the first frame.
Any ideas? I'll post a video of the lights, if I get it working. (The code works otherwise - if I base the timer on time, it works fine)
I'll post the code, but you'd need the lights to see it:
(note the previous version of the code works without the timer)
Hi to all, I'm new to the arduino environment, I own an arduino due, I made some experiments with interrupts, apparently I cannot get the frequency higher than 250kHz, is this a known limit of the hardware ? I'm missing something, I read the datasheet and it states that TC_CMR_TCCLKS_TIMER_CLOCK1 is 84MHz / 2 = 41MHz so I was hoping that setting appropriately RA and RC (in my case 20 and 41 respectively) I would be able to acquire timer interrupts at 1MHz frequency.
I answer myself, I was wrong, with correct values the timer interrupt can be triggered at 1MHz.
The problem was that the analogWrite is too slow to go to that frequency, so I digged into the arduino/sam7core sources and found how to use the SAM library directly, the code (much fast) that I wrote is:
// This function to configure a Timer was given some replies above, I changed only the used CLOCK.
void startTimer(Tc *tc, uint32_t channel, IRQn_Type irq, uint32_t frequency) {
pmc_set_writeprotect(false);
pmc_enable_periph_clk((uint32_t)irq);
TC_Configure(tc, channel, TC_CMR_WAVE | TC_CMR_WAVSEL_UP_RC | TC_CMR_TCCLKS_TIMER_CLOCK1);
uint32_t rc = VARIANT_MCK/2/frequency; //2 because we selected TIMER_CLOCK1 above
TC_SetRA(tc, channel, rc/2); //50% high, 50% low
TC_SetRC(tc, channel, rc);
TC_Start(tc, channel);
tc->TC_CHANNEL[channel].TC_IER=TC_IER_CPCS;
tc->TC_CHANNEL[channel].TC_IDR=~TC_IER_CPCS;
NVIC_EnableIRQ(irq);
}
volatile boolean l;
void TC3_Handler()
{
TC_GetStatus(TC1, 0);
dacc_write_conversion_data(DAC0, (l = !l)*4095);
}
void setup() {
Serial.begin(115200);
pinMode(DAC0, OUTPUT);
analogWriteResolution(12);
pmc_enable_periph_clk(DACC_INTERFACE_ID);
dacc_reset(DACC_INTERFACE);
dacc_set_transfer_mode(DACC_INTERFACE, 0);
dacc_set_power_save(DACC_INTERFACE, 0, 0);
dacc_set_timing(DACC_INTERFACE, 0x0, 1, 0x0);
dacc_set_analog_control(DACC_INTERFACE, DACC_ACR_IBCTLCH0(0x02) |
DACC_ACR_IBCTLCH1(0x02) |
DACC_ACR_IBCTLDACCORE(0x01));
dacc_disable_trigger(DACC_INTERFACE);
dacc_set_channel_selection(DACC_INTERFACE, 0);
dacc_enable_channel(DACC_INTERFACE, 0);
// Start timer. Parameters are:
// TC1 : timer counter. Can be TC0, TC1 or TC2
// 0 : channel. Can be 0, 1 or 2
// TC3_IRQn: irq number. See table.
// 40 : frequency (in Hz)
// The interrupt service routine is TC3_Handler. See table.
startTimer(TC1, 0, TC3_IRQn, 1000000);
}
My classmate and I have written a timer library that encapsulates cmaglie's "Black Magic" code and allows the user to pass their own function that they want to be executed by the timer as a function pointer. I have included an example program that shows how this is used. It also cleanly allows the user to start multiple timers for multiple functions in the same sketch. I would appreciate any suggestions, criticism, comments, etc.
That looks pretty good to me! I've already implemented two timers in my own code - one for lights and the other to debounce/read some buttons. I think that your library will make things much neater. I'll try it next weekend.
Thanks for the feedback! Good to know that it is working well. If anyone thinks of some useful additions or improvements, I would be happy to add those in.
Thanks alot for all the activity on this post. This is the first time I used timers and all I could find were explainations on how to do it on the atmega328. I read the datasheet but couldnt make up how to do it on the due, so this helped alot!
Thanks for the idea BKM! I have added it to the library along with several other major improvements that should completely remove any IRQ references from the sketches and make it much cleaner and more user friendly. I will attach a link to my github repo tomorrow night once I get to test it a little bit.
When you download this, remove the "-master" part of the folder name so that it will show up correctly in the Arduino IDE and drag it into your libraries folder.
This has several new improvements. I would love some more testing/feedback if any of you get a chance.
Great library, Thank you very much for sharing it!
I noted that the function startTimer accepts as parameter the frequency at which the ISR is executed so I figure out that the maximum time between two consecutive calls of the ISR is 1 second. If I would like to executed some code at intervals of more than one second this should be managed inside the function corresponding to the ISR?
Hi!
I read trough this thread and find it very very helpful!
At the moment i am trying to measure times between signal-flanks. Therefore i need to stop the time between two (external)interrupts. I'd like to do this with a timer - but don't need the timer interrupt.
As far as i can see the actual time is hold in the TC_CV register. How do i get this value?
I saw you make a lot of use of functions like pmc_set_write_protect and others. Where do you get the documentation of these functions from? And why do you know they even exist?
Thanks a lot!
Could someone offer some more explanation on this library I am trying to get my head around it.
I would like to set up a 500Khz clock output to a ATA6870. Is this possible using this library?
Does setting up these timers on certain pins have any affects on other parts of the system like the SPI Bus as I am using this to communicate with the ATA6870 which will use a SCK of half the CLK input I provide as recommended in the ATA6870 datasheet?
I am new to ARM processor and I am struggling making the timer work as well. The content in this post have been very helpful. But I have a very very dumb question.
Where did you guys find the reference manual for those functions used in these code? Like(NVIC_EnableIRQ, TC_Configure, TC_SetRA, etc). From the files in IDE it seems to be a library from Atmel. I probably used wrong keyword; I tried to search those on google for hours and got nothing. =( =( =( =( =(
You have to do some homework as none of the above is a tutorial. Most of the functions/defines were not obvious until I read the code. Had to do the same thing for the DAC interface (e.g., to enable flexible & word mode updates).