STM32复习笔记(十五) —— 高级定时器(定时)

STM32复习笔记(十五) —— 高级定时器(定时)

1.功能框图 (STM32F10xxx参考手册 图50 高级控制定时器框图)
STM32复习笔记(十五) —— 高级定时器(定时)_第1张图片
STM32复习笔记(十五) —— 高级定时器(定时)_第2张图片
SSS15.003
时基单元包括:

1)计数器寄存器 TIMx_CNT
2)预分频器寄存器 TIMx_PSC
3)自动装载寄存器 TIMx_ARR
4)重复次数寄存器 TIMx_RCR

预分频器,实际为16位寄存器 (带有缓冲器) 控制的16位计数器,用于分频计数器时钟,其16位寄存器 and 计数器取值范围 0 - 65535,计数器从 0 开始计数,与寄存器值比较分频,因此可以对计数器时钟频率进行1 - 65536 分频,寄存器缓冲器使其可以运行时被改变

重复计数器,当发生计数器上溢 or 下溢时,重复计数器值递减一次,直至为 0 产生一次计数器上溢 or 下溢更新事件 (UEV),当更新事件由软件产生 (UG 位) or 从模式控制器产生时,立即发生更新事件,发生更新事件时,重复计数器值 and 自动装载寄存器值 and 预分频器值均自动重载

计数器模式:

1)向上计数 0 -> ARR -> 0 . . .
2)向下计数 ARR -> 0 -> ARR . . .
3)向上/向下计数 (中央对齐模式) 0 -> (ARR - 1) -> ARR -> 1 -> 0 . . .

时钟选择:

1)内部时钟 CK_INT
2)外部时钟1,外部输入引脚
3)外部时钟2,外部触发输入 ETR
4)内部触发输入 ITRx,使用一个定时器作为另一个定时器的预分频器

2.本例程软件设计思路

1)使用定时器1产生500ms 定时
2)使用 PA0 作为 LED,定时时间到则翻转 LED 电平

3.代码编写

于 main.c 中编写代码

#include "stm32f10x.h"
#include "dr_usart.h"

void LED_GPIO_Config(void)
{
	/* 开启 GPIOA 时钟 */
	RCC->APB2ENR |= ((uint16_t)0x01 << 2);
	
	/* 配置 PA0 用于 LED, 推挽输出, 10MHz */
	GPIOA->CRL &= ~((uint32_t)0x0F << 0);
	GPIOA->CRL |=  ((uint32_t)0x01 << 0);
	
	/* 初始化引脚为低电平 */
	GPIOA->BRR |= ((uint16_t)0x01 << 0);
}

void TIM1_NVIC_Config(void)
{
    /* 配置 TIM1 优先级 15 */
	NVIC->IP[25] = ((uint8_t)15 << 4);
	
	/* 使能 TIM1 更新中断 */
	NVIC->ISER[0]|= ((uint32_t)0x01 << 25);
}

void TIM1_Config(void)
{
	/* 开启 TIM1 时钟, 挂载于 APB2 总线 */
	RCC->APB2ENR |= ((uint32_t)0x01 << 11);
	
	/**
	  * 定时时间计算:
	  *
	  * 1. 计数器时钟 (72MHz/(PSC+1)):        时钟源(72MHz) -> PSC 分频
	  *
	  * 2. 定时时间 ((1/(72MHz/(PSC+1)))*ARR):(1/计数器时钟) * 自动重载值
	  *
	  * 16位预分频器 PSC 值取值范围:          0 - 65535 (+1, PSC+1)
	  *
	  * 16位自动重载寄存器 ARR 取值范围:      0 - 65535 (>=1, 为0计数器停止)
	  *
	  * 综上:
	  *
	  * 定时时间计算:((PSC + 1) * ARR) / (72 * 1000000) * 自定义系数
	  *
	  * 如定时 500 ms, 取自定义系数为 10, PSC 值为 71, ARR 值为 50000
	  */
	
	/* 向上计数 */
	TIM1->CR1 &= ~((uint16_t)0x07 << 4);
	
	/* 时钟分频因子 */
	TIM1->CR1 &= ~((uint16_t)0x03 << 8);
	
	/* 重装载值 */
	TIM1->ARR = ((uint16_t)50000);
	
	/* 预分频器值 */
	TIM1->PSC = ((uint16_t)71);
	
	/* 重复计数器值 */
	TIM1->RCR = ((uint16_t)0);
	
	/* 开启中断 */
	TIM1->DIER |= ((uint16_t)0x01 << 0);
	
	/* 配置 TIM1 更新中断 */
	TIM1_NVIC_Config();
	
	/* 开始计数 */
	TIM1->CR1 |= ((uint32_t)0x01 << 0);
}

int main(void)
{
	/* --------- (81 = 30 + 51) --------- --------- --------- --------- ------ */
	
	User_Init(); /* 中断优先级分组 (16级抢占优先级) and 配置串口1打印调试信息 */
	
	delay_(1);   /* 粗略延时 (约为ms级), 置于此处, 便于使用时复制调用 */
	
	/* --------- 换行基准 --------- --------- --------- --------- --------- -- */
	
	/* 配置 GPIOA GPIO_Pin_0 */
	LED_GPIO_Config();
	
	/* 配置 TIM1 */
	TIM1_Config();
	
	while(1);
}

void TIM1_UP_IRQHandler(void)
{
	static uint16_t Time_Count = 0;
	
	/* 判断是否产生更新中断 */
	if(0 != (TIM1->SR & ((uint16_t)0x01)))
	{
		/* 50ms 进一次中断, 10*50ms = 500ms */
		if(++Time_Count >= 10)
		{
			Time_Count = 0;
			
			/* 每 500ms 翻转一次电平 */
			GPIOA->ODR ^= ((uint32_t)0x01 << 0);
		}
		
		/* 清除中断标志 */
		TIM1->SR &= ~((uint16_t)0x01 << 0);
	}
}

点击编译,如无错误可进入仿真界面
SSS15.004
打开逻辑分析仪
STM32复习笔记(十五) —— 高级定时器(定时)_第3张图片
添加 PA0
STM32复习笔记(十五) —— 高级定时器(定时)_第4张图片
点击运行
STM32复习笔记(十五) —— 高级定时器(定时)_第5张图片
可以看出,LED 电平每隔一段时间翻转一次 (此处仿真时间与预想结果有差异,或未得仿真软件正确配置方法,但理论上硬件运行结果应正确)

你可能感兴趣的:(stm32)