Timer Interrupt on Due for Matrix Keyboard Scan


I am trying to get to work a program on Due that uses timer interruption to multiplex some outputs.

The project consists of a matrix keyboard and I am trying to put together a scan program that could be used in different projects using the Due.

The program is for a 8x4 matrix keyboard and I am only getting the number one I printed on the first column scan.

When I try to conect a output to a input to see if something is printed, nothing happens.

I’m really stucked on this and I appreciate alll your efforts to help me.

Thanks you very much.

teclado_varredura_8x4_Due.ino (14.7 KB)

The most obvious issue I can see in your code:

In TC7_Handler() counter is incremented. BUT counter should have been previously declared as volatile before setup() (volatile uint8_t counter); because counter has to keep the previous value before incrementing in the interrupt handler.

Thank you for your reply!

So, I've just changed that and compiled the code and after downloading I'm still getting the number one on my serial monitor when I should be getting one to eight repeatedly and as soon as I connect a output to a input I should be getting the correspondent signal on the serial monitor.

I'm kinda thinking it may be the way I set up the timer.

Any other thoughts about that are appreciated.

Declare control and number as volatile for the same reasons (they are used inside the interrupt handler).

I see no other issue with your Timer Counter settings.

An example sketch with a Timer Counter and its interrupt handler:

/*                     Blink an LED with a 1 Hz frequency                        */
void setup() {

void loop() {

void tc_setup() {

  PMC->PMC_PCER0 |= PMC_PCER0_PID29;                       // TC2 power ON : Timer Counter 0 channel 2 IS TC2

  TC0->TC_CHANNEL[2].TC_CMR = TC_CMR_TCCLKS_TIMER_CLOCK1   // MCK/2, clk on rising edge
                              | TC_CMR_WAVE                // Waveform mode
                              | TC_CMR_WAVSEL_UP_RC;       // UP mode with automatic trigger on RC Compare

  TC0->TC_CHANNEL[2].TC_RC = 2100;                         // Frequency = (Mck/2)/TC_RC  Hz = 20 KHz

  TC0->TC_CHANNEL[2].TC_IER = TC_IER_CPCS;                 //Interrupt on RC compare match
  NVIC_EnableIRQ(TC2_IRQn);                                // Enable interrupts

  TC0->TC_CHANNEL[2].TC_CCR = TC_CCR_SWTRG | TC_CCR_CLKEN; // Software trigger TC2 counter and enable

void TC2_Handler() {

  static uint32_t Count;

  TC0->TC_CHANNEL[2].TC_SR;         // Read and clear status register;

  if (Count++ == 20000) {
    PIOB->PIO_ODSR ^= PIO_ODSR_P27; // Toggle LED_BUILTIN every 1 Hz
    Count = 0;
  // Some stuff, as short as possible

EDIT: You should not call readkeyboard() inside the interrupt handler (keep it as short as possible !). Just set a Flag in the interrupt handler so that readkeyboard can be called inside loop().

Thank you so much for helping me through this.

I did exactly what you said, I called the function readKeyboard() on the void loop with a flag and the code started running after that. It shows the numbers one to eight but it keeps printing some stuff on the serial monitor even tough I didn’t connect anything.

By the way, thank you for your code it will make me understand the timer interrupt better on the Due.

I attached the up-to-date code if you or anyone wants to take a look at it.

teclado_varredura_8x4_Due.ino (14.9 KB)

flag should declared as volatile for the same reasons !! AND set flag to 0 after calling readkeyboard() in loop().

flag should declared as volatile for the same reasons !!

Sorry about that!! I'm too stuborn.

I changed what you said but still there's something wrong, it keeps showing caracthers on the serial monitor, which should show up only if I connect the input and output. I've noticed it keeps showing particularly the last row (D) sequentially.

Appreciate your attention, again sorry about the inconvinience.