Temporizador SysTick no STM32 para Atrasos Precisos e Medição de Tempo

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++;
}

Tags: STM32 SysTick Cortex-M3 Temporização Microcontroladores ARM

Publicado em 6-21 16:37