STM32常用函数:中断定时器操作指南

学习江协科技stm32基于库函数开发记录一下
代码压缩包地址:code

函数

  • 8.对射式红外传感器(中断)
  • 中断流程
  • RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE);//开启afio时钟
  • GPIO_EXTILineConfig(GPIO_PortSourceGPIOB, GPIO_PinSource14);//将外部中断的14号线映射到GPIOB
  • EXTI_Init(&EXTI_InitStruct);//中断初始化
  • NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//配置nvic分组
  • NVIC_Init(&NVIC_InitStruct);//nvic初始化
  • EXTI_GetITStatus(EXTI_Line14)//获取标志位
  • EXTI_ClearITPendingBit(EXTI_Line14)//清除标志位
  • EXTI15_10_IRQHandler(void)//中断服务函数(启动文件)
  • CountSensor.h
  • CountSensor.c
  • main.c
  • 9.旋转编码器(中断)
  • Encoder.h
  • Encoder.c
  • 10.定时器内部时钟
  • 定时器初始化流程
  • RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);//开启tim2时钟位于apb1总线
  • TIM_InternalClockConfig(TIM2);//选择时钟(内部时钟tim2)
  • TIM_TimeBaseInit();//配置时基单元
  • TIM_ITConfig();//中断输出配置
  • TIM_Cmd()//定时器使能
  • Timer.h
  • Timer.c
  • main.c
  • 11.定时器外部时钟
  • 定时器流程
  • TIM_ETRClockMode2Config();//配置外部时钟模式2
  • TIM_GetCounter(TIM2);//返回tim2的cnt值
  • Timer.h
  • Timer.c
  • main.c
  • 12.PWM控制LED
  • 输出比较流程
  • TIM_InternalClockConfig(TIM2); //内部时钟源选择
  • TIM_TimeBaseInit();//时基单元初始化
  • TIM_OC1Init();//输出比较初始化
  • TIM_OCStructInit();//结构体赋值
  • TIM_Cmd();//定时器使能
  • TIM_SetCompare1();//设置ccr1的值
  • pwm.h
  • pwm.c
  • main.c
  • 13.PWM控制舵机
  • Servo.h
  • Servo.c
  • main.c
  • 14.pwm驱动直流电机
  • Motor.h
  • Motor.c
  • main.c
  • 15.定时器输入捕获
  • TIM_ICInit(TIM3,&TIM_ICInitStruct);//输入捕获初始化
  • TIM_SelectInputTrigger(TIM3,TIM_TS_TI1FP1);//触发源选择~TI1FP1
  • TIM_SelectSlaveMode(TIM3,TIM_SlaveMode_Reset);//从模式选择
  • 输入捕获流程
  • ic.h
  • ic.c
  • main.c
  • 16.输入捕获~频率与占空比
  • TIM_PWMIConfig();//传入通道及结构体变量将自动配置另一个通道
  • ic.h
  • ic.c
  • main.c
  • 17.编码器测速
  • TIM_EncoderInterfaceConfig();//配置编码器以及两个通道是否反相
  • EncoderTwo.h
  • EncoderTwo.c
  • main.c
  • 8.对射式红外传感器(中断)

    中断流程

    中断初始化
    1.开启时钟
    2.GPIO初始化
    3.AFIO选择引脚
    4.EXTI初始化
    5.NVIC分组
    6.NVIC配置   
    

    RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE);//开启afio时钟

    GPIO_EXTILineConfig(GPIO_PortSourceGPIOB, GPIO_PinSource14);//将外部中断的14号线映射到GPIOB

    EXTI_Init(&EXTI_InitStruct);//中断初始化

    NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//配置nvic分组

    NVIC_Init(&NVIC_InitStruct);//nvic初始化

    EXTI_GetITStatus(EXTI_Line14)//获取标志位

    EXTI_ClearITPendingBit(EXTI_Line14)//清除标志位

    EXTI15_10_IRQHandler(void)//中断服务函数(启动文件)

    CountSensor.h

    #ifndef __COUNTSENSOR_H
    #define __COUNTSENSOR_H
    
    void CountSeneor_Init(void);//中断初始化
    uint16_t CountSensor_Get(void);//次数获取
    #endif
    

    CountSensor.c

    #include "stm32f10x.h"                  // Device header
    uint16_t CountSensor_Count;
    /*
    	中断初始化
    	1.开启时钟
    	2.GPIO初始化
    	3.AFIO选择引脚
    	4.EXTI初始化
    	5.NVIC分组
    	6.NVIC配置
    */
    void CountSeneor_Init(void)
    {
    	//开启时钟
    	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);//开启gpiob时钟
    	RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE);//开启afio时钟,外部中断必须开启afio时钟
    	//GPIO初始化
    	GPIO_InitTypeDef GPIO_InitStruct;
    	GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IPU;
    	GPIO_InitStruct.GPIO_Pin = GPIO_Pin_14;
    	GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
    	GPIO_Init(GPIOB,&GPIO_InitStruct);//将PB14脚初始化为上拉输入  
    	
    	GPIO_EXTILineConfig(GPIO_PortSourceGPIOB, GPIO_PinSource14);//选择用作EXTI线的GPIO引脚
    	//中断线选择,将外部中断的14号线映射到GPIOB,即选择PB14为外部中断引脚
    	
    	EXTI_InitTypeDef EXTI_InitStruct;
    	EXTI_InitStruct.EXTI_Line = EXTI_Line14;//配置外部中断线
    	EXTI_InitStruct.EXTI_LineCmd = ENABLE;//外部中断线使能
    	EXTI_InitStruct.EXTI_Mode = EXTI_Mode_Interrupt;//指定外部中断线为中断模式
    	EXTI_InitStruct.EXTI_Trigger = EXTI_Trigger_Rising;//外部中断线上升沿触发
    	EXTI_Init(&EXTI_InitStruct);
    	
    	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//配置nvic分组,目前为分组2,抢占优先级与响应优先级均为0~3
    	
    	//nvic配置	
    	NVIC_InitTypeDef NVIC_InitStruct;//结构体定义
    	NVIC_InitStruct.NVIC_IRQChannel = EXTI15_10_IRQn;//选择配置nvic的EXTI15_10
    	NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE;//使能
    	NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = 1;//抢占优先级
    	NVIC_InitStruct.NVIC_IRQChannelSubPriority = 1;//响应优先级
    	NVIC_Init(&NVIC_InitStruct);
    }
    void EXTI15_10_IRQHandler(void)//服务中断函数
    {
    	if(EXTI_GetITStatus(EXTI_Line14)== SET)
    	{
    		if(GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_14) == 0)
    		{
    			CountSensor_Count ++;
    		}
    		EXTI_ClearITPendingBit(EXTI_Line14);//结束清除标志位
    	}
    }
    
    uint16_t CountSensor_Get(void)
    {
    	return CountSensor_Count;
    }
    

    main.c

    #include "stm32f10x.h"                  // Device header
    #include "Delay.h"
    #include "oled.h"
    #include "countsensor.h"
    
    int main()
    {
    	OLED_Init();//oled初始化
    	CountSeneor_Init();
    	OLED_ShowString(1,1,"count:");//第一行第一列展示字符串count:
    	while(1)
    	{
    		OLED_ShowNum(1,7,CountSensor_Get(),5);
    	}
    }
    

    9.旋转编码器(中断)

    Encoder.h

    #ifndef __ENCODER_H
    #define __ENCODER_H
    
    void Encoder_Init(void);
    int16_t Encoder_Get(void);
    #endif
    

    Encoder.c

    #include "stm32f10x.h"                  // Device header
    uint16_t Encoder_Count;
    /*
    	中断初始化
    	1.开启时钟
    	2.GPIO初始化
    	3.AFIO选择引脚
    	4.EXTI初始化
    	5.NVIC分组
    	6.NVIC配置
    */
    void Encoder_Init(void)
    {
    	//开启时钟
    	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);//开启gpiob时钟
    	RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE);//开启afio时钟,外部中断必须开启afio时钟
    	//GPIO初始化
    	GPIO_InitTypeDef GPIO_InitStruct;
    	GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IPU;
    	GPIO_InitStruct.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_0;
    	GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
    	GPIO_Init(GPIOB,&GPIO_InitStruct);//将PB14脚初始化为上拉输入  
    	
    	GPIO_EXTILineConfig(GPIO_PortSourceGPIOB, GPIO_PinSource0);//选择用作EXTI线的GPIO引脚
    	GPIO_EXTILineConfig(GPIO_PortSourceGPIOB, GPIO_PinSource1);
    	
    	EXTI_InitTypeDef EXTI_InitStruct;
    	EXTI_InitStruct.EXTI_Line = EXTI_Line0 | EXTI_Line1;//配置外部中断线
    	EXTI_InitStruct.EXTI_LineCmd = ENABLE;//外部中断线使能
    	EXTI_InitStruct.EXTI_Mode = EXTI_Mode_Interrupt;//指定外部中断线为中断模式
    	EXTI_InitStruct.EXTI_Trigger = EXTI_Trigger_Falling;//外部中断线下降沿触发
    	EXTI_Init(&EXTI_InitStruct);
    	
    	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//配置nvic分组,目前为分组2,抢占优先级与响应优先级均为0~3
    	
    	//nvic配置	
    	NVIC_InitTypeDef NVIC_InitStruct;//结构体定义
    	NVIC_InitStruct.NVIC_IRQChannel = EXTI0_IRQn;//选择配置nvic的EXTI0
    	NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE;//使能
    	NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = 1;//抢占优先级
    	NVIC_InitStruct.NVIC_IRQChannelSubPriority = 1;//响应优先级
    	NVIC_Init(&NVIC_InitStruct);
    	
    	NVIC_InitStruct.NVIC_IRQChannel = EXTI1_IRQn;//选择配置nvic的EXTI0
    	NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE;//使能
    	NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = 1;//抢占优先级
    	NVIC_InitStruct.NVIC_IRQChannelSubPriority = 2;//响应优先级
    	NVIC_Init(&NVIC_InitStruct);
    }
    void EXTI0_IRQHandler(void)//服务中断函数
    {
    	if(EXTI_GetITStatus(EXTI_Line0)== SET)
    	{
    		if(GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_0) == 0)
    		{
    			if(GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_1) == 0)
    			{
    				Encoder_Count ++;
    			} 
    		}
    		EXTI_ClearITPendingBit(EXTI_Line0);//结束清除标志位
    	}
    }
    void EXTI1_IRQHandler(void)//服务中断函数
    {
    	if(EXTI_GetITStatus(EXTI_Line1)== SET)
    	{
    		if(GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_1) == 0)
    		{
    			if(GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_1) == 0)
    			{
    				Encoder_Count --;
    			}
    		}
    		EXTI_ClearITPendingBit(EXTI_Line1);//结束清除标志位
    	}
    }
    
    int16_t Encoder_Get(void)
    {
    	int16_t Temp;
    	Temp = Encoder_Count;
    	Encoder_Count = 0;
    	return Temp;
    }//返回后数据清零
    
    

    10.定时器内部时钟

    定时器初始化流程

    1.开启时钟
    2.配置时钟源
    3.时基单元初始化
    4.中断输出配置
    5.nvic中断分组
    6.nvic配置
    7.tim使能
    

    RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);//开启tim2时钟位于apb1总线

    TIM_InternalClockConfig(TIM2);//选择时钟(内部时钟tim2)

    TIM_TimeBaseInit();//配置时基单元

    TIM_ITConfig();//中断输出配置

    TIM_Cmd()//定时器使能

    Timer.h

    #ifndef __TIMER_H
    #define __TIMER_H
    
    void Timer_Init(void);
    
    #endif
    

    Timer.c

    #include "stm32f10x.h"                  // Device header
    /*
    	1.开启时钟
    	2.配置时钟源
    	3.时基单元初始化
    	4.中断输出配置
    	5.nvic中断分组
    	6.nvic配置
    	7.tim使能
    */
    
    /*
    51
    32   usart/iic/spi/freertos ~ 通信+系统
    树莓派 ~linux编程
    */
    void Timer_Init(void)
    {
    	//开启时钟
    	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);
    	//选择时钟源~~选择tim2为内部时钟
    	TIM_InternalClockConfig(TIM2);
    	//配置时基单元
    	TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStruct;
    	TIM_TimeBaseInitStruct.TIM_ClockDivision = TIM_CKD_DIV1;//时钟分频
    	TIM_TimeBaseInitStruct.TIM_CounterMode = TIM_CounterMode_Up;//计数模式~向上计数
    	TIM_TimeBaseInitStruct.TIM_Period = 10000 - 1;//计数周期
    	TIM_TimeBaseInitStruct.TIM_Prescaler = 7200 - 1;//预分频器72M = 7200 0000 /10000 /7200 = 1
    	TIM_TimeBaseInitStruct.TIM_RepetitionCounter = 0;
    	TIM_TimeBaseInit(TIM2, &TIM_TimeBaseInitStruct);
    	
    	//中断输出配置
    	TIM_ITConfig(TIM2,TIM_IT_Update,ENABLE);//开启nvic中断
    	
    	//nvic中断分组
    	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//ncic中断分组2
    	//nvic初始化
    	NVIC_InitTypeDef NVIC_InitStruct;
    	NVIC_InitStruct.NVIC_IRQChannel = TIM2_IRQn;
    	NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE;
    	NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = 2;
    	NVIC_InitStruct.NVIC_IRQChannelSubPriority = 1;
    	NVIC_Init(&NVIC_InitStruct);
    	//定时器使能
    	TIM_Cmd(TIM2, ENABLE);
    }
    //void TIM2_IRQHandler(void)
    //{
    //	if(TIM_GetITStatus(TIM2,TIM_IT_Update) == SET)
    //	{
    //		TIM_ClearITPendingBit(TIM2,TIM_IT_Update);//清除标志位
    //	}
    //}
    

    main.c

    #include "stm32f10x.h"                  // Device header
    #include "Delay.h"
    #include "oled.h"
    #include "Timer.h"//.h文件多打了一个空格
    
    int16_t Num;
    
    int main()
    {
    	OLED_Init();//oled初始化
    	Timer_Init();
    	OLED_ShowString(1,1,"Num:");
    	while(1)
    	{
    		OLED_ShowNum(1,5,Num,5);
    	}
    }
    
    void TIM2_IRQHandler(void)
    {
    	if(TIM_GetITStatus(TIM2,TIM_IT_Update) == SET)
    	{
    		Num ++ ;
    		TIM_ClearITPendingBit(TIM2,TIM_IT_Update);//清除标志位
    	}
    }
    

    11.定时器外部时钟

    定时器流程

    1.开启时钟
    2.配置时钟源
    3.时基单元初始化
    4.中断输出配置
    5.nvic中断分组
    6.nvic配置
    7.tim使能 
    

    TIM_ETRClockMode2Config();//配置外部时钟模式2

    TIM_GetCounter(TIM2);//返回tim2的cnt值

    Timer.h

    #ifndef __TIMER_H
    #define __TIMER_H
    
    void Timer_Init(void);
    uint16_t Timer_GetCount(void);
    #endif
    

    Timer.c

    #include "stm32f10x.h"                  // Device header
    
    void Timer_Init(void)
    {
    	//开启时钟
    	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);
    //
    	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);//开启gpioa时钟
    //
    	
    //
    	GPIO_InitTypeDef GPIO_InitStruct;
    	GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IPU;
    	GPIO_InitStruct.GPIO_Pin = GPIO_Pin_0;
    	GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
    	GPIO_Init(GPIOA, &GPIO_InitStruct);//gpioa初始化~上拉输入
    //
    
    //
    	TIM_ETRClockMode2Config(TIM2,TIM_ExtTRGPSC_OFF,TIM_ExtTRGPolarity_NonInverted,0x0f);
    	//配置外部时钟模式2,外设tim2,外部触发关闭,外部触发极性上升沿,滤波最大~0x0f
    //
    //	//选择时钟源~~选择tim2为内部时钟
    //	TIM_InternalClockConfig(TIM2);
    	//配置时基单元
    	TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStruct;
    	TIM_TimeBaseInitStruct.TIM_ClockDivision = TIM_CKD_DIV1;//时钟分频
    	TIM_TimeBaseInitStruct.TIM_CounterMode = TIM_CounterMode_Up;//计数模式~向上计数
    	TIM_TimeBaseInitStruct.TIM_Period = 10 - 1;//计数周期 arr
    	TIM_TimeBaseInitStruct.TIM_Prescaler = 1 - 1;//预分频器psc
    	TIM_TimeBaseInitStruct.TIM_RepetitionCounter = 0;//重复计数器
    	TIM_TimeBaseInit(TIM2, &TIM_TimeBaseInitStruct);
    	
    	TIM_ClearFlag(TIM2, TIM_FLAG_Update);//清除中断触发标志位
    	//中断输出配置
    	TIM_ITConfig(TIM2,TIM_IT_Update,ENABLE);//开启nvic中断
    	//启用或禁用指定中断,tim2,tim更新中断源,使能
    	//nvic中断分组
    	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//ncic中断分组2
    	//nvic初始化
    	NVIC_InitTypeDef NVIC_InitStruct;
    	NVIC_InitStruct.NVIC_IRQChannel = TIM2_IRQn;
    	NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE;
    	NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = 2;
    	NVIC_InitStruct.NVIC_IRQChannelSubPriority = 1;
    	NVIC_Init(&NVIC_InitStruct);
    	//定时器使能
    	TIM_Cmd(TIM2, ENABLE);
    }
    uint16_t Timer_GetCount(void)
    {
    	return TIM_GetCounter(TIM2);//返回tim2的cnt值
    }
    //void TIM2_IRQHandler(void)
    //{
    //	if(TIM_GetITStatus(TIM2,TIM_IT_Update) == SET)
    //	{
    //		TIM_ClearITPendingBit(TIM2,TIM_IT_Update);//清除标志位
    //	}
    //}
    

    main.c

    #include "stm32f10x.h"                  // Device header
    #include "Delay.h"
    #include "oled.h"
    #include "Timer.h"//.h文件多打了一个空格
    
    int16_t Num;
    
    int main()
    {
    	OLED_Init();//oled初始化
    	Timer_Init();
    	OLED_ShowString(1,1,"Num:");
    	OLED_ShowString(2,1,"CNT:");
    	while(1)
    	{
    		OLED_ShowNum(1,5,Num,5);
    		OLED_ShowNum(2,5,Timer_GetCount(),5);
    	}
    }
    
    void TIM2_IRQHandler(void)
    {
    	if(TIM_GetITStatus(TIM2,TIM_IT_Update) == SET)
    	{
    		Num ++ ;
    		TIM_ClearITPendingBit(TIM2,TIM_IT_Update);//清除标志位
    	}
    }
    

    12.PWM控制LED

    输出比较流程

    1.rcc开启时钟(tim/gpio)
    2.配置时基单元
    3.配置输出比较单元(ccr/输出比较模式/极性选择/输出使能)
    4.配置GPIO口为复用推挽
    5.启动计数器
    

    TIM_InternalClockConfig(TIM2); //内部时钟源选择

    TIM_TimeBaseInit();//时基单元初始化

    TIM_OC1Init();//输出比较初始化

    TIM_OCStructInit();//结构体赋值

    TIM_Cmd();//定时器使能

    TIM_SetCompare1();//设置ccr1的值

    pwm.h

    #ifndef __PWM_H
    #define __PWM_H
    void PWM_Init(void);//pwm初始化
    void PWM_SetComparel(uint16_t Compare);//设置ccr1的值用于调节占空比
    #endif
    

    pwm.c

    #include "stm32f10x.h"                  // Device header
    /*
    1.rcc开启时钟(tim/gpio)
    2.配置时基单元
    3.配置输出比较单元(ccr/输出比较模式/极性选择/输出使能)
    4.配置GPIO口为复用推挽
    5.启动计数器
    */
    void PWM_Init(void)
    {
    	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);							//tim2时钟开启
    	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);             //gpioa初始化
    	
    	GPIO_InitTypeDef GPIO_InitStruct;
    	GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF_PP;//复用推挽输出
    	GPIO_InitStruct.GPIO_Pin = GPIO_Pin_0;
    	GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
    	GPIO_Init(GPIOA,&GPIO_InitStruct);																//gpio_a0脚初始化
    	
    	TIM_InternalClockConfig(TIM2);																	//内部时钟源选择
    	
    	TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStruct;
    	TIM_TimeBaseInitStruct.TIM_ClockDivision = TIM_CKD_DIV1;
    	TIM_TimeBaseInitStruct.TIM_CounterMode = TIM_CounterMode_Up;
    	TIM_TimeBaseInitStruct.TIM_Period = 100 - 1;//计数周期
    	TIM_TimeBaseInitStruct.TIM_Prescaler = 720 - 1;//预分频器
    	TIM_TimeBaseInitStruct.TIM_RepetitionCounter = 0;//重复计数器
    	TIM_TimeBaseInit(TIM2,&TIM_TimeBaseInitStruct);                //时基单元初始化
    	
    	TIM_OCInitTypeDef TIM_OCInitStruct;
    	TIM_OCStructInit(&TIM_OCInitStruct);//结构体初始化,结构体未完全赋值先进行初始化赋值
    	
    	TIM_OCInitStruct.TIM_OCMode = TIM_OCMode_PWM1;//输出比较模式
    	TIM_OCInitStruct.TIM_OCPolarity = TIM_OCPolarity_High;//输出比较极性~high原样输出/low反向输出
    	TIM_OCInitStruct.TIM_OutputState = ENABLE;//使能
    	TIM_OCInitStruct.TIM_Pulse = 0;//CCR初始值
    	TIM_OC1Init(TIM2,&TIM_OCInitStruct);                            //输出比较初始化
    	
    	TIM_Cmd(TIM2, ENABLE);//使能,定时器开始运行
    }
    void PWM_SetComparel(uint16_t Compare)
    {
    	TIM_SetCompare1(TIM2, Compare);//设置ccr1的值
    }
    

    main.c

    #include "stm32f10x.h"                  // Device header
    #include "Delay.h"
    #include "oled.h"
    #include "pwm.h"
    
    uint8_t i;
    
    int main()
    {
    	OLED_Init();//oled初始化
    	PWM_Init();//pwm初始化
    	while(1)
    	{
    		for(i = 0;i<=100;i++)
    		{
    			PWM_SetComparel(i);
    			Delay_ms(10);
    		}
    		for(i = 0;i<=100;i++)
    		{
    			PWM_SetComparel(100 - i);
    			Delay_ms(10);
    		}
    	}
    }
    

    13.PWM控制舵机

    Servo.h

    #ifndef __SERVO_H
    #define __SERVO_H
    void Servo_Init(void);
    void Servo_SetAngle(float Angle);
    #endif 
    

    Servo.c

    #include "stm32f10x.h"                  // Device header
    #include "stm32f10x.h"                  // Device header
    #include "pwm.h"
    void Servo_Init(void)
    {
    	PWM_Init();//初始化舵机底层pwm
    }
    void Servo_SetAngle(float Angle)
    {
    	PWM_SetCompare2(Angle / 180 * 2000 + 500);//设置占空比
    }
    

    main.c

    #include "stm32f10x.h"                  // Device header
    #include "Delay.h"
    #include "oled.h"
    #include "Servo.h"
    #include "Key.h"
    
    uint8_t KeyNum;
    float Angle;
    
    int main()
    {
    	OLED_Init();//oled初始化
    	Servo_Init();//舵机初始化
    	Key_Init();//按键初始化
    	
    	OLED_ShowString(1,1,"Angle:");//显示静态字符"Angle:"
    	
    	while(1)
    	{
    		KeyNum = Key_GetNum();//得到键码返回值
    		if(KeyNum == 1)
    		{
    			Angle += 30;//角度增加30
    			if(Angle > 180)
    			{
    				Angle = 0;
    			}
    		}
    		Servo_SetAngle(Angle);
    		OLED_ShowNum(1,7,Angle,3);
    	}
    }
    

    14.pwm驱动直流电机

    Motor.h

    #ifndef __MOTOR_H
    #define __MOTOR_H
    void Motor_Init(void);//舵机初始化
    void Motor_SetSpeed(int8_t Speed);//速度设置
    #endif
    

    Motor.c

    #include "stm32f10x.h"                  // Device header
    #include "pwm.h"
    void Motor_Init(void)
    {
    	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
    	GPIO_InitTypeDef GPIO_InitStruct;
    	GPIO_InitStruct.GPIO_Mode = GPIO_Mode_Out_PP;
    	GPIO_InitStruct.GPIO_Pin = GPIO_Pin_4 | GPIO_Pin_5;
    	GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
    	GPIO_Init(GPIOA ,&GPIO_InitStruct);//PA4与PA5脚进行初始化,用作控制脚
    	
    	PWM_Init();//PA2脚用作输出pwm
    }
    void Motor_SetSpeed(int8_t Speed)
    {
    	if(Speed >= 0)
    	{
    		GPIO_SetBits(GPIOA, GPIO_Pin_4);
    		GPIO_ResetBits(GPIOA, GPIO_Pin_5);
    		PWM_SetCompare3(Speed);
    	}
    	else
    	{
    		GPIO_ResetBits(GPIOA,GPIO_Pin_4);
    		GPIO_SetBits(GPIOA,GPIO_Pin_5);
    		PWM_SetCompare3(-Speed);//反向旋转
    	}
    }
    

    main.c

    #include "stm32f10x.h"                  // Device header
    #include "Delay.h"
    #include "oled.h"
    #include "Motor.h"
    #include "Key.h"
    
    uint8_t KeyNum;
    int8_t Speed;
    
    int main()
    {
    	OLED_Init();//oled初始化
    	Motor_Init();//舵机初始化
    	Key_Init();//按键初始化
    	
    	OLED_ShowString(1,1,"speed:");
    	
    	while(1)
    	{
    		KeyNum = Key_GetNum();
    		if(KeyNum == 1)
    		{
    			Speed += 20;
    			if(Speed > 100)
    			{
    				Speed = -100;
    			}
    		}
    		Motor_SetSpeed(Speed);//占空比传递
    		OLED_ShowSignedNum(1,7,Speed,3);
    	}
    }
    

    15.定时器输入捕获

    TIM_ICInit(TIM3,&TIM_ICInitStruct);//输入捕获初始化

    TIM_SelectInputTrigger(TIM3,TIM_TS_TI1FP1);//触发源选择~TI1FP1

    TIM_SelectSlaveMode(TIM3,TIM_SlaveMode_Reset);//从模式选择

    输入捕获流程

    1.rcc开启时钟(gpio/tim)
    2.gpio初始化(gpio~输入模式)~上拉 or 浮空  
    3.配置时基单元,让cnt计数器在内部时钟的驱动下自增
    4.配置输入捕获单元(滤波器、极性、直连通道 or 交叉通道、分频器) 
    5.选择从模式的触发源ti1fp1
    6.选择触发后进行的操作reset
    7.tim开启定时器
    

    ic.h

    #ifndef __IC_H
    #define __IC_H
    void Ic_Init(void);//输入捕获初始化
    uint32_t Ic_GetFreq(void);//获取频率
    #endif
    

    ic.c

    #include "stm32f10x.h"                  // Device header
    /*
    1.rcc开启时钟(gpio/tim)
    2.gpio初始化(gpio~输入模式)~上拉 or 浮空  
    3.配置时基单元,让cnt计数器在内部时钟的驱动下自增
    4.配置输入捕获单元(滤波器、极性、直连通道 or 交叉通道、分频器)  
    5.选择从模式的触发源ti1fp1
    6.选择触发后进行的操作reset
    7.tim开启定时器
    */
    void Ic_Init(void)
    {
    	//rcc开启时钟
    	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);							//tim2时钟开启
    	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);             //gpioa初始化
    	//gpio初始化
    	GPIO_InitTypeDef GPIO_InitStruct;
    	GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IPU;//复用推挽输出
    	GPIO_InitStruct.GPIO_Pin = GPIO_Pin_6;
    	GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
    	GPIO_Init(GPIOA,&GPIO_InitStruct);																//gpio_a0脚初始化
    	//时钟源选择
    	TIM_InternalClockConfig(TIM3);																	//内部时钟源选择
    	//时基单元初始化
    	TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStruct;
    	TIM_TimeBaseInitStruct.TIM_ClockDivision = TIM_CKD_DIV1;
    	TIM_TimeBaseInitStruct.TIM_CounterMode = TIM_CounterMode_Up;
    	TIM_TimeBaseInitStruct.TIM_Period = 65536 - 1;//计数周期
    	TIM_TimeBaseInitStruct.TIM_Prescaler = 72 - 1;//预分频器
    	TIM_TimeBaseInitStruct.TIM_RepetitionCounter = 0;//重复计数器
    	TIM_TimeBaseInit(TIM3,&TIM_TimeBaseInitStruct);  
    	//输入捕获初始化
    	TIM_ICInitTypeDef TIM_ICInitStruct;
    	TIM_ICInitStruct.TIM_Channel = TIM_Channel_1;//模式3通道1
    	TIM_ICInitStruct.TIM_ICFilter = 0xF;//滤波
    	TIM_ICInitStruct.TIM_ICPolarity = TIM_ICPolarity_Rising;//极性,不反转
    	TIM_ICInitStruct.TIM_ICPrescaler = TIM_ICPSC_DIV1;//预分频,不分频
    	TIM_ICInitStruct.TIM_ICSelection = TIM_ICSelection_DirectTI;//直接选择
    	TIM_ICInit(TIM3,&TIM_ICInitStruct);                                  //<=====================
    	//选择触发源及从模式
    	TIM_SelectInputTrigger(TIM3,TIM_TS_TI1FP1);//触发源选择~TI1FP1       //<=====================
    	TIM_SelectSlaveMode(TIM3,TIM_SlaveMode_Reset);//选择从模式					 //<=====================
    	
    	TIM_Cmd(TIM3,ENABLE);//使能tim3,定时器开始运行
    }
    uint32_t Ic_GetFreq(void)
    {
    	return 1000000 / (TIM_GetCapture1(TIM3) + 1);
    }
    

    main.c

    #include "stm32f10x.h"                  // Device header
    #include "Delay.h"
    #include "oled.h"
    #include "pwm.h"
    #include "ic.h"
    int main()
    {
    	OLED_Init();//oled初始化
    	PWM_Init();//pwm初始化
    	Ic_Init();//输入捕获初始化
    	OLED_ShowString(1,1,"Freq:00000Hz");
    	PWM_SetPrescaler(720 - 1);//设置频率 freq = 72M / (psc + 1)/100
    	PWM_SetCompare3(50);//设置占空比 duty = ccr / 100
    	while(1)
    	{
    		OLED_ShowNum(1,6,Ic_GetFreq(),5);//频率展示
    	}
    }
    

    16.输入捕获~频率与占空比

    TIM_PWMIConfig();//传入通道及结构体变量将自动配置另一个通道

    ic.h

    #ifndef __IC_H
    #define __IC_H
    void Ic_Init(void);//输入捕获初始化
    uint32_t Ic_GetFreq(void);//获取频率
    uint32_t Ic_GetDuty(void);//获取占空比
    #endif
    

    ic.c

    #include "stm32f10x.h"                  // Device header
    /*
    1.rcc开启时钟(gpio/tim)
    2.gpio初始化(gpio~输入模式)~上拉 or 浮空  
    3.配置时基单元,让cnt计数器在内部时钟的驱动下自增
    4.配置输入捕获单元(滤波器、极性、直连通道 or 交叉通道、分频器)  
    5.选择从模式的触发源ti1fp1
    6.选择触发后进行的操作reset
    7.tim开启定时器
    */
    void Ic_Init(void)
    {
    	//rcc开启时钟
    	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);							//tim2时钟开启
    	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);             //gpioa初始化
    	//gpio初始化
    	GPIO_InitTypeDef GPIO_InitStruct;
    	GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IPU;//复用推挽输出
    	GPIO_InitStruct.GPIO_Pin = GPIO_Pin_6;
    	GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
    	GPIO_Init(GPIOA,&GPIO_InitStruct);																//gpio_a0脚初始化
    	//时钟源选择
    	TIM_InternalClockConfig(TIM3);																	//内部时钟源选择
    	//时基单元初始化
    	TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStruct;
    	TIM_TimeBaseInitStruct.TIM_ClockDivision = TIM_CKD_DIV1;
    	TIM_TimeBaseInitStruct.TIM_CounterMode = TIM_CounterMode_Up;
    	TIM_TimeBaseInitStruct.TIM_Period = 65536 - 1;//计数周期
    	TIM_TimeBaseInitStruct.TIM_Prescaler = 72 - 1;//预分频器
    	TIM_TimeBaseInitStruct.TIM_RepetitionCounter = 0;//重复计数器
    	TIM_TimeBaseInit(TIM3,&TIM_TimeBaseInitStruct);  
    	//输入捕获初始化(pwmi)
    	TIM_ICInitTypeDef TIM_ICInitStruct;
    	TIM_ICInitStruct.TIM_Channel = TIM_Channel_1;//模式3通道1
    	TIM_ICInitStruct.TIM_ICFilter = 0xF;//滤波
    	TIM_ICInitStruct.TIM_ICPolarity = TIM_ICPolarity_Rising;//极性,不反转
    	TIM_ICInitStruct.TIM_ICPrescaler = TIM_ICPSC_DIV1;//预分频,不分频
    	TIM_ICInitStruct.TIM_ICSelection = TIM_ICSelection_DirectTI;//直接选择
    	//TIM_ICInit(TIM3,&TIM_ICInitStruct);                                  
    	TIM_PWMIConfig(TIM3,&TIM_ICInitStruct);//将结构体变量交给TIM_PWMIConfig,配置tim3的输入捕获通道
    																				 //同时此函数会把另一个通道配置为相反模式//<=====================
    	//选择触发源及从模式
    	TIM_SelectInputTrigger(TIM3,TIM_TS_TI1FP1);//触发源选择~TI1FP1       
    	TIM_SelectSlaveMode(TIM3,TIM_SlaveMode_Reset);//选择从模式					 
    	
    	TIM_Cmd(TIM3,ENABLE);//使能tim3,定时器开始运行
    }
    uint32_t Ic_GetFreq(void)
    {
    	return 1000000 / (TIM_GetCapture1(TIM3) + 1);
    }
    uint32_t Ic_GetDuty(void)
    {
    	return (TIM_GetCapture2(TIM3) + 1) * 100 / (TIM_GetCapture1(TIM3) + 1);//计算占空比
    }
    

    main.c

    #include "stm32f10x.h"                  // Device header
    #include "Delay.h"
    #include "oled.h"
    #include "pwm.h"
    #include "ic.h"
    int main()
    {
    	OLED_Init();//oled初始化
    	PWM_Init();//pwm初始化
    	Ic_Init();//输入捕获初始化
    	OLED_ShowString(1,1,"Freq:00000Hz");
    	OLED_ShowString(2,1,"Duty:00%");
    	PWM_SetPrescaler(720 - 1);//设置频率 freq = 72M / (psc + 1)/100
    	PWM_SetCompare3(50);//设置占空比 duty = ccr / 100
    	while(1)
    	{
    		OLED_ShowNum(1,6,Ic_GetFreq(),5);//频率展示
    		OLED_ShowNum(2,6,Ic_GetDuty(),2);//占空比显示
    	}
    }
    

    17.编码器测速

    TIM_EncoderInterfaceConfig();//配置编码器以及两个通道是否反相

    EncoderTwo.h

    #ifndef __ENCODERTWO_H
    #define __ENCODERTWO_H
    void EncoderTwo_Init(void);//编码器测速初始化
    int16_t Encoder_Get(void);//获取编码器测速值
    #endif
    

    EncoderTwo.c

    #include "stm32f10x.h"                  // Device header
    
    void EncoderTwo_Init(void)
    {
    	/*开启时钟*/
    	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);			//开启TIM3的时钟
    	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);			//开启GPIOA的时钟
    	
    	/*GPIO初始化*/
    	GPIO_InitTypeDef GPIO_InitStructure;
    	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
    	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7;
    	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    	GPIO_Init(GPIOA, &GPIO_InitStructure);							//将PA6和PA7引脚初始化为上拉输入
    	
    	/*时基单元初始化*/
    	TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;				//定义结构体变量
    	TIM_TimeBaseInitStructure.TIM_ClockDivision = TIM_CKD_DIV1;     //时钟分频,选择不分频,此参数用于配置滤波器时钟,不影响时基单元功能
    	TIM_TimeBaseInitStructure.TIM_CounterMode = TIM_CounterMode_Up; //计数器模式,选择向上计数
    	TIM_TimeBaseInitStructure.TIM_Period = 65536 - 1;               //计数周期,即ARR的值
    	TIM_TimeBaseInitStructure.TIM_Prescaler = 1 - 1;                //预分频器,即PSC的值
    	TIM_TimeBaseInitStructure.TIM_RepetitionCounter = 0;            //重复计数器,高级定时器才会用到
    	TIM_TimeBaseInit(TIM3, &TIM_TimeBaseInitStructure);             //将结构体变量交给TIM_TimeBaseInit,配置TIM3的时基单元
    	
    	//输入捕获初始化
    	TIM_ICInitTypeDef TIM_ICInitStruct;
    	TIM_ICStructInit(&TIM_ICInitStruct);//不完全赋值先进行初始化//<======================
    	
    	TIM_ICInitStruct.TIM_Channel = TIM_Channel_1;//选择定时器通道
    	TIM_ICInitStruct.TIM_ICFilter = 0xf;//滤波器
    	TIM_ICInit(TIM3,&TIM_ICInitStruct);
    	TIM_ICInitStruct.TIM_Channel = TIM_Channel_2;//选择定时器通道
    	TIM_ICInitStruct.TIM_ICFilter = 0xf;//滤波器
    	TIM_ICInit(TIM3,&TIM_ICInitStruct);
    
    	TIM_EncoderInterfaceConfig(TIM3,TIM_EncoderMode_TI12,TIM_ICPolarity_Rising,TIM_ICPolarity_Rising);
    	//配置编码器模式以及两个输入通道是否反相
    	TIM_Cmd(TIM3, ENABLE);
    }
    int16_t Encoder_Get(void)
    {
    	int16_t Temp;
    	Temp = TIM_GetCounter(TIM3);//获取计数器计数值
    	TIM_SetCounter(TIM3 , 0);//设置计数器值
    	return Temp;
    }
    

    main.c

    #include "stm32f10x.h"                  // Device header
    #include "Delay.h"
    #include "oled.h"
    #include "timer.h"
    #include "encodertwo.h"
    
    int16_t Speed;
    
    int main()
    {
    	OLED_Init();//oled初始化
    	Timer_Init();//定时器初始化
    	EncoderTwo_Init();//编码器接口初始化
    	OLED_ShowString(1,1,"Speed:");
    	while(1)
    	{
    		OLED_ShowSignedNum(1,7,Speed,5);
    	}
    }
    void TIM2_IRQHandler(void)
    {
    	if(TIM_GetITStatus(TIM2,TIM_IT_Update) == SET)
    	{
    		Speed = Encoder_Get();//将寄存器中数值保存到中间变量Speed中
    		TIM_ClearITPendingBit(TIM2,TIM_IT_Update);//清除标志位
    	}
    }
    
    
    物联沃分享整理
    物联沃-IOTWORD物联网 » STM32常用函数:中断定时器操作指南

    发表评论