STM32F103 TIM学习笔记

看官方的参考手册,边看边调,做些记录,也供有需要的人参考。

时钟源的选择可以参考这篇文章,写的很清晰

STM定时器时钟源选择函数_stm32 定时器选择时钟源-CSDN博客

1、内部时钟源(CK_INT):时基配置、PWM输出、更新中断

复位后默认是内部时钟源

复制代码
void GPIOInit(void)
{
	GPIO_InitTypeDef GPIO_InitStruct;
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);

	/* GPIOA Configuration: Channel 1, 2 and 3 as alternate function push-pull */
	GPIO_InitStruct.GPIO_Pin = GPIO_Pin_8 ;
	GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF_PP;
	GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOA, &GPIO_InitStruct);



	/* GPIOB Configuration: Channel 1N, 2N and 3N as alternate function push-pull */
	GPIO_InitStruct.GPIO_Pin = GPIO_Pin_13 | GPIO_Pin_14 | GPIO_Pin_15;
	GPIO_Init(GPIOB, &GPIO_InitStruct);


	//输出GPIO方便观察波形
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC,ENABLE);
	GPIO_InitStruct.GPIO_Mode=GPIO_Mode_Out_PP;
	GPIO_InitStruct.GPIO_Pin=GPIO_Pin_13|GPIO_Pin_14;
	GPIO_InitStruct.GPIO_Speed=GPIO_Speed_50MHz;

	GPIO_Init(GPIOC, &GPIO_InitStruct);

}

void TIM1_Init(void)//1毫秒定时
{

	//时基设置
	TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1, ENABLE); 
    /* Time Base configuration */
    TIM_TimeBaseStructure.TIM_Prescaler = 71;
    TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
    TIM_TimeBaseStructure.TIM_Period =999;
    TIM_TimeBaseStructure.TIM_ClockDivision = 0;
    TIM_TimeBaseStructure.TIM_RepetitionCounter = 0;
    TIM_TimeBaseInit(TIM1, &TIM_TimeBaseStructure);


	//输出设置
	TIM_OCInitTypeDef  TIM_OCInitStructure;
	/* Channel 1, 2,3 and 4 Configuration in PWM mode */
	TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;
	TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
	TIM_OCInitStructure.TIM_OutputNState = TIM_OutputNState_Enable;
	TIM_OCInitStructure.TIM_Pulse = 200;
	TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;
	TIM_OCInitStructure.TIM_OCNPolarity = TIM_OCNPolarity_High;
	TIM_OCInitStructure.TIM_OCIdleState = TIM_OCIdleState_Set;
	TIM_OCInitStructure.TIM_OCNIdleState = TIM_OCIdleState_Reset;
	TIM_OC1Init(TIM1, &TIM_OCInitStructure);

	

	//中断设置
	NVIC_InitTypeDef NVIC_InitStructure;
    NVIC_InitStructure.NVIC_IRQChannel = TIM1_UP_IRQn;   
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;   
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;        
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
    NVIC_Init(&NVIC_InitStructure); 

	//使能更新中断
    TIM_ClearFlag(TIM1,TIM_FLAG_Update);
    TIM_ITConfig(TIM1,TIM_IT_Update,ENABLE);

	//使能定时器
    TIM_Cmd(TIM1, ENABLE);
	
	//PWM输出
	TIM_CtrlPWMOutputs(TIM1, ENABLE);

  
}

void TIM1_UP_IRQHandler(void)
{
    if(TIM_GetITStatus(TIM1,TIM_IT_Update)==SET)
    {  
        TIM_ClearFlag(TIM1,TIM_FLAG_Update);
			
		GPIOC->ODR^=GPIO_Pin_13;
    }
}
int main (void)
{
	
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4);
	
	RCC_ClocksTypeDef RCC_Clocks;
	RCC_GetClocksFreq(&RCC_Clocks); //查看RCC时钟配置结果

	GPIOInit();
	TIM1_Init();

	
//	TIM_ETR_Init();


	
	while(1)
	{
		
	}
}

2、外部时钟模式1:外部输入引脚

复制代码
void TIM_TIxExternalClock_Init(void)
{

	//第一步:开启外部时钟和外设时钟(注意使用APB1的开启时钟函数,因为TIM2是APB1总线的外设
		RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1,ENABLE);
		

		RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
		
		GPIO_InitTypeDef GPIO_InitStructure;
		GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
		GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8;
		GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
		GPIO_Init(GPIOA,&GPIO_InitStructure);
	
		TIM_TIxExternalClockConfig(TIM1,TIM_TIxExternalCLK1Source_TI1,TIM_ICPolarity_Rising,0);
	

		
	//第三步:配置时基单元(在stm32f10x_tim.h文件中查找函数)
		TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;
		TIM_TimeBaseInitStructure.TIM_ClockDivision = TIM_CKD_DIV1;//指定时钟分频
		TIM_TimeBaseInitStructure.TIM_CounterMode = TIM_CounterMode_Up;//指定计数器模式(此处选择向上计数)
		TIM_TimeBaseInitStructure.TIM_Period = 10 - 1;//指定要在下一次更新事件时加载到ARR自动重新加载寄存器中的周期值	ARR取值[0,65535]
		TIM_TimeBaseInitStructure.TIM_Prescaler = 1 - 1;//指定用于划分TIM时钟的预分频器值    PSC取值[0,65535]
		TIM_TimeBaseInitStructure.TIM_RepetitionCounter = 0;//指定重复计数器的值(高级定时器才用得上,本项目给0)
		TIM_TimeBaseInit(TIM1,&TIM_TimeBaseInitStructure);//初始化时基单元
		
		TIM_ClearFlag(TIM1,TIM_FLAG_Update);
		
	//第四步:使能更新中断(在stm32f10x_tim.h文件中查找函数)
		TIM_ITConfig(TIM1,TIM_IT_Update,ENABLE);
	//开启了更新中断到NVIC的通路
	//第五步:配置NVIC
		NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//NVIC优先级分组
		NVIC_InitTypeDef NVIC_InitStructure;
		NVIC_InitStructure.NVIC_IRQChannel = TIM1_UP_IRQn;//指定中断通道
		NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
		NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2;//指定IRQ通道的抢占优先级
		NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;//指定IRQ通道的响应优先级
		NVIC_Init(&NVIC_InitStructure);
	//第六步:启动定时器(在stm32f10x_tim.h文件中查找函数)
		TIM_Cmd(TIM1,ENABLE);
		
	//至此定时器就可以开始工作了,当产生更新时,就会触发中断

	 

}

3、外部时钟模式2:外部触发输入ETR

复制代码
void TIM_ETR_Init(void)
{
//第一步:开启外部时钟和外设时钟(注意使用APB1的开启时钟函数,因为TIM2是APB1总线的外设
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1,ENABLE);
    
//需要额外配置GPIO来驱动对射式红外传感器
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
    
    GPIO_InitTypeDef GPIO_InitStructure;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(GPIOA,&GPIO_InitStructure);
    
//第二步:选择时基单元的时钟(在stm32f10x_tim.h文件中查找函数)
    TIM_ETRClockMode2Config(TIM1,TIM_ExtTRGPSC_OFF,TIM_ExtTRGPolarity_Inverted,0x00);
//通过ETR引脚的外部时钟模式2配置
//时基单元就由外部时钟ETR(查表可知引脚PA0)驱动了
    
//第三步:配置时基单元(在stm32f10x_tim.h文件中查找函数)
    TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;
    TIM_TimeBaseInitStructure.TIM_ClockDivision = TIM_CKD_DIV1;//指定时钟分频
    TIM_TimeBaseInitStructure.TIM_CounterMode = TIM_CounterMode_Up;//指定计数器模式(此处选择向上计数)
    TIM_TimeBaseInitStructure.TIM_Period = 10 - 1;//指定要在下一次更新事件时加载到ARR自动重新加载寄存器中的周期值  ARR取值[0,65535]
    TIM_TimeBaseInitStructure.TIM_Prescaler = 1 - 1;//指定用于划分TIM时钟的预分频器值    PSC取值[0,65535]
    TIM_TimeBaseInitStructure.TIM_RepetitionCounter = 0;//指定重复计数器的值(高级定时器才用得上,本项目给0)
    TIM_TimeBaseInit(TIM1,&TIM_TimeBaseInitStructure);//初始化时基单元
    
    TIM_ClearFlag(TIM1,TIM_FLAG_Update);
    
//第四步:使能更新中断(在stm32f10x_tim.h文件中查找函数)
    TIM_ITConfig(TIM1,TIM_IT_Update,ENABLE);
//开启了更新中断到NVIC的通路
//第五步:配置NVIC
    NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//NVIC优先级分组
    NVIC_InitTypeDef NVIC_InitStructure;
    NVIC_InitStructure.NVIC_IRQChannel = TIM1_UP_IRQn;//指定中断通道
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2;//指定IRQ通道的抢占优先级
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;//指定IRQ通道的响应优先级
    NVIC_Init(&NVIC_InitStructure);
//第六步:启动定时器(在stm32f10x_tim.h文件中查找函数)
    TIM_Cmd(TIM1,ENABLE);
    
//至此定时器就可以开始工作了,当产生更新时,就会触发中断
}  
相关推荐
小淮AI10 小时前
从“刷题”到“追问”:AI课堂正在重塑哪些学习旧习惯?
人工智能·学习
码上上岸10 小时前
基于单片机的老人跌倒监测报警器设计与实现
stm32·嵌入式硬件·物联网·智能硬件·硬件
wixzjsh11 小时前
TCP通信与HTTP协议学习笔记:粘包、三次握手、四次挥手与C/S、B/S模型
学习·tcp/ip·http
ZhiMuZhiLing11 小时前
拓客软件学习成本实测方法论:从注册到出第一批名单要多久
学习·流量运营·用户运营
程序员大雄学编程12 小时前
微积分46. 无穷级数四大核心性质:从理论到实践的全方位解析
python·学习·微积分·学习工具
别催小唐敲代码13 小时前
Pixhawk 6C — Mission Planner 烧录 & 全套校准教程
stm32·单片机·嵌入式硬件
LuminousCPP13 小时前
数据结构-二叉树(六):BFS层序遍历与完全二叉树判断|复用链式队列 + (N_0=N_2+1) 性质证明
c语言·数据结构·笔记·算法·二叉树·宽度优先
指针常量14 小时前
【RL系列文章】难样本学习等
学习·大语言模型·rl·后训练
wuyk55514 小时前
从零吃透Modbus通信|第7章:终极工程整合(模块化架构、双模式主机从机、RTOS适配、量产级模板)
c语言·stm32·学习·架构
一条破秋裤15 小时前
STM32 学习笔记:PWM 驱动 LED 呼吸灯与舵机代码
笔记·stm32·学习