Hi, I am trying to port some code from my Uno to work on the Nano Every. The interrupts are completely different. I do have the datasheet and have been looking through it. I only ever understood interrupts for the Uno from a few guides I found, of which there seem to be none for the mega4089, at least that cover the basics. All the posts here have been rather complicated and specific. I was wondering if someone could post a simple program that just blinks the internal LED using a timer interrupt and not an external library? I think if I saw that, plus the docs I have, I could figure it out. Thanks in advance.
There are different ways to do this with compare match interrupts or overflow interrupts. I think it would be better for you to post the code you are trying to port from the Uno to the Nano Every, and your best effort at doing that.
not an external library
As you realize, the timers on the 4809 are complex, and a library might make some sense, I have used this one, which is available through the library manager
There is a very good book from Tom Almy called "Far Inside The Arduino: Nano Every Supplement" He covers comprehensibly all the things you can do with it.
You can get the code from his examples here
https://almy.us/arduinoeverybook.html
He covers examples of using the timers in the processor.
Better still buy the book.
+1 for the Tom Almy book. It sits on my desk.
Thank you very much for the link, that never came up when I searched. I'll have a look at the series.
As far as the code goes, I mentioned not being able to find an example of the standard blinking led code that everyone writes when they start out. Here's an example that runs on my Uno:
/*
* LAB Name: Arduino Timer Overflow Interrupt
* Author: Khaled Magdy
* For More Info Visit: www.DeepBlueMbedded.com
*/
ISR(TIMER1_OVF_vect)
{
TCNT1 = 40535; // Timer Preloading
// Handle The Timer Overflow Interrupt
digitalWrite(LED_BUILTIN, !digitalRead(LED_BUILTIN));
}
void setup()
{
TCCR1A = 0; // Init Timer1A
TCCR1B = 0; // Init Timer1B
TCCR1B |= B00000011; // Prescaler = 64
TCNT1 = 40535; // Timer Preloading
TIMSK1 |= B00000001; // Enable Timer Overflow Interrupt
pinMode(LED_BUILTIN, OUTPUT);
}
void loop()
{
// Do Nothing
}
This was found at: https://deepbluembedded.com/arduino-timer-interrupts/
The timers in a Nano Every are totally different to the timers in the Uno so you should not expect them to be compatible.
Without getting into the full data sheet, there is complete information on the 4809 timers here
https://ww1.microchip.com/downloads/en/Appnotes/TB3214-Getting-Started-with-TCB-DS90003214.pdf
https://ww1.microchip.com/downloads/en/Appnotes/TB3217-Getting-Started-with-TCA-DS90003217.pdf
There is also a good summary of the timers and a library which configures a B timer to work like TimerOne.h library. You can look at the source code for how to configure the timer for a periodic interrupt.
https://github.com/Kees-van-der-Oord/Arduino-Nano-Every-Timer-Controller-B/tree/master
Yes, I am aware of that and even stated that in my first post. The differences (and lack of examples online) are why I am posting here.
I appreciate the links, but why did you ask me to post code then?
-
To understand if you were trying to use a compare match or overflow interrupt.
-
To see what effort you had made to do it yourself.
I told you exactly what I had done in my first post, which was try to understand the docs.
Here is some example Timer overflow interrupt code for a Nano Every.
It uses the A timer, and leaves the 64x default pre scaler for a 4us tick.
I would recommend not changing the prescaler as it is shared with the timer B3 which controls millis() and micros().
There is code for the toggle at 100 ms which matches the AT328 code you posted. There is an alternate set up for a 1000ms toggle.
The blink period is set by the values in the period registers and the number of overflow counts.
volatile unsigned int tickA = 0;
volatile byte flag = 0;
unsigned long lastTime;
ISR(TCA0_OVF_vect) {
TCA0.SINGLE.INTFLAGS = TCA_SINGLE_OVF_bm; //clear flag by writing 1 resets interrupt
tickA++;
if (tickA >= 1) //100 ms overflow toggle
//if (tickA >=4) //4 x 250 ms overflow toggle
{
flag = 1;
tickA = 0;
digitalWrite(LED_BUILTIN, !digitalRead(LED_BUILTIN));
}
}
void setup_timer_A() {
//ATMega4809 runs at 16MHz without Main Clock Prescaller and default is TCA_SINGLE_CLKSEL_DIV64_gc
//4us per tick
TCA0.SINGLE.INTCTRL = TCA_SINGLE_OVF_bm; //enable overflow interrupt
TCA0.SINGLE.CTRLB = TCA_SINGLE_WGMODE_NORMAL_gc;//timer mode may break pwm
//100ms = 25000 x .000004 set H and L period registers
TCA0.SINGLE.PERL = lowByte(25000);
TCA0.SINGLE.PERH = highByte(25000);
/*
//1 second = 250000 x .000004 set H and L period registers
//16 bit register can't hold this value
//62500 = 250000/4
TCA0.SINGLE.PERL = lowByte(62500);
TCA0.SINGLE.PERH = highByte(62500);
*/
TCA0.SINGLE.CTRLA |= TCA_SINGLE_ENABLE_bm;
}
void setup() {
// put your setup code here, to run once:
pinMode(LED_BUILTIN, OUTPUT);
Serial.begin(115200);
while (!Serial) {
; // wait for serial port to connect. Needed for native USB port only
}
setup_timer_A();
}
void loop() {
if (flag == 1)
{
flag = 0;
Serial.println(millis() - lastTime);
lastTime = millis();
}
}
Great, works for me on my Nano Every.
This is how I would do it:
/* Blink using timer interrupt */
/* All timers are set up by the standard initialization of
the Arduino IDE with CLK_TCA at DIV64 giving 4us ticks.
I will use TCB2 to avoid messing with millis() or PWM */
ISR(TCB2_INT_vect) {
PORTE.OUTTGL = 1 << PIN2; // to toggle pin PE2
TCB2.INTFLAGS = TCB_CAPT_bm; // reset interrupt flag
/* Dont ask why TCB_CAPT_bm to reset TCB2_INT_vect */
}
void setup() {
PORTE.DIRSET = 1 << PIN2; // set pin PE2 (LED_BUILTIN) as output
TCB2.CTRLA = 0; // stop timer while setting up
TCB2.CTRLB = 0; // remove previous setting, default is Periodic Interrupt Mode
TCB2.CCMP = 62500; // 62500 x 4us = 250ms (max = 262ms)
/* for longer periods use an overflow counter */
TCB2.INTFLAGS = TCB_CAPT_bm; // reset possible previous interrupt
TCB2.INTCTRL = TCB_CAPT_bm; // enable interrupt
TCB2.CNT = 0; // clear timer
TCB2.CTRLA = TCB_CLKSEL_CLKTCA_gc | TCB_ENABLE_bm; // start timer
}
void loop() {
// put your main code here, to run repeatedly:
}
This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.