【联盛德W806上手笔记】五、TIM定时器

Windows 10 20H2
HLK-W806-V1.0-KIT
WM_SDK_W806_v0.6.0


       摘自《W806 芯片设计指导书 V1.0》、《W806 MCU 芯片规格书 V2.0》

定时器

       微秒与毫秒计时(据时钟频率配置计数个数),实现六个可配置的 32 位计数器,当相应计算器配置的计数完成时,产生相应中断。

库函数

函数

       打开wm_tim.h,有如下的函数声明:

HAL_StatusTypeDef HAL_TIM_Base_Init(TIM_HandleTypeDef *htim);
//初始化所用的定时器及其节拍所用时间单位和计数值等基本参数配置
HAL_StatusTypeDef HAL_TIM_Base_DeInit(TIM_HandleTypeDef *htim);
//将初始化之后的定时器恢复成默认的状态–各个寄存器复位时的值
void HAL_TIM_Base_MspInit(TIM_HandleTypeDef *htim);
//初始化定时器时钟、优先级和启用对应中断
void HAL_TIM_Base_MspDeInit(TIM_HandleTypeDef *htim);
//将对应定时器恢复成默认的状态
HAL_StatusTypeDef HAL_TIM_Base_Start(TIM_HandleTypeDef *htim);
//定时器开始计数
HAL_StatusTypeDef HAL_TIM_Base_Stop(TIM_HandleTypeDef *htim);
//定时器停止计数
HAL_StatusTypeDef HAL_TIM_Base_Start_IT(TIM_HandleTypeDef *htim);
//定时器中断方式启动计数
HAL_StatusTypeDef HAL_TIM_Base_Stop_IT(TIM_HandleTypeDef *htim);
//定时器停止中断方式计数
HAL_TIM_StateTypeDef HAL_TIM_Base_GetState(TIM_HandleTypeDef *htim);
//获取定时器状态
void HAL_TIM_IRQHandler(TIM_HandleTypeDef *htim);
//定时器中断服务函数,用来响应定时器中断。函数实体里面有两个功能,一是清除中断标记位,二是调用下面的回调函数。
void HAL_TIM_Callback(TIM_HandleTypeDef *htim);
//中断回调函数,可以理解为中断函数具体要响应的动作。

参数

结构体和枚举类型

typedef enum
{
  HAL_TIM_STATE_RESET             = 0x00U,
  HAL_TIM_STATE_READY             = 0x01U,
  HAL_TIM_STATE_BUSY              = 0x02U,
  HAL_TIM_STATE_TIMEOUT           = 0x03U,
  HAL_TIM_STATE_ERROR             = 0x04U
} HAL_TIM_StateTypeDef;

typedef struct
{
	uint32_t Unit;
	uint32_t AutoReload;
	uint32_t Period;
	
} TIM_Base_InitTypeDef;

typedef struct
{
	uint32_t                        Instance;
	TIM_Base_InitTypeDef            Init;
	
	HAL_LockTypeDef                 Lock;
	__IO HAL_TIM_StateTypeDef       State;
	
} TIM_HandleTypeDef;

宏参数

#define TIM                ((TIM_TypeDef *)TIM_BASE)
#define TIM0				0
#define TIM1				1
#define TIM2				2
#define TIM3				3
#define TIM4				4
#define TIM5				5

#define TIM_UNIT_US				0x00000000U
#define TIM_UNIT_MS				0x00000001U
//定时器节拍的时间单位

#define TIM_AUTORELOAD_PRELOAD_DISABLE                0x00000001U
#define TIM_AUTORELOAD_PRELOAD_ENABLE                 0x00000000U

#define IS_TIM_INSTANCE(INSTANCE)\
		  (((INSTANCE) == TIM0)    || \
		   ((INSTANCE) == TIM1)    || \
		   ((INSTANCE) == TIM2)    || \
		   ((INSTANCE) == TIM3)    || \
		   ((INSTANCE) == TIM4)    || \
		   ((INSTANCE) == TIM5))

#define IS_TIM_UNIT(UNIT) (((UNIT) == TIM_UNIT_US) || \
						   ((UNIT) == TIM_UNIT_MS))

#define IS_TIM_AUTORELOAD(PRELOAD) (((PRELOAD) == TIM_AUTORELOAD_PRELOAD_DISABLE) || \
                                            ((PRELOAD) == TIM_AUTORELOAD_PRELOAD_ENABLE))

#define __HAL_TIM_ENABLE(__HANDLE__)				(TIM->CR |= TIM_CR_TIM_EN((__HANDLE__)->Instance - TIM0))

#define __HAL_TIM_DISABLE(__HANDLE__)				(TIM->CR &= ~(TIM_CR_TIM_EN((__HANDLE__)->Instance - TIM0)))

#define __HAL_TIM_ENABLE_IT(__HANDLE__)				(TIM->CR |= TIM_CR_TIM_TIE((__HANDLE__)->Instance - TIM0))

#define __HAL_TIM_DISABLE_IT(__HANDLE__)			(TIM->CR &= ~(TIM_CR_TIM_TIE((__HANDLE__)->Instance - TIM0)))

#define __HAL_TIM_GET_FLAG(__HANDLE__)          	((TIM->CR & TIM_CR_TIM_TIF((__HANDLE__)->Instance - TIM0)) == \
														TIM_CR_TIM_TIF((__HANDLE__)->Instance - TIM0))

#define __HAL_TIM_CLEAR_IT(__HANDLE__)      		(TIM->CR |= TIM_CR_TIM_TIF((__HANDLE__)->Instance - TIM0))

Demo中的测试程序

main.c


#include <stdio.h>
#include "wm_hal.h"

TIM_HandleTypeDef htim0;
TIM_HandleTypeDef htim1;
TIM_HandleTypeDef htim2;
TIM_HandleTypeDef htim3;
TIM_HandleTypeDef htim4;
TIM_HandleTypeDef htim5;

void Error_Handler(void);
static void TIM0_Init(void);
static void TIM1_Init(void);
static void TIM2_Init(void);
static void TIM3_Init(void);
static void TIM4_Init(void);
static void TIM5_Init(void);

int main(void)
{
	SystemClock_Config(CPU_CLK_160M);
	printf("enter main\r\n");

	TIM0_Init();
	HAL_TIM_Base_Start_IT(&htim0);
	TIM1_Init();
	HAL_TIM_Base_Start_IT(&htim1);
	TIM2_Init();
	HAL_TIM_Base_Start_IT(&htim2);
	TIM3_Init();
	HAL_TIM_Base_Start_IT(&htim3);
	TIM4_Init();
	HAL_TIM_Base_Start_IT(&htim4);
	TIM5_Init();
	HAL_TIM_Base_Start_IT(&htim5);
	
	while(1)
	{
		HAL_Delay(1000);
	}
}

static void TIM0_Init(void)
{
	htim0.Instance = TIM0;
	htim0.Init.Unit = TIM_UNIT_US;
	htim0.Init.Period = 1000000;
	htim0.Init.AutoReload = TIM_AUTORELOAD_PRELOAD_ENABLE;
	if (HAL_TIM_Base_Init(&htim0) != HAL_OK)
	{
		Error_Handler();
	}
}

static void TIM1_Init(void)
{
	htim1.Instance = TIM1;
	htim1.Init.Unit = TIM_UNIT_US;
	htim1.Init.Period = 1001000;
	htim1.Init.AutoReload = TIM_AUTORELOAD_PRELOAD_ENABLE;
	if (HAL_TIM_Base_Init(&htim1) != HAL_OK)
	{
		Error_Handler();
	}
}

static void TIM2_Init(void)
{
	htim2.Instance = TIM2;
	htim2.Init.Unit = TIM_UNIT_US;
	htim2.Init.Period = 1002000;
	htim2.Init.AutoReload = TIM_AUTORELOAD_PRELOAD_ENABLE;
	if (HAL_TIM_Base_Init(&htim2) != HAL_OK)
	{
		Error_Handler();
	}
}

static void TIM3_Init(void)
{
	htim3.Instance = TIM3;
	htim3.Init.Unit = TIM_UNIT_US;
	htim3.Init.Period = 1003000;
	htim3.Init.AutoReload = TIM_AUTORELOAD_PRELOAD_ENABLE;
	if (HAL_TIM_Base_Init(&htim3) != HAL_OK)
	{
		Error_Handler();
	}
}

static void TIM4_Init(void)
{
	htim4.Instance = TIM4;
	htim4.Init.Unit = TIM_UNIT_US;
	htim4.Init.Period = 1004000;
	htim4.Init.AutoReload = TIM_AUTORELOAD_PRELOAD_ENABLE;
	if (HAL_TIM_Base_Init(&htim4) != HAL_OK)
	{
		Error_Handler();
	}
}

static void TIM5_Init(void)
{
	htim5.Instance = TIM5;
	htim5.Init.Unit = TIM_UNIT_US;
	htim5.Init.Period = 1005000;
	htim5.Init.AutoReload = TIM_AUTORELOAD_PRELOAD_ENABLE;
	if (HAL_TIM_Base_Init(&htim5) != HAL_OK)
	{
		Error_Handler();
	}
}

void HAL_TIM_Callback(TIM_HandleTypeDef *htim)
{
	printf("%d ", htim->Instance);
	if (htim->Instance == TIM0)
	{
		
	}
	if (htim->Instance == TIM1)
	{
		
	}
	if (htim->Instance == TIM2)
	{
		
	}
	if (htim->Instance == TIM3)
	{
		
	}
	if (htim->Instance == TIM4)
	{
		
	}
	if (htim->Instance == TIM5)
	{
		
	}
}

void Error_Handler(void)
{
	while (1)
	{
	}
}

void assert_failed(uint8_t *file, uint32_t line)
{
	printf("Wrong parameters value: file %s on line %d\r\n", file, line);
}

wm_hal_msp.c

#include "wm_hal.h"

void HAL_MspInit(void)
{

}

void HAL_TIM_Base_MspInit(TIM_HandleTypeDef* htim_base)
{
	__HAL_RCC_TIM_CLK_ENABLE();
	HAL_NVIC_SetPriority(TIM_IRQn, 0);
	HAL_NVIC_EnableIRQ(TIM_IRQn);
}

void HAL_TIM_Base_MspDeInit(TIM_HandleTypeDef* htim_base)
{
	// 由于所有的TIM共用一个时钟和中断,所以如果只用了一路TIM,在DeInit时可以关闭时钟和中断,但如果使用了多路TIM,在某一路DeInit时,如果
	// 关闭时钟和中断,会影响其他在运行的TIM
//	__HAL_RCC_TIM_CLK_DISABLE();
//	HAL_NVIC_DisableIRQ(TIM_IRQn);
}

wm_it.c


#include "wm_hal.h"

extern TIM_HandleTypeDef htim0;
extern TIM_HandleTypeDef htim1;
extern TIM_HandleTypeDef htim2;
extern TIM_HandleTypeDef htim3;
extern TIM_HandleTypeDef htim4;
extern TIM_HandleTypeDef htim5;

#define readl(addr) ({unsigned int __v = (*(volatile unsigned int *) (addr)); __v;})
__attribute__((isr)) void CORET_IRQHandler(void)
{
	readl(0xE000E010);
	HAL_IncTick();
}

__attribute__((isr)) void TIM0_5_IRQHandler(void)
{
	HAL_TIM_IRQHandler(&htim0);
	HAL_TIM_IRQHandler(&htim1);
	HAL_TIM_IRQHandler(&htim2);
	HAL_TIM_IRQHandler(&htim3);
	HAL_TIM_IRQHandler(&htim4);
	HAL_TIM_IRQHandler(&htim5);
}

实验现象

在这里插入图片描述

版权声明:本文为CSDN博主「乙酸氧铍」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/weixin_44457994/article/details/122605332

Windows 10 20H2
HLK-W806-V1.0-KIT
WM_SDK_W806_v0.6.0


       摘自《W806 芯片设计指导书 V1.0》、《W806 MCU 芯片规格书 V2.0》

定时器

       微秒与毫秒计时(据时钟频率配置计数个数),实现六个可配置的 32 位计数器,当相应计算器配置的计数完成时,产生相应中断。

库函数

函数

       打开wm_tim.h,有如下的函数声明:

HAL_StatusTypeDef HAL_TIM_Base_Init(TIM_HandleTypeDef *htim);
//初始化所用的定时器及其节拍所用时间单位和计数值等基本参数配置
HAL_StatusTypeDef HAL_TIM_Base_DeInit(TIM_HandleTypeDef *htim);
//将初始化之后的定时器恢复成默认的状态–各个寄存器复位时的值
void HAL_TIM_Base_MspInit(TIM_HandleTypeDef *htim);
//初始化定时器时钟、优先级和启用对应中断
void HAL_TIM_Base_MspDeInit(TIM_HandleTypeDef *htim);
//将对应定时器恢复成默认的状态
HAL_StatusTypeDef HAL_TIM_Base_Start(TIM_HandleTypeDef *htim);
//定时器开始计数
HAL_StatusTypeDef HAL_TIM_Base_Stop(TIM_HandleTypeDef *htim);
//定时器停止计数
HAL_StatusTypeDef HAL_TIM_Base_Start_IT(TIM_HandleTypeDef *htim);
//定时器中断方式启动计数
HAL_StatusTypeDef HAL_TIM_Base_Stop_IT(TIM_HandleTypeDef *htim);
//定时器停止中断方式计数
HAL_TIM_StateTypeDef HAL_TIM_Base_GetState(TIM_HandleTypeDef *htim);
//获取定时器状态
void HAL_TIM_IRQHandler(TIM_HandleTypeDef *htim);
//定时器中断服务函数,用来响应定时器中断。函数实体里面有两个功能,一是清除中断标记位,二是调用下面的回调函数。
void HAL_TIM_Callback(TIM_HandleTypeDef *htim);
//中断回调函数,可以理解为中断函数具体要响应的动作。

参数

结构体和枚举类型

typedef enum
{
  HAL_TIM_STATE_RESET             = 0x00U,
  HAL_TIM_STATE_READY             = 0x01U,
  HAL_TIM_STATE_BUSY              = 0x02U,
  HAL_TIM_STATE_TIMEOUT           = 0x03U,
  HAL_TIM_STATE_ERROR             = 0x04U
} HAL_TIM_StateTypeDef;

typedef struct
{
	uint32_t Unit;
	uint32_t AutoReload;
	uint32_t Period;
	
} TIM_Base_InitTypeDef;

typedef struct
{
	uint32_t                        Instance;
	TIM_Base_InitTypeDef            Init;
	
	HAL_LockTypeDef                 Lock;
	__IO HAL_TIM_StateTypeDef       State;
	
} TIM_HandleTypeDef;

宏参数

#define TIM                ((TIM_TypeDef *)TIM_BASE)
#define TIM0				0
#define TIM1				1
#define TIM2				2
#define TIM3				3
#define TIM4				4
#define TIM5				5

#define TIM_UNIT_US				0x00000000U
#define TIM_UNIT_MS				0x00000001U
//定时器节拍的时间单位

#define TIM_AUTORELOAD_PRELOAD_DISABLE                0x00000001U
#define TIM_AUTORELOAD_PRELOAD_ENABLE                 0x00000000U

#define IS_TIM_INSTANCE(INSTANCE)\
		  (((INSTANCE) == TIM0)    || \
		   ((INSTANCE) == TIM1)    || \
		   ((INSTANCE) == TIM2)    || \
		   ((INSTANCE) == TIM3)    || \
		   ((INSTANCE) == TIM4)    || \
		   ((INSTANCE) == TIM5))

#define IS_TIM_UNIT(UNIT) (((UNIT) == TIM_UNIT_US) || \
						   ((UNIT) == TIM_UNIT_MS))

#define IS_TIM_AUTORELOAD(PRELOAD) (((PRELOAD) == TIM_AUTORELOAD_PRELOAD_DISABLE) || \
                                            ((PRELOAD) == TIM_AUTORELOAD_PRELOAD_ENABLE))

#define __HAL_TIM_ENABLE(__HANDLE__)				(TIM->CR |= TIM_CR_TIM_EN((__HANDLE__)->Instance - TIM0))

#define __HAL_TIM_DISABLE(__HANDLE__)				(TIM->CR &= ~(TIM_CR_TIM_EN((__HANDLE__)->Instance - TIM0)))

#define __HAL_TIM_ENABLE_IT(__HANDLE__)				(TIM->CR |= TIM_CR_TIM_TIE((__HANDLE__)->Instance - TIM0))

#define __HAL_TIM_DISABLE_IT(__HANDLE__)			(TIM->CR &= ~(TIM_CR_TIM_TIE((__HANDLE__)->Instance - TIM0)))

#define __HAL_TIM_GET_FLAG(__HANDLE__)          	((TIM->CR & TIM_CR_TIM_TIF((__HANDLE__)->Instance - TIM0)) == \
														TIM_CR_TIM_TIF((__HANDLE__)->Instance - TIM0))

#define __HAL_TIM_CLEAR_IT(__HANDLE__)      		(TIM->CR |= TIM_CR_TIM_TIF((__HANDLE__)->Instance - TIM0))

Demo中的测试程序

main.c


#include <stdio.h>
#include "wm_hal.h"

TIM_HandleTypeDef htim0;
TIM_HandleTypeDef htim1;
TIM_HandleTypeDef htim2;
TIM_HandleTypeDef htim3;
TIM_HandleTypeDef htim4;
TIM_HandleTypeDef htim5;

void Error_Handler(void);
static void TIM0_Init(void);
static void TIM1_Init(void);
static void TIM2_Init(void);
static void TIM3_Init(void);
static void TIM4_Init(void);
static void TIM5_Init(void);

int main(void)
{
	SystemClock_Config(CPU_CLK_160M);
	printf("enter main\r\n");

	TIM0_Init();
	HAL_TIM_Base_Start_IT(&htim0);
	TIM1_Init();
	HAL_TIM_Base_Start_IT(&htim1);
	TIM2_Init();
	HAL_TIM_Base_Start_IT(&htim2);
	TIM3_Init();
	HAL_TIM_Base_Start_IT(&htim3);
	TIM4_Init();
	HAL_TIM_Base_Start_IT(&htim4);
	TIM5_Init();
	HAL_TIM_Base_Start_IT(&htim5);
	
	while(1)
	{
		HAL_Delay(1000);
	}
}

static void TIM0_Init(void)
{
	htim0.Instance = TIM0;
	htim0.Init.Unit = TIM_UNIT_US;
	htim0.Init.Period = 1000000;
	htim0.Init.AutoReload = TIM_AUTORELOAD_PRELOAD_ENABLE;
	if (HAL_TIM_Base_Init(&htim0) != HAL_OK)
	{
		Error_Handler();
	}
}

static void TIM1_Init(void)
{
	htim1.Instance = TIM1;
	htim1.Init.Unit = TIM_UNIT_US;
	htim1.Init.Period = 1001000;
	htim1.Init.AutoReload = TIM_AUTORELOAD_PRELOAD_ENABLE;
	if (HAL_TIM_Base_Init(&htim1) != HAL_OK)
	{
		Error_Handler();
	}
}

static void TIM2_Init(void)
{
	htim2.Instance = TIM2;
	htim2.Init.Unit = TIM_UNIT_US;
	htim2.Init.Period = 1002000;
	htim2.Init.AutoReload = TIM_AUTORELOAD_PRELOAD_ENABLE;
	if (HAL_TIM_Base_Init(&htim2) != HAL_OK)
	{
		Error_Handler();
	}
}

static void TIM3_Init(void)
{
	htim3.Instance = TIM3;
	htim3.Init.Unit = TIM_UNIT_US;
	htim3.Init.Period = 1003000;
	htim3.Init.AutoReload = TIM_AUTORELOAD_PRELOAD_ENABLE;
	if (HAL_TIM_Base_Init(&htim3) != HAL_OK)
	{
		Error_Handler();
	}
}

static void TIM4_Init(void)
{
	htim4.Instance = TIM4;
	htim4.Init.Unit = TIM_UNIT_US;
	htim4.Init.Period = 1004000;
	htim4.Init.AutoReload = TIM_AUTORELOAD_PRELOAD_ENABLE;
	if (HAL_TIM_Base_Init(&htim4) != HAL_OK)
	{
		Error_Handler();
	}
}

static void TIM5_Init(void)
{
	htim5.Instance = TIM5;
	htim5.Init.Unit = TIM_UNIT_US;
	htim5.Init.Period = 1005000;
	htim5.Init.AutoReload = TIM_AUTORELOAD_PRELOAD_ENABLE;
	if (HAL_TIM_Base_Init(&htim5) != HAL_OK)
	{
		Error_Handler();
	}
}

void HAL_TIM_Callback(TIM_HandleTypeDef *htim)
{
	printf("%d ", htim->Instance);
	if (htim->Instance == TIM0)
	{
		
	}
	if (htim->Instance == TIM1)
	{
		
	}
	if (htim->Instance == TIM2)
	{
		
	}
	if (htim->Instance == TIM3)
	{
		
	}
	if (htim->Instance == TIM4)
	{
		
	}
	if (htim->Instance == TIM5)
	{
		
	}
}

void Error_Handler(void)
{
	while (1)
	{
	}
}

void assert_failed(uint8_t *file, uint32_t line)
{
	printf("Wrong parameters value: file %s on line %d\r\n", file, line);
}

wm_hal_msp.c

#include "wm_hal.h"

void HAL_MspInit(void)
{

}

void HAL_TIM_Base_MspInit(TIM_HandleTypeDef* htim_base)
{
	__HAL_RCC_TIM_CLK_ENABLE();
	HAL_NVIC_SetPriority(TIM_IRQn, 0);
	HAL_NVIC_EnableIRQ(TIM_IRQn);
}

void HAL_TIM_Base_MspDeInit(TIM_HandleTypeDef* htim_base)
{
	// 由于所有的TIM共用一个时钟和中断,所以如果只用了一路TIM,在DeInit时可以关闭时钟和中断,但如果使用了多路TIM,在某一路DeInit时,如果
	// 关闭时钟和中断,会影响其他在运行的TIM
//	__HAL_RCC_TIM_CLK_DISABLE();
//	HAL_NVIC_DisableIRQ(TIM_IRQn);
}

wm_it.c


#include "wm_hal.h"

extern TIM_HandleTypeDef htim0;
extern TIM_HandleTypeDef htim1;
extern TIM_HandleTypeDef htim2;
extern TIM_HandleTypeDef htim3;
extern TIM_HandleTypeDef htim4;
extern TIM_HandleTypeDef htim5;

#define readl(addr) ({unsigned int __v = (*(volatile unsigned int *) (addr)); __v;})
__attribute__((isr)) void CORET_IRQHandler(void)
{
	readl(0xE000E010);
	HAL_IncTick();
}

__attribute__((isr)) void TIM0_5_IRQHandler(void)
{
	HAL_TIM_IRQHandler(&htim0);
	HAL_TIM_IRQHandler(&htim1);
	HAL_TIM_IRQHandler(&htim2);
	HAL_TIM_IRQHandler(&htim3);
	HAL_TIM_IRQHandler(&htim4);
	HAL_TIM_IRQHandler(&htim5);
}

实验现象

在这里插入图片描述

版权声明:本文为CSDN博主「乙酸氧铍」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/weixin_44457994/article/details/122605332

生成海报
点赞 0

乙酸氧铍

我还没有学会写个人说明!

暂无评论

发表评论

相关推荐

ESP32S2+ES8388移植过程及问题

电路图如下, 有点小瑕疵ES8388_VMID PIN10/19/20电容没有忘加,查资料应该不影响语言输出,可能噪音大,如果能导致不输出请告诉我一下。 ESP32S2管脚映射 这里主