➤ Programa
/* Marzo de 2016Tarjeta: STM32 Discovery
Microcontrolador: STM32F411VET6U
IDE: IAR Embedded Workbench
Programa que produce el parpadeo cíclico de LED verde (PD12) de la tarjeta
STM32 Discovery cada segundo. El retardo se genera manejando Systick.
*/
#include "stm32f4xx.h"
//--- Función que inicializa el puerto D y configura PD12 ---
void ini_LED_verde(void){
RCC->AHB1ENR |= 0x00000008; // Habilita el reloj para el puerto D
GPIOD->MODER |= 0x01000000; // Configura el pin 12 como salida
GPIOD->OSPEEDR |= 0x03000000; // PD12 podrá funcionar a alta velocidad
}
//--- Función que configura Systick ---
void config_systick_retardo(void) {
SysTick->CTRL &= ~(SysTick_CTRL_CLKSOURCE_Msk); // La señal de reloj para
// Systick es AHB / 8
// ( = 12 MHz, en este caso)
SysTick->LOAD = 12000 - 1; // Systick contará 12000 ciclos de una señal de reloj de 12 MHz
}
//--- Función que genera un retardo en milisegundos igual a num_ms ---
void retardo_ms(uint32_t num_ms) {
SysTick->CTRL |= SysTick_CTRL_ENABLE_Msk; // Habilita Systick
while (num_ms != 0) {
// Espera hasta que el valor del bit COUNTFLAG del registro de control de Systick sea igual a '1'
while ((SysTick->CTRL & SysTick_CTRL_COUNTFLAG_Msk) == 0) {}
--num_ms;
}
SysTick->CTRL &= ~(SysTick_CTRL_ENABLE_Msk); // Deshabilita Systick
}
//--- Función principal del programa ---
void main (void) {
ini_LED_verde();
config_systick_retardo();
while (1) {
GPIOD->BSRRL = 0x1000; // Enciende el LED
retardo_ms(1000); // Retardo de 1 segundo
GPIOD->BSRRH = 0x1000; // Apaga el LED
retardo_ms(1000); // Retardo de 1 segundo
}
}
➤ Observaciones
- No es necesario ningún componente electrónico externo a la tarjeta Discovery, dado que se utiliza el LED verde de la misma.
- El programa accede a los siguientes registros: RCC_AHB1ENR, GPIOD_MODER, GPIOD_OSPEEDR, STK_CTRL, STK_LOAD.
- En este programa se genera un retardo mediante el temporizador del sistema, SysTick.
- SysTick es un temporizador pensado para sistemas operativos en tiempo real, pero también puede ser usado como contador descendente estándar. Dispone de: un contador descendente de 24 bits, capacidad de auto-recarga, un sistema de generación de interrupciones cuando el contador llega a 0 y una fuente de señal de reloj programable.
- SysTick cuenta de manera descendente desde el valor de carga hasta 0, recarga ese valor en el registro STK_LOAD en el siguiente flanco de reloj y entonces cuenta descendentemente en los siguientes ciclos de reloj. Es decir, cuenta cíclicamente desde el valor cargado en STK_LOAD hasta 0.
- config_sysTick_retardo(): efectúa una llamada a la función encargada de configurar SysTick.
- retardo_ms(1000): llama a la función que crea el retardo valiéndose de SysTick. En este caso, la función llamada crea un retardo de 1000 milisegundos.
- SysTick->CTRL &= ~(SysTick_CTRL_CLKSOURCE_Msk): selecciona la fuente de la señal de reloj para SysTick. En este caso, poniendo a ‘0’ el bit CLKSOURCE del registro STK_CTRL (bit 2), se decide que la señal de reloj de SysTick sea AHB / 8, que es la frecuencia a la salida del prescaler AHB dividida entre 8. En la entrada anterior del blog se había elegido una frecuencia para AHB de 96 MHz. La constante SysTick_CTRL_CLKSOURCE_Msk está definida en el archivo core_m4.h, al igual que el resto de constantes relacionadas con SysTick y empleadas en este programa.
- SysTick->LOAD = 12000 – 1: carga el valor ‘11999’ en el registro STK_VAL (bits 23:0, RELOAD). Este valor se carga en el registro STK_VAL cuando el contador está habilitado y alcanza 0. El valor de RELOAD puede ser cualquiera en el rango comprendido entre ‘0x00000001’ y ‘0x00FFFFFF’.
- El valor de RELOAD se calcula según su uso: para generar un temporizador multidisparo con un periodo de N ciclos de reloj del procesador, hay que usar un valor de RELOAD de N-1. Por ejemplo, si se requiere una interrupción de SysTick cada 100 pulsos de reloj, RELOAD tiene que valer 99.
- Según el apartado 10.1.2 del documento RM0383 Reference Manual, el valor de calibración está fijado en 10500, lo que da una referencia de la base de tiempos de 1 ms para una frecuencia de reloj de SysTick de 10,5 MHz (HCLK/8, con HCLK ajustado a 84 MHz). En este programa, el valor de RELOAD hace que SysTick cuente 12000 ciclos de una señal de reloj de 12 MHz; para efectuar esta operación es necesario 1 milisegundo de tiempo.
- SysTick->CTRL |= SysTick_CTRL_ENABLE_Msk: habilita el contador, escribiendo un ‘1’ en el bit ENABLE del registro SysTick->CTRL. Cuando este bit está a ‘1’ el contador carga el valor de RELOAD desde el registro STK_LOAD y empieza a contar de manera descendente. Al llegar a 0, pone el bit COUNTFLAG (bit 16) a ‘1’ y opcionalmente activa la petición de excepción, dependiendo del valor de TICKINT, que es el bit 1 del registro STK_CTRL (en este ejemplo no se habilita la petición de excepción). Después de esto, carga el valor de RELOAD otra vez y sigue contando.
- while ((SysTick->CTRL & SysTick_CTRL_COUNTFLAG_Msk) == 0) {}: esta instrucción sirve para esperar hasta que el valor del bit COUNTFLAG del registro STK_CTRL sea igual a ‘1’. El bit COUNTFLAG devuelve un ’1’, si la cuenta del temporizador ha llegado a ‘0’; cuando sucede esto, que es cada milisegundo, se decrementa en una unidad el valor numérico contenido en la variable num_ms.
- SysTick->CTRL &= ~(SysTick_CTRL_ENABLE_Msk): deshabilita el contador, poniendo a ‘0’ el bit ENABLE del registro SysTick_CTRL. Esto es necesario porque mientras este bit esté habilitado el contador seguirá contando de manera cíclica.
- El programa accede a los siguientes registros: RCC_AHB1ENR, GPIOD_MODER, GPIOD_OSPEEDR, STK_CTRL, STK_LOAD.
- En este programa se genera un retardo mediante el temporizador del sistema, SysTick.
- SysTick es un temporizador pensado para sistemas operativos en tiempo real, pero también puede ser usado como contador descendente estándar. Dispone de: un contador descendente de 24 bits, capacidad de auto-recarga, un sistema de generación de interrupciones cuando el contador llega a 0 y una fuente de señal de reloj programable.
- SysTick cuenta de manera descendente desde el valor de carga hasta 0, recarga ese valor en el registro STK_LOAD en el siguiente flanco de reloj y entonces cuenta descendentemente en los siguientes ciclos de reloj. Es decir, cuenta cíclicamente desde el valor cargado en STK_LOAD hasta 0.
- config_sysTick_retardo(): efectúa una llamada a la función encargada de configurar SysTick.
- retardo_ms(1000): llama a la función que crea el retardo valiéndose de SysTick. En este caso, la función llamada crea un retardo de 1000 milisegundos.
- SysTick->CTRL &= ~(SysTick_CTRL_CLKSOURCE_Msk): selecciona la fuente de la señal de reloj para SysTick. En este caso, poniendo a ‘0’ el bit CLKSOURCE del registro STK_CTRL (bit 2), se decide que la señal de reloj de SysTick sea AHB / 8, que es la frecuencia a la salida del prescaler AHB dividida entre 8. En la entrada anterior del blog se había elegido una frecuencia para AHB de 96 MHz. La constante SysTick_CTRL_CLKSOURCE_Msk está definida en el archivo core_m4.h, al igual que el resto de constantes relacionadas con SysTick y empleadas en este programa.
- SysTick->LOAD = 12000 – 1: carga el valor ‘11999’ en el registro STK_VAL (bits 23:0, RELOAD). Este valor se carga en el registro STK_VAL cuando el contador está habilitado y alcanza 0. El valor de RELOAD puede ser cualquiera en el rango comprendido entre ‘0x00000001’ y ‘0x00FFFFFF’.
- El valor de RELOAD se calcula según su uso: para generar un temporizador multidisparo con un periodo de N ciclos de reloj del procesador, hay que usar un valor de RELOAD de N-1. Por ejemplo, si se requiere una interrupción de SysTick cada 100 pulsos de reloj, RELOAD tiene que valer 99.
- Según el apartado 10.1.2 del documento RM0383 Reference Manual, el valor de calibración está fijado en 10500, lo que da una referencia de la base de tiempos de 1 ms para una frecuencia de reloj de SysTick de 10,5 MHz (HCLK/8, con HCLK ajustado a 84 MHz). En este programa, el valor de RELOAD hace que SysTick cuente 12000 ciclos de una señal de reloj de 12 MHz; para efectuar esta operación es necesario 1 milisegundo de tiempo.
- SysTick->CTRL |= SysTick_CTRL_ENABLE_Msk: habilita el contador, escribiendo un ‘1’ en el bit ENABLE del registro SysTick->CTRL. Cuando este bit está a ‘1’ el contador carga el valor de RELOAD desde el registro STK_LOAD y empieza a contar de manera descendente. Al llegar a 0, pone el bit COUNTFLAG (bit 16) a ‘1’ y opcionalmente activa la petición de excepción, dependiendo del valor de TICKINT, que es el bit 1 del registro STK_CTRL (en este ejemplo no se habilita la petición de excepción). Después de esto, carga el valor de RELOAD otra vez y sigue contando.
- while ((SysTick->CTRL & SysTick_CTRL_COUNTFLAG_Msk) == 0) {}: esta instrucción sirve para esperar hasta que el valor del bit COUNTFLAG del registro STK_CTRL sea igual a ‘1’. El bit COUNTFLAG devuelve un ’1’, si la cuenta del temporizador ha llegado a ‘0’; cuando sucede esto, que es cada milisegundo, se decrementa en una unidad el valor numérico contenido en la variable num_ms.
- SysTick->CTRL &= ~(SysTick_CTRL_ENABLE_Msk): deshabilita el contador, poniendo a ‘0’ el bit ENABLE del registro SysTick_CTRL. Esto es necesario porque mientras este bit esté habilitado el contador seguirá contando de manera cíclica.
➤ Registros empleados
Para más información, ver los documentos RM0383 Reference Manual y PM0214 Programming manual.
No hay comentarios:
Los comentarios nuevos no están permitidos.