Temporizadores
Temporizadores
Temporizadores
GERSON PEREZ
TEMPORIZADORES
Un temporizador es un contador de pulsos de reloj, cuyo conteo puede ser reducido con la
utilización de prescalers.
Un prescaler define el número de pulsos de reloj que permiten que el contador del
temporizador se incremente en una unidad. Por ejemplo, un prescaler de 4 incrementa el
contador del temporizador en una unidad cada cuatro pulsos del reloj.
Un temporizador puede ser utilizado como:
➢Como base para medir tiempo (temporizador)
➢Como contador de eventos.
Un temporizador puede ser configurado para trabajar como:
➢Como capturador de señales externas (mide la frecuencia de un evento externo).
➢Como comparador (indica cuando a transcurrido un periodo de tiempo dado), y
➢Para generar modulación por ancho de pulsos (también conocida como PWM)
TEMPORIZADORES
uint32_t CounterMode;
RELACION ENTRE LAS TRES CATEGORIAS DE TIMERS
TIPO DE CONTEO
uint32_t Period;
Ascendente, descendente y
Temporizador Avanzado alineado al centro
uint32_t ClockDivision;
Ascendente, descendente y
Temporizador de propósito general alineado al centro
uint32_t RepetitionCounter;
Temporizador Ascendente
} TIM_Base_InitTypeDef; Básico
TEMPORIZADOR BÁSICO
La estructura de configuración es: Reduce la velocidad del conteo, dividiendo el reloj del
temporizador entre un factor cuyo rango va desde 1 a 65535
typedef struct
{
uint32_t Prescaler; Define la forma de contar del temporizador, puede tomar
cualquiera de los siguientes valores:
uint32_t CounterMode;
La estructura de configuración es: Define el valor máximo del contador del temporizador antes de
que se reinicie el conteo, este puede asumir un valor desde 1
typedef struct hasta 65535
{
uint32_t Prescaler; Indica la relación entre la frecuencia del reloj interno y el reloj de
uint32_t CounterMode; muestreo utilizado por los filtros digitales Rx y Tx. Estas
relaciones de campo pueden ser:
uint32_t Period;
TIM_CLOCKDIVISION_DIV1
uint32_t ClockDivision; Realiza una muestra de la señal de entrada en los pines
uint32_t RepetitionCounter; ETRx y TIx
TIM_CLOCKDIVISION_DIV2
} TIM_Base_InitTypeDef; Realiza 2 muestras de la señal de entrada en los pines
ETRx y TIx
TIM_CLOCKDIVISION_DIV4
Realiza 4 muestras de la señal de entrada en los pines
ETRx y TIx
TEMPORIZADOR BÁSICO
La estructura de configuración es: Sirve para darle seguimiento a las veces que el temporizador se
desborda ya sea de manera ascendente o descendente.
typedef struct
{
uint32_t Prescaler;
uint32_t CounterMode;
uint32_t Period;
uint32_t ClockDivision;
uint32_t RepetitionCounter;
} TIM_Base_InitTypeDef;
TEMPORIZADOR BÁSICO
Los valores numéricos de los campos Prescaler y
Period determinan la frecuencia del temporizador,
es decir, el tiempo que tardara en desbordarse.
Estos valores se pueden definir de las siguientes
formulas: 𝐹𝐶
𝐹𝑇 =
𝑃𝑟𝑒𝑠𝑐𝑎𝑙𝑒𝑟 + 1
𝑃𝑒𝑟𝑖𝑜𝑑 + 1
𝑇=
𝐹𝑇
𝐹𝐶
Actualización del Evento= 𝑃𝑟𝑒𝑠𝑐𝑎𝑙𝑒𝑟+1 𝑃𝑒𝑟𝑖𝑜𝑑+1
La interrupción debe ser inicializada por el usuario. Por tanto, luego de generar el código
con CubeMX, es debe agregar la función:
HAL_TIM_Base_Start_IT(&htimX);
𝐹𝐶 𝑃𝑒𝑟𝑖𝑜𝑑 + 1 𝐹𝐶
𝐹𝑇 = 𝑇= 𝐹𝑟𝑒𝑐𝑢𝑒𝑛𝑐𝑖𝑎 =
𝑃𝑟𝑒𝑠𝑐𝑎𝑙𝑒𝑟 + 1 𝐹𝑇 𝑃𝑟𝑒𝑠𝑐𝑎𝑙𝑒𝑟 + 1 𝑃𝑒𝑟𝑖𝑜𝑑 + 1
Por tanto:
𝑃𝑒𝑟𝑖𝑜𝑑 + 1 8000000
0,5 = 𝐹𝑇 = = 1000
1000 𝑃𝑟𝑒𝑠𝑐𝑎𝑙𝑒𝑟 + 1
SW4STM2
TEMPORIZADOR BÁSICO EJEMPLO 1
#include "main.h" static void MX_TIM3_Init(void)
#include "stm32f1xx_hal.h" {
TIM_ClockConfigTypeDef sClockSourceConfig;
TIM_HandleTypeDef htim3; TIM_MasterConfigTypeDef sMasterConfig;
htim3.Instance = TIM3;
void SystemClock_Config(void); htim3.Init.Prescaler = 7999;
static void MX_GPIO_Init(void); htim3.Init.CounterMode = TIM_COUNTERMODE_UP;
static void MX_TIM3_Init(void); htim3.Init.Period = 499;
htim3.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
htim3.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;
int main(void) if (HAL_TIM_Base_Init(&htim3) != HAL_OK)
{ {
_Error_Handler(__FILE__, __LINE__);
HAL_Init(); }
SystemClock_Config(); sClockSourceConfig.ClockSource = TIM_CLOCKSOURCE_INTERNAL;
MX_GPIO_Init(); if (HAL_TIM_ConfigClockSource(&htim3, &sClockSourceConfig) != HAL_OK)
MX_TIM3_Init(); {
HAL_TIM_Base_Start_IT(&htim3); _Error_Handler(__FILE__, __LINE__);
}
while (1) sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET;
{ sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
if (HAL_TIMEx_MasterConfigSynchronization(&htim3, &sMasterConfig) != HAL_OK)
} {
_Error_Handler(__FILE__, __LINE__);
} }
}
TEMPORIZADOR BÁSICO EJEMPLO 1
}
TEMPORIZADOR BÁSICO EJEMPLO 2
Funciones adicionales
● Para detener el timer:
HAL_TIM_Base_Stop_IT(&htimx)
● Cambiar prescaler:
__HAL_TIM_SET_PRESCALER(&htimx, val_prescaler)
● Cambiar periodo:
__HAL_TIM_SET_AUTORELOAD(&htimx, val_periodo)
Cambiar el contador del timer:
● __HAL_TIM_SET_COUNTER(&htimx, val_contador)
TEMPORIZADOR CON FUENTE EXTERNA
Un temporizador puede recibir estímulos de una fuente externa a uno de los pines asociados
con los TIMERS.
La estructura de configuración es: Indica la fuente de la señal del reloj usada para alimentar el
typedef struct temporizador, y puede asumir cualquiera de los siguientes
{ valores:
uint32_t ClockSource;
uint32_t ClockPolarity; TIM_CLOCKSOURCE_INTERNAL
uint32_t ClockPrescaler; El temporizador esta polarizado con el reloj del bus APBx
uint32_t ClockFilter; TIM_CLOCKSOURCE_ETRMODE1
} TIM_ClockConfigTypeDef; Configurado como modo1 de reloj externo, el temporizador esta
polarizado por una señal interna o externa conectada a los pines
ITR0, ITR1, ITR2, ITR3, TI1FP1 o TI2FP2
TIM_CLOCKSOURCE_ETRMODE2
Configurado como modo 2 de reloj externo, y esta polarizado por
una fuente externa que se encuentra conectado al pin ETR
TEMPORIZADOR CON FUENTE EXTERNA
Un temporizador puede recibir estímulos de una fuente externa a uno de los pines asociados
con los TIMERS.
La estructura de configuración es: Indica la polaridad de la señal del reloj usada para alimentar el
typedef struct temporizador, puede asignarse cualquiera de los siguientes
{ valores:
uint32_t ClockSource;
uint32_t ClockPolarity; TIM_CLOCKPOLARITY_INVERTED
uint32_t ClockPrescaler; Polarity for ETRx clock sources
uint32_t ClockFilter; TIM_CLOCKPOLARITY_NONINVERTED
} TIM_ClockConfigTypeDef; Polarity for ETRx clock sources
TIM_CLOCKPOLARITY_RISING
Polarity for TIx clock sources
TIM_CLOCKPOLARITY_FALLING
Polarity for TIx clock sources
TIM_CLOCKPOLARITY_BOTHEDGE
Polarity for TIx clock sources
TEMPORIZADOR CON FUENTE EXTERNA
Un temporizador puede recibir estímulos de una fuente externa a uno de los pines asociados
con los TIMERS.
La estructura de configuración es: Especifica el prescaler de la fuente externa del reloj, puede
typedef struct asignarse cualquiera de los siguientes valores:
{
uint32_t ClockSource;
uint32_t ClockPolarity; TIM_CLOCKPRESCALER_DIV1 No prescaler is used
uint32_t ClockPrescaler; TIM_CLOCKPRESCALER_DIV2 Prescaler for External ETR
uint32_t ClockFilter; Clock: Capture performed once every 2 events.
} TIM_ClockConfigTypeDef; TIM_CLOCKPRESCALER_DIV4 Prescaler for External ETR
Clock: Capture performed once every 4 events.
TIM_CLOCKPRESCALER_DIV8 Prescaler for External ETR
Clock: Capture performed once every 8 events.
TEMPORIZADOR CON FUENTE EXTERNA
Un temporizador puede recibir estímulos de una fuente externa a uno de los pines asociados
con los TIMERS.
La estructura de configuración es: Este campo de 4 bits de valor numérico, define la frecuencia
typedef struct usada para el muestreo de la señal del reloj externo y el ancho
{ del filtro digital aplicada a este:
uint32_t ClockSource;
uint32_t ClockPolarity;
uint32_t ClockPrescaler;
uint32_t ClockFilter;
} TIM_ClockConfigTypeDef;
TEMPORIZADOR CON FUENTE EXTERNA
𝐹𝐶 𝑃𝑒𝑟𝑖𝑜𝑑 + 1 𝐹𝐶
𝐹𝑇 = 𝑇= 𝐹𝑟𝑒𝑐𝑢𝑒𝑛𝑐𝑖𝑎 =
𝑃𝑟𝑒𝑠𝑐𝑎𝑙𝑒𝑟 + 1 𝐹𝑇 𝑃𝑟𝑒𝑠𝑐𝑎𝑙𝑒𝑟 + 1 𝑃𝑒𝑟𝑖𝑜𝑑 + 1
Por tanto:
𝑃𝑒𝑟𝑖𝑜𝑑 + 1 8000000
0,5 = 𝐹𝑇 = = 1000
1000 𝑃𝑟𝑒𝑠𝑐𝑎𝑙𝑒𝑟 + 1
TIM_ClockConfigTypeDef sClockSourceConfig;
TIM_MasterConfigTypeDef sMasterConfig;
htim2.Instance = TIM2;
htim2.Init.Prescaler = 7999;
htim2.Init.CounterMode = TIM_COUNTERMODE_UP;
htim2.Init.Period = 499;
htim2.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
htim2.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;
sClockSourceConfig.ClockSource = TIM_CLOCKSOURCE_ETRMODE2;
sClockSourceConfig.ClockPolarity = TIM_CLOCKPOLARITY_NONINVERTED;
sClockSourceConfig.ClockPrescaler = TIM_CLOCKPRESCALER_DIV1;
sClockSourceConfig.ClockFilter = 0;
sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET;
sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
}
TEMPORIZADOR CON FUENTE EXTERNA - EJEMPLO 3
static void MX_GPIO_Init(void)
{ void TIM2_IRQHandler(void)
GPIO_InitTypeDef GPIO_InitStruct; {
HAL_TIM_IRQHandler(&htim2);
/* GPIO Ports Clock Enable */ }
__HAL_RCC_GPIOC_CLK_ENABLE();
__HAL_RCC_GPIOA_CLK_ENABLE(); void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
/*Configure GPIO pin Output Level */ if(htim->Instance==TIM2)
HAL_GPIO_WritePin(GPIOC, GPIO_PIN_13, GPIO_PIN_RESET); {
HAL_GPIO_TogglePin(GPIOC, GPIO_PIN_13);
/*Configure GPIO pin : PC13 */ }
GPIO_InitStruct.Pin = GPIO_PIN_13; }
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);
Se realizaran todos los cálculos tomando en cuenta que la frecuencia del reloj
principal será de 8MHz (HSE).
TEMPORIZADOR COMO MODULADOR POR ANCHO DE PULSO
CICLO DE
TRABAJO
PERIODO: Es fijo
CICLO DE TRABAJO: Es variable
PERIODO
La cantidad de pasos que le
tomará al PWM llegar al
100% de su ciclo de trabajo
𝐹𝐶 𝑃𝑒𝑟𝑖𝑜𝑑 + 1
𝐹𝑇 = 𝑇=
𝑃𝑟𝑒𝑠𝑐𝑎𝑙𝑒𝑟 + 1 𝐹𝑇
𝐹𝐶 𝑃𝑒𝑟𝑖𝑜𝑑 + 1
𝐹𝑇 = 𝑇=
𝑃𝑟𝑒𝑠𝑐𝑎𝑙𝑒𝑟 + 1 𝐹𝑇
Por tanto:
𝑃𝑒𝑟𝑖𝑜𝑑 + 1 8000000
0,001 = Son 999 los de pasos que le 𝐹𝑇 = = 1000000
1000000 𝑃𝑟𝑒𝑠𝑐𝑎𝑙𝑒𝑟 + 1
tomará al PWM llegar al
𝑃𝑒𝑟𝑖𝑜𝑑 = 999 100% de su ciclo de trabajo 𝑃𝑟𝑒𝑠𝑐𝑎𝑙𝑒𝑟 = 7
TEMPORIZADOR COMO MODULADOR POR ANCHO DE PULSO
Creamos un nuevo proyecto dentro de STM32CubeMX accionando sobre el icono correspondiente y seleccionando
nuestro Microcontrolador STM32F103C8T6
TIM_HandleTypeDef htim1;
void SystemClock_Config(void);
static void MX_GPIO_Init(void);
static void MX_TIM1_Init(void);
void HAL_TIM_MspPostInit(TIM_HandleTypeDef *htim);
void user_pwm_setvalue(uint16_t);
uint8_t valor_pwm=0;
uint8_t paso=0;
int main(void) Antes de poder controlar nuestro PWM debemos de
{ inicializarlo con la función Hal_TIM_PWM_Start(); la cual
HAL_Init();
SystemClock_Config();
requiere dos parámetros. El primer parámetro es el Timer
a usar y el segundo es el canal del Timer que controlará el
MX_GPIO_Init(); GPIO.
MX_TIM1_Init();
HAL_TIM_PWM_Start(&htim1, TIM_CHANNEL_1);
TEMPORIZADOR COMO MODULADOR POR ANCHO DE PULSO
while (1)
static void MX_GPIO_Init(void)
{
{
HAL_Delay(100);
__HAL_RCC_GPIOD_CLK_ENABLE();
if(valor_pwm == 0) paso = 50;
__HAL_RCC_GPIOA_CLK_ENABLE();
if(valor_pwm == 1000) paso = -50;
valor_pwm += paso;
}
pwm_por_usuario(valor_pwm);
}
} // fin del main(void)
TIM_HandleTypeDef htim1;
void SystemClock_Config(void);
static void MX_GPIO_Init(void);
static void MX_TIM1_Init(void);
void HAL_TIM_MspPostInit(TIM_HandleTypeDef *htim);
int main(void)
{
HAL_Init();
SystemClock_Config(); Antes de poder controlar nuestro PWM debemos de
inicializarlo con la función Hal_TIM_PWM_Start(); la cual
MX_GPIO_Init();
MX_TIM1_Init();
requiere dos parámetros. El primer parámetro es el Timer
a usar y el segundo es el canal del Timer que controlará el
HAL_TIM_PWM_Start(&htim1, TIM_CHANNEL_1); GPIO.
TEMPORIZADOR COMO MODULADOR POR ANCHO DE PULSO
while (1)
{ static void MX_GPIO_Init(void)
for (int pwm=0;pwm<=999;pwm++) // {
{ __HAL_RCC_GPIOD_CLK_ENABLE();
__HAL_TIM_SET_COMPARE(&htim1, TIM_CHANNEL_1, pwm); // __HAL_RCC_GPIOA_CLK_ENABLE();
HAL_Delay(10);
} }
HAL_Delay(200); //
for (int pwm=999;pwm>=0;pwm--) //
{
__HAL_TIM_SET_COMPARE(&htim1, TIM_CHANNEL_1, pwm);
HAL_Delay(10);
}
La función que se encarga de controlar el GPIO mapeado por el
HAL_Delay(200); //
} Microcontrolador es __Hal_TIM_SET_COMPARE(); Esta función
} // fin del main(void) recibe tres parámetros: el Timer a usar, el canal y el número de pasos.
Este último valor es el valor de Pulse del Timer1, por consiguiente
únicamente podemos colocar valores entre 0 y 999, es decir, el 100%
de nuestro ciclo de trabajo es 999. Si deseamos que el ciclo de trabajo
se encuentre a la mitad (50%) debemos de colocar 499,5 como tercer
parámetro, redondeándolo da 500.
TEMPORIZADOR COMO MODULADOR POR ANCHO DE PULSO
sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET;
static void MX_TIM1_Init(void) sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
{ if (HAL_TIMEx_MasterConfigSynchronization(&htim1, &sMasterConfig) != HAL_OK)
TIM_ClockConfigTypeDef sClockSourceConfig; {
TIM_MasterConfigTypeDef sMasterConfig; _Error_Handler(__FILE__, __LINE__);
TIM_OC_InitTypeDef sConfigOC; }
TIM_BreakDeadTimeConfigTypeDef sBreakDeadTimeConfig; sConfigOC.OCMode = TIM_OCMODE_PWM1;
sConfigOC.Pulse = 0;
htim1.Instance = TIM1; sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH;
htim1.Init.Prescaler = 7; sConfigOC.OCNPolarity = TIM_OCNPOLARITY_HIGH;
htim1.Init.CounterMode = TIM_COUNTERMODE_UP; sConfigOC.OCFastMode = TIM_OCFAST_DISABLE;
htim1.Init.Period = 999; sConfigOC.OCIdleState = TIM_OCIDLESTATE_RESET;
htim1.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1; sConfigOC.OCNIdleState = TIM_OCNIDLESTATE_RESET;
htim1.Init.RepetitionCounter = 0; if (HAL_TIM_PWM_ConfigChannel(&htim1, &sConfigOC, TIM_CHANNEL_1) != HAL_OK)
htim1.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE; {
if (HAL_TIM_Base_Init(&htim1) != HAL_OK) _Error_Handler(__FILE__, __LINE__);
{ }
_Error_Handler(__FILE__, __LINE__); sBreakDeadTimeConfig.OffStateRunMode = TIM_OSSR_DISABLE;
} sBreakDeadTimeConfig.OffStateIDLEMode = TIM_OSSI_DISABLE;
sClockSourceConfig.ClockSource = TIM_CLOCKSOURCE_INTERNAL; sBreakDeadTimeConfig.LockLevel = TIM_LOCKLEVEL_OFF;
if (HAL_TIM_ConfigClockSource(&htim1, &sClockSourceConfig) != HAL_OK) sBreakDeadTimeConfig.DeadTime = 0;
{ sBreakDeadTimeConfig.BreakState = TIM_BREAK_DISABLE;
_Error_Handler(__FILE__, __LINE__); sBreakDeadTimeConfig.BreakPolarity = TIM_BREAKPOLARITY_HIGH;
} sBreakDeadTimeConfig.AutomaticOutput = TIM_AUTOMATICOUTPUT_DISABLE;
if (HAL_TIM_PWM_Init(&htim1) != HAL_OK) if (HAL_TIMEx_ConfigBreakDeadTime(&htim1, &sBreakDeadTimeConfig) != HAL_OK)
{ {
_Error_Handler(__FILE__, __LINE__); _Error_Handler(__FILE__, __LINE__);
} }
HAL_TIM_MspPostInit(&htim1);
}
TEMPORIZADOR COMO MODULADOR POR ANCHO DE PULSO
Diseñar un programa que genere una señal PWM con un periodo de 1ms, con un ciclo de trabajo que varié cuando se
presiona un pulsador. Inicialmente el ciclo de trabajo debe ser del 30%. Si se presiona el pulsador el ciclo de trabajo
cambiará al 70%. Si se vuelve a presionar el pulsador el ciclo de trabajo regresará a ser de 30%.
TEMPORIZADOR COMO MODULADOR POR ANCHO DE PULSO
TEMPORIZADOR COMO MODULADOR POR ANCHO DE PULSO
TEMPORIZADOR COMO MODULADOR POR ANCHO DE PULSO
TEMPORIZADOR COMO MODULADOR POR ANCHO DE PULSO