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);
    
//至此定时器就可以开始工作了,当产生更新时,就会触发中断
}  
相关推荐
视觉小萌新10 小时前
AI Class 3 · Chapter 1:变量、字符串、list/dict、if/for(python学习-小白版-有经验可跳过)
python·学习·list
Zw-awa13 小时前
从 CPU 搬运到自动搬运:DMA、空闲中断和两块缓冲
stm32
yyyang8813 小时前
蓝牙系统整体架构详解
学习·信息与通信
程序边界13 小时前
一台数据集成软件的拆解笔记(下):一致性、容错、跑批与迁移,KFS 真正难的地方在这
java·前端·笔记
无敌贵点大王13 小时前
从寄存器层面重学STM32(6)——串口USART实战部分
stm32·单片机·嵌入式硬件
庙堂龙吟奈我何13 小时前
二进制和十六进制
stm32·单片机
Linux-lucky13 小时前
46-Linux学习之旅之LVS负载均衡与keepalived高可用
linux·运维·学习·ubuntu·负载均衡·lvs
TST-魚爷15 小时前
小型视频会议室音频踩坑:一体化拾音扩音方案实测分享(易视讯)
stm32·电脑·音视频·钉钉·腾讯会议·zoom会议
金色光环15 小时前
【DSP学习】C2000_ADC中断_笔记
笔记·学习
Дерек的学习记录15 小时前
Unreal Engine 5:第三人称运动系统和人物动画
开发语言·学习·ue5