Timers en Arduino Due - SAM

Arduino, STM32 (Maple), ESP8266, etc
Responder
Avatar de Usuario
Naguissa
Administrador del Sitio
Mensajes: 325
Registrado: 04 Jul 2016, 11:17
Agradecido: 87 veces
Agradecimiento recibido: 82 veces
Contactar:

Timers en Arduino Due - SAM

Mensaje por Naguissa » 22 Feb 2018, 17:00

Mientras implementaba la compatibilidad de la librería uTimerLib con el microcontrolador SAM (Arduino Due) me he dado cuenta que existe poca información sobre como hacerlo en Internet. Y, debido a que uTimerLib usa un timer definido, he querido explicar cómo implementar timers manualmente en este microcontrolador.

Este microcontrolador posee 3 timers con 3 canales de 32 bits cada uno por cada timer. Esto significa que podemos usarlos casi como 9 timers de 32 bits, pero en cada grupo de 3 el prescaler ha de ser el mismo.

Prescalers

Cada Timer tiene 4 opciones de prescaler: 2, 8, 32 y 128.

Para referirnos a ellos usaremos las siguientes definiciones: TC_CMR_TCCLKS_TIMER_CLOCK1, TC_CMR_TCCLKS_TIMER_CLOCK2, TC_CMR_TCCLKS_TIMER_CLOCK3 y TC_CMR_TCCLKS_TIMER_CLOCK4 respectivamente.


Si usamos como ejemplo un Arduino Due, que funciona a 84MHz, los ticks por segundo quedarían:

Código: Seleccionar todo

Base		DEFINE		    Prescaler	Frecuencia	Intervalo base			Intervalo overflow
84MHz	TC_CMR_TCCLKS_TIMER_CLOCK1	  2	  42MHz		0,023809524us	102261126,913327104us, 102,261126913327104s
84MHz	TC_CMR_TCCLKS_TIMER_CLOCK2	  8	 10.5MHz	0,095238095us	409044503,35834112us, 409,04450335834112s
84MHz	TC_CMR_TCCLKS_TIMER_CLOCK3	 32	2.625MHz	0,380952381us	1636178017,523809524us, 1636,178017523809524s
84MHz	TC_CMR_TCCLKS_TIMER_CLOCK4	128	656.25KHz	1,523809524us	6544712070,913327104us, 6544,712070913327104s

Timers

Los 3*3 timers se definen como:

Código: Seleccionar todo

Nombre	Timer	Canal	Pines disponibles
  TC0	  0	  0	   2, 13
  TC1	  0	  1	   60, 61
  TC2	  0	  2	   58
  TC3	  1	  0	    -
  TC4	  1	  1	    -
  TC5	  1	  2	    -
  TC6	  2	  0	   4, 5
  TC7	  2	  1	   3, 10
  TC8	  2	  2	   11, 12
Recuerda: ¡32 bits!

Acostumbrados a timers de 8 o 16 bits, recuerda que estos timers son de 32 bits (unsigned long int).



(Continuará en breve)

Tags:

Avatar de Usuario
Naguissa
Administrador del Sitio
Mensajes: 325
Registrado: 04 Jul 2016, 11:17
Agradecido: 87 veces
Agradecimiento recibido: 82 veces
Contactar:

Re: Timers en Arduino Due - SAM

Mensaje por Naguissa » 23 Feb 2018, 08:44

Pasos y código para programar un Timer en un microcontrolador SAM:

La arquitectura SAM es bastante peculiar comparada con los sencillos AVR. Debido a su potencia, por defecto la mayoría de partes de este microcontrolador están apagadas, de manera que así se reduce muchísimo su consumo. Pero por ello mismo debemos activarlas para poder usarlas.

Por ello, antes de usar el Timer en sí debemos activar dichas partes:

En este código usaré diversos 'comodines' cuyos nombres corresponderán a los nombres de las tablas anteriores:

- _TC_TIMER_ - Corresponde a la columna "Timer".
- _TC_NAME_ - Corresponde a la columna "Nombre".
- _TC_CHANNEL_ - Corresponde a la columna "Canal".
- _PRESCALER_ - Corresponderá a la columna "DEFINE".
- _ID_TC_TIMER_ - No es una columna, sino un #define que usamos y que corresponde a "ID_" con el _TC_TIMER_ que usamos; así, para TC3 será ID_TC3.
- _TC_IRQn_ - Tampoco es una columna, es un #define que corresponde al _TC_TIMER_ con "_IRQn" detrás; así, para TC3 será TC3_IRQn.
- __COUNT__ - Es el número de 32 bits cuando deseamos que salte la interrupción
- _HANDLER_ - Es el nombre de la función que hace de manejador para la interrupción; se compone por el _TC_NAME_ con el texto "_Handler".

Código: Seleccionar todo

pmc_set_writeprotect(false); // Permite la reprogramación
pmc_enable_periph_clk(_ID_TC_TIMER_); // Activar el periférico
TC_Configure(_TC_TIMER_, _TC_CHANNEL_, TC_CMR_WAVE | TC_CMR_WAVSEL_UP_RC | _PRESCALER_); // Configuramos el timer

TC_SetRC(_TC_TIMER_, _TC_CHANNEL_, __COUNT__); // Int on last number
//TC_SetRA(_TC_TIMER_, _TC_CHANNEL_, __COUNT__); // EXTRA: Si deseas usar PWM, este es el número donde el pin de salida pasará a estado low. Así, podríamos definir que la señal PWM esté baja del tick 12 al 40000 y el resto a alta. Si no vas a usar PWM no hace falta ponerlo.

TC_Start(_TC_TIMER_, _TC_CHANNEL_); // Iniciamos la cuenta

// Cuidado aquí, TC_CHANNEL (sin los "_") NO es un texto a substituir; la substitución está entre los corchetes:
_TC_TIMER_->TC_CHANNEL[_TC_CHANNEL_].TC_IER = TC_IER_CPCS; // Habilitamos las interrupciones ligadas al registro C
_TC_TIMER_->TC_CHANNEL[_TC_CHANNEL_].TC_IDR = ~TC_IER_CPCS; // Y quitamos el flag de deshabilitar interrupciones (sí, dos pasos, habilitar y quitar bloqueo)

NVIC_EnableIRQ(_TC_IRQn_); // Finalmente habilitamos la interrupción del Timer en el dispositivo de interrupciones anidadas

// [...]

// Y en el programa, como instrucción global, definiremos la función a adjuntar a la interrupción:
void TC3_Handler() {
	TC_GetStatus(_TC_TIMER_, TC_CHANNEL); // Reseteamos la interrupción; de no hacerse no se volverá a llamar.
	
	// Nuestro código
}
Y aquí tenéis un ejemplo completo, usando El timer TC3, es decir, Timer 1 y canal 0, con un prescaler de 32

Código: Seleccionar todo

pmc_set_writeprotect(false); // Permite la reprogramación
pmc_enable_periph_clk(ID_TC3); // Activar el periférico
TC_Configure(TC1, 0, TC_CMR_WAVE | TC_CMR_WAVSEL_UP_RC | TC_CMR_TCCLKS_TIMER_CLOCK3); // Configuramos el timer (prescaler 32)

TC_SetRC(TC1, 0,30000); // Lo he puesto a boleo, ni idea....

TC_Start(TC1, 0); // Iniciamos la cuenta
TC1->TC_CHANNEL[0].TC_IER = TC_IER_CPCS; // Habilitamos las interrupciones ligadas al registro C
TC1->TC_CHANNEL[0].TC_IDR = ~TC_IER_CPCS; // Y quitamos el flag de deshabilitar interrupciones (sí, dos pasos, habilitar y quitar bloqueo)

NVIC_EnableIRQ(TC3_IRQn); // Finalmente habilitamos la interrupción del Timer en el dispositivo de interrupciones anidadas

// [...]

// Y en el programa, como instrucción global, definiremos la función a adjuntar a la interrupción:
void TC3_Handler() {
	TC_GetStatus(TC1, 0); // Reseteamos la interrupción; de no hacerse no se volverá a llamar.

	// Nuestro código
}

Responder
  • Similar Topics
    Respuestas
    Vistas
    Último mensaje