I am going to developing a program which simultaneously runs 3 timers and returns data to the PC through serial in two of them. This can be achieved in the Arduino UNO by the following code:
int flag = 0;
void setup() {
// TIMER 2 for interrupt frequency 1000 Hz:
cli(); // stop interrupts
TCCR2A = 0; // set entire TCCR2A register to 0
TCCR2B = 0; // same for TCCR2B
TCNT2 = 0; // initialize counter value to 0
// set compare match register for 1000 Hz increments
OCR2A = 249; // = 16000000 / (64 * 1000) - 1 (must be <256)
// turn on CTC mode
TCCR2A |= (1 << WGM21);
// Set CS22, CS21 and CS20 bits for 64 prescaler
TCCR2B |= (1 << CS22) | (0 << CS21) | (0 << CS20);
// enable timer compare interrupt
TIMSK2 |= (1 << OCIE2A);
sei(); // allow interrupts
// TIMER 1 for interrupt frequency 1 Hz:
cli(); // stop interrupts
TCCR1A = 0; // set entire TCCR1A register to 0
TCCR1B = 0; // same for TCCR1B
TCNT1 = 0; // initialize counter value to 0
// set compare match register for 1 Hz increments
OCR1A = 62499; // = 16000000 / (256 * 1) - 1 (must be <65536)
// turn on CTC mode
TCCR1A |= (1 << WGM12);
// Set CS12, CS11 and CS10 bits for 256 prescaler
TCCR1B |= (1 << CS12) | (0 << CS11) | (0 << CS10);
// enable timer compare interrupt
TIMSK1 |= (1 << OCIE1A);
sei(); // allow interrupts
// TIMER 0 for interrupt frequency 100.16025641025641 Hz:
cli(); // stop interrupts
TCCR0A = 0; // set entire TCCR0A register to 0
TCCR0B = 0; // same for TCCR0B
TCNT0 = 0; // initialize counter value to 0
// set compare match register for 100.16025641025641 Hz increments
OCR0A = 155; // = 16000000 / (1024 * 100.16025641025641) - 1 (must be <256)
// turn on CTC mode
TCCR0A |= (1 << WGM01);
// Set CS02, CS01 and CS00 bits for 1024 prescaler
TCCR0B |= (1 << CS02) | (0 << CS01) | (1 << CS00);
// enable timer compare interrupt
TIMSK0 |= (1 << OCIE0A);
sei(); // allow interrupts
Serial.begin(57600);
}
//interrupt commands for TIMER 0 here
ISR(TIMER0_COMPA_vect){
Serial.println(flag) ;
}
//interrupt commands for TIMER 1 here
ISR(TIMER1_COMPA_vect){
Serial.println("complete") ;
}
//interrupt commands for TIMER 2 here
ISR(TIMER2_COMPA_vect){
flag++;
}
void loop() {
// put your main code here, to run repeatedly:
}
Now I want to make it on the nrf52832 bluefruit feather, but it seems like that the timers of the feather only work well for on-board command processing. Although it works when operating the digitalToggle in the IRQHandler, calling the serial.println will cause an error.
Does anyone knows how to solve this problem and achieves the same function as what I did on the Arduino UNO?
#include <bluefruit.h>
#define TIMEOUT1 100 // 100ms
void setup() {
Serial.begin(57600);
NVIC_EnableIRQ(TIMER0_IRQn);
NRF_TIMER0->TASKS_STOP = 1;
// Create an Event-Task shortcut to clear TIMER0 on COMPARE[0] event
NRF_TIMER0->MODE = TIMER_MODE_MODE_Timer;
NRF_TIMER0->BITMODE = (TIMER_BITMODE_BITMODE_24Bit << TIMER_BITMODE_BITMODE_Pos);
NRF_TIMER0->PRESCALER = 4; // 1us resolution
NRF_TIMER0->TASKS_CLEAR = 1; // clear the task first to be usable for later
NRF_TIMER0->CC[0] = TIMEOUT1 * 1000; //first timeout
NRF_TIMER0->INTENSET = TIMER_INTENSET_COMPARE0_Enabled << TIMER_INTENSET_COMPARE0_Pos;
/* Create an Event-Task shortcut to clear TIMER0 on COMPARE[0] event. */
// COMPARE HIGHER DIGIT MEANS TO SATISFY BOTH HIGH AND LOW DIGIT TO TRIGGER
NRF_TIMER0->SHORTS = (TIMER_SHORTS_COMPARE0_CLEAR_Enabled << TIMER_SHORTS_COMPARE0_CLEAR_Pos);
NRF_TIMER0->TASKS_START = 1;
}
void loop() {
}
extern "C"
{
void TIMER0_IRQHandler(void)
{
if (NRF_TIMER0->EVENTS_COMPARE[0] != 0)
{
//Serial.println(0); // error, cannot call serial.println in interrupt
digitalToggle(LED_RED);
NRF_TIMER0->EVENTS_COMPARE[0] = 0;
}
}
}