Visão Geral do SysTick
O SysTick é um temporizador de contagem regressiva integrado ao núcleo Cortex-M3, projetado para fornecer um intervalo de tempo periódico, essencial para sistemas operacionais em tempo real ou para funções de temporização precisas. Ao contrário dos temporizadores periféricos, o SysTick padroniza a geração de ticks, facilitando a portabilidade de software entre diferentes microcontroladores baseados em Cortex-M3.
Registrador de Controle e Status (STK_CTRL)
O STK_CTRL gerencia a operação do SysTick. Um bit importante é o COUNTFLAG, que indica quando o contador atinge zero. Este bit é automaticamente limpo após leitura, permitindo que o software detecte o término de uma contagem sem intervenção manual.
Implementação de Função de Atraso Preciso
Para criar atrasos em microsegundos, utiliza-se o polling do COUNTFLAG após configurar o SysTick para um período específico. O código a seguir demonstra uma abordagem onde o temporizador é reiniciado automaticamente, e o software verifica a conclusão de cada ciclo.
#include "stm32f10x.h"
// Função para verificar o estado do flag COUNTFLAG
static int VerificarFlagContagem(void) {
if (SysTick->CTRL & SysTick_CTRL_COUNTFLAG_Msk) {
return 1; // Flag setado
}
return 0; // Flag não setado
}
// Inicialização do SysTick para atrasos de 10 microsegundos
uint32_t ConfigurarSysTickAtraso(void) {
if (SysTick_Config(SystemCoreClock / 100000)) {
return 1; // Erro na configuração
}
// Desabilitar temporizador e interrupções
SysTick->CTRL &= ~(SysTick_CTRL_ENABLE_Msk | SysTick_CTRL_TICKINT_Msk);
return 0;
}
// Função de atraso em unidades de 10 microsegundos
void AtrasoMicrosegundos(volatile uint32_t tempoAtraso) {
SysTick->VAL = 0;
SysTick->CTRL |= SysTick_CTRL_ENABLE_Msk;
while (tempoAtraso-- > 0) {
while (!VerificarFlagContagem());
}
SysTick->CTRL &= ~SysTick_CTRL_ENABLE_Msk;
}
Este método é eficiente por evitar variáveiss globais, mas pode ser afetado por interrupções de alta prioridade, prolongando o atraso se o serviço de interrupção for longo. Recomenda-se usar períodos de pelo menos 10 microsegundos para minimizar erros de tempo.
Aplicação para Medição de Tempo de Segmentos de Código
O SysTick também pode medir a duração de trechos de código. Configura-se o temporizador com o valor máximo, e utiliza-se enterrupções para contar estouros. Os dados são armazenados em uma estrutura para análise posterior.
// Definições para armazenamento de medições
#define NUM_AMOSTRAS 4
typedef struct {
uint32_t maxAmostras;
uint32_t amostraAtual;
uint32_t largurasTempo[NUM_AMOSTRAS];
uint32_t mediaTempo;
} DadosTemporizacao;
DadosTemporizacao mediçõesAtuais;
volatile uint32_t estourosConta = 0;
// Inicialização do SysTick para medição máxima
uint32_t InicializarSysTickMedicao(void) {
if (SysTick_Config(SysTick_LOAD_RELOAD_Msk)) {
return 1;
}
SysTick->CTRL &= ~SysTick_CTRL_ENABLE_Msk;
return 0;
}
// Preparar variáveis para medição
void PrepararTemporizacao(DadosTemporizacao *ptrDados) {
mediçõesAtuais = *ptrDados;
mediçõesAtuais.maxAmostras = NUM_AMOSTRAS - 2;
}
// Iniciar medição de um segmento
void IniciarMedicao(void) {
if (mediçõesAtuais.amostraAtual < mediçõesAtuais.maxAmostras) {
SysTick->VAL = 0;
estourosConta = 0;
SysTick->CTRL |= SysTick_CTRL_ENABLE_Msk;
}
}
// Parar medição e processar resultados
void PararMedicao(void) {
if (SysTick->CTRL & SysTick_CTRL_ENABLE_Msk) {
SysTick->CTRL &= ~SysTick_CTRL_ENABLE_Msk;
uint32_t tempoTotal = SysTick_LOAD_RELOAD_Msk * estourosConta +
(SysTick_LOAD_RELOAD_Msk - SysTick->VAL + 1);
mediçõesAtuais.largurasTempo[mediçõesAtuais.amostraAtual] = tempoTotal;
mediçõesAtuais.amostraAtual++;
if (mediçõesAtuais.amostraAtual == mediçõesAtuais.maxAmostras) {
uint32_t soma = 0;
for (int i = 0; i < mediçõesAtuais.maxAmostras; i++) {
soma += mediçõesAtuais.largurasTempo[i];
}
mediçõesAtuais.mediaTempo = soma / mediçõesAtuais.maxAmostras;
}
}
}
// Rotina de interrupção do SysTick
void SysTick_Handler(void) {
estourosConta++;
}