#第六章 TIM定时器#基于江科大的stm32单片机学习笔记

 

视频链接:[1-1] 课程简介_哔哩哔哩_bilibili

STM32F103c8t6引脚定义表:(橙色是电源相关的引脚,蓝色是最小系统相关的引脚。绿色的是IO口和功能引脚,FT意为能容忍5V电压,主功能是上电默认的功能,默认复用功能是IO口上连接的外设功能引脚,加粗的引脚是能直接用的,没加粗的引脚可能要进行其他配置才能使用)

6-1TIM定时器中断

 

 

 

 

有关定时器的库函数就更多了,先将"stm32f10x_tim.h"内的函数都列出来大致看一下,用到再详细说明

//将时钟配置恢复到上电时的默认状态
void TIM_DeInit(TIM_TypeDef* TIMx);

//时基单元初始化
void TIM_TimeBaseInit(TIM_TypeDef* TIMx, TIM_TimeBaseInitTypeDef* TIM_TimeBaseInitStruct);

//这四个函数就是配置输出比较模块的,OC(Output Compare)的意思是输出比较
void TIM_OC1Init(TIM_TypeDef* TIMx, TIM_OCInitTypeDef* TIM_OCInitStruct);
void TIM_OC2Init(TIM_TypeDef* TIMx, TIM_OCInitTypeDef* TIM_OCInitStruct);
void TIM_OC3Init(TIM_TypeDef* TIMx, TIM_OCInitTypeDef* TIM_OCInitStruct);
void TIM_OC4Init(TIM_TypeDef* TIMx, TIM_OCInitTypeDef* TIM_OCInitStruct);

//输入通道的初始化
void TIM_ICInit(TIM_TypeDef* TIMx, TIM_ICInitTypeDef* TIM_ICInitStruct);

//PWM输入捕获的设置
void TIM_PWMIConfig(TIM_TypeDef* TIMx, TIM_ICInitTypeDef* TIM_ICInitStruct);


void TIM_BDTRConfig(TIM_TypeDef* TIMx, TIM_BDTRInitTypeDef *TIM_BDTRInitStruct);

//将之前配置的结构体内的变量重置成默认值,以便重新进行配置
void TIM_TimeBaseStructInit(TIM_TimeBaseInitTypeDef* TIM_TimeBaseInitStruct);

//给结构体赋默认值的,当我们要重新配置结构体或有些参数用不上时,就使用此函数把结构体赋默认值
void TIM_OCStructInit(TIM_OCInitTypeDef* TIM_OCInitStruct);

//初始化输入捕获配置结构体,以便于赋默认值或重新配置
void TIM_ICStructInit(TIM_ICInitTypeDef* TIM_ICInitStruct);


void TIM_BDTRStructInit(TIM_BDTRInitTypeDef* TIM_BDTRInitStruct);

//用来使能定时器
void TIM_Cmd(TIM_TypeDef* TIMx, FunctionalState NewState);

//仅高级定时器使用,在使用高级定时器输出PWM时,要调用此函数,否则无法正常输出PWM
void TIM_CtrlPWMOutputs(TIM_TypeDef* TIMx, FunctionalState NewState);

//使能定时器产生的中断信号
void TIM_ITConfig(TIM_TypeDef* TIMx, uint16_t TIM_IT, FunctionalState NewState);


void TIM_GenerateEvent(TIM_TypeDef* TIMx, uint16_t TIM_EventSource);


void TIM_DMAConfig(TIM_TypeDef* TIMx, uint16_t TIM_DMABase, uint16_t TIM_DMABurstLength);


void TIM_DMACmd(TIM_TypeDef* TIMx, uint16_t TIM_DMASource, FunctionalState NewState);

//选择内部时钟,如果不用此函数,芯片默认也是使用内部时钟,追求严谨可加上此函数
void TIM_InternalClockConfig(TIM_TypeDef* TIMx);

//选择ITRx其他定时器的时钟
void TIM_ITRxExternalClockConfig(TIM_TypeDef* TIMx, uint16_t TIM_InputTriggerSource);

//选择TIx捕获通道的时钟
void TIM_TIxExternalClockConfig(TIM_TypeDef* TIMx, uint16_t TIM_TIxExternalCLKSource,
                                uint16_t TIM_ICPolarity, uint16_t ICFilter);

//选择ETR通过外部时钟模式1输入的时钟
void TIM_ETRClockMode1Config(TIM_TypeDef* TIMx, uint16_t TIM_ExtTRGPrescaler, uint16_t TIM_ExtTRGPolarity,
                             uint16_t ExtTRGFilter);

//选择ETR通过外部时钟模式2输入的时钟
void TIM_ETRClockMode2Config(TIM_TypeDef* TIMx, uint16_t TIM_ExtTRGPrescaler, 
                             uint16_t TIM_ExtTRGPolarity, uint16_t ExtTRGFilter);

//单独用来配置ETR引脚的预分频器、极性、滤波器这些参数
void TIM_ETRConfig(TIM_TypeDef* TIMx, uint16_t TIM_ExtTRGPrescaler, uint16_t TIM_ExtTRGPolarity,
                   uint16_t ExtTRGFilter);

//直接单独配置预分配值PSC,参数2是写入模式,可选择是听从安排,在更新事件生效;或者是在写入后手动
//产生一个更新事件,让这个值立刻生效
void TIM_PrescalerConfig(TIM_TypeDef* TIMx, uint16_t Prescaler, uint16_t TIM_PSCReloadMode);

//改变计数器的计数模式
void TIM_CounterModeConfig(TIM_TypeDef* TIMx, uint16_t TIM_CounterMode);


void TIM_SelectInputTrigger(TIM_TypeDef* TIMx, uint16_t TIM_InputTriggerSource);


void TIM_EncoderInterfaceConfig(TIM_TypeDef* TIMx, uint16_t TIM_EncoderMode,
                                uint16_t TIM_IC1Polarity, uint16_t TIM_IC2Polarity);

//配置强制输出模式,运行中想要强制改变输出的波形,直接输出高或低电平就用这个
//不过其效果和改变PWM占空比100%或0%的效果是一样的
void TIM_ForcedOC1Config(TIM_TypeDef* TIMx, uint16_t TIM_ForcedAction);
void TIM_ForcedOC2Config(TIM_TypeDef* TIMx, uint16_t TIM_ForcedAction);
void TIM_ForcedOC3Config(TIM_TypeDef* TIMx, uint16_t TIM_ForcedAction);
void TIM_ForcedOC4Config(TIM_TypeDef* TIMx, uint16_t TIM_ForcedAction);

//自动重装器预装功能配置
void TIM_ARRPreloadConfig(TIM_TypeDef* TIMx, FunctionalState NewState);


void TIM_SelectCOM(TIM_TypeDef* TIMx, FunctionalState NewState);


void TIM_SelectCCDMA(TIM_TypeDef* TIMx, FunctionalState NewState);


void TIM_CCPreloadControl(TIM_TypeDef* TIMx, FunctionalState NewState);

//配置CCR寄存器的预装功能,也就是影子寄存器(写入的值不会立即生效,而是在事件更新后才生效)
void TIM_OC1PreloadConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCPreload);
void TIM_OC2PreloadConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCPreload);
void TIM_OC3PreloadConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCPreload);
void TIM_OC4PreloadConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCPreload);

//配置快速使能
void TIM_OC1FastConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCFast);
void TIM_OC2FastConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCFast);
void TIM_OC3FastConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCFast);
void TIM_OC4FastConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCFast);

//外部事件时清除REF信号
void TIM_ClearOC1Ref(TIM_TypeDef* TIMx, uint16_t TIM_OCClear);
void TIM_ClearOC2Ref(TIM_TypeDef* TIMx, uint16_t TIM_OCClear);
void TIM_ClearOC3Ref(TIM_TypeDef* TIMx, uint16_t TIM_OCClear);
void TIM_ClearOC4Ref(TIM_TypeDef* TIMx, uint16_t TIM_OCClear);

//用来单独设置输出比较极性的,带N的就是高级定时器的互补通道的配置,OC4无互补通道
void TIM_OC1PolarityConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCPolarity);
void TIM_OC1NPolarityConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCNPolarity);
void TIM_OC2PolarityConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCPolarity);
void TIM_OC2NPolarityConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCNPolarity);
void TIM_OC3PolarityConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCPolarity);
void TIM_OC3NPolarityConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCNPolarity);
void TIM_OC4PolarityConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCPolarity);

//单独修改输出使能参数的
void TIM_CCxCmd(TIM_TypeDef* TIMx, uint16_t TIM_Channel, uint16_t TIM_CCx);
void TIM_CCxNCmd(TIM_TypeDef* TIMx, uint16_t TIM_Channel, uint16_t TIM_CCxN);

//单独更改输出比较模式
void TIM_SelectOCxM(TIM_TypeDef* TIMx, uint16_t TIM_Channel, uint16_t TIM_OCMode);


void TIM_UpdateDisableConfig(TIM_TypeDef* TIMx, FunctionalState NewState);


void TIM_UpdateRequestConfig(TIM_TypeDef* TIMx, uint16_t TIM_UpdateSource);


void TIM_SelectHallSensor(TIM_TypeDef* TIMx, FunctionalState NewState);


void TIM_SelectOnePulseMode(TIM_TypeDef* TIMx, uint16_t TIM_OPMode);


void TIM_SelectOutputTrigger(TIM_TypeDef* TIMx, uint16_t TIM_TRGOSource);


void TIM_SelectSlaveMode(TIM_TypeDef* TIMx, uint16_t TIM_SlaveMode);


void TIM_SelectMasterSlaveMode(TIM_TypeDef* TIMx, uint16_t TIM_MasterSlaveMode);

//给计数器直接写入一个值
void TIM_SetCounter(TIM_TypeDef* TIMx, uint16_t Counter);

//给自动重装值直接写入一个值
void TIM_SetAutoreload(TIM_TypeDef* TIMx, uint16_t Autoreload);

//单独用来更改CCR寄存器值的,PWM输出更改占空比就用这个函数
void TIM_SetCompare1(TIM_TypeDef* TIMx, uint16_t Compare1);
void TIM_SetCompare2(TIM_TypeDef* TIMx, uint16_t Compare2);
void TIM_SetCompare3(TIM_TypeDef* TIMx, uint16_t Compare3);
void TIM_SetCompare4(TIM_TypeDef* TIMx, uint16_t Compare4);


void TIM_SetIC1Prescaler(TIM_TypeDef* TIMx, uint16_t TIM_ICPSC);


void TIM_SetIC2Prescaler(TIM_TypeDef* TIMx, uint16_t TIM_ICPSC);


void TIM_SetIC3Prescaler(TIM_TypeDef* TIMx, uint16_t TIM_ICPSC);


void TIM_SetIC4Prescaler(TIM_TypeDef* TIMx, uint16_t TIM_ICPSC);


void TIM_SetClockDivision(TIM_TypeDef* TIMx, uint16_t TIM_CKD);


uint16_t TIM_GetCapture1(TIM_TypeDef* TIMx);


uint16_t TIM_GetCapture2(TIM_TypeDef* TIMx);


uint16_t TIM_GetCapture3(TIM_TypeDef* TIMx);


uint16_t TIM_GetCapture4(TIM_TypeDef* TIMx);

//获取当前计数器的值,返回值就是当前计数器的值
uint16_t TIM_GetCounter(TIM_TypeDef* TIMx);

//获取当前预分频器的值,返回值就是当前预分频器的值
uint16_t TIM_GetPrescaler(TIM_TypeDef* TIMx);

//获取TIM标志位
FlagStatus TIM_GetFlagStatus(TIM_TypeDef* TIMx, uint16_t TIM_FLAG);

//清除TIM标志位
void TIM_ClearFlag(TIM_TypeDef* TIMx, uint16_t TIM_FLAG);

//获取定时器中断标志位
ITStatus TIM_GetITStatus(TIM_TypeDef* TIMx, uint16_t TIM_IT);

//清除定时器中断标志位
void TIM_ClearITPendingBit(TIM_TypeDef* TIMx, uint16_t TIM_IT);

6-2 定时器定时中断&定时器外部时钟

main.c

#include "stm32f10x.h"                  // Device header
#include "delay.h"
#include "timer.h"
#include "oled.h"
	
	int16_t num = 0;
	
//任务1 定时器定时中断
//OLED的SCL连B8,SDA连B9,显示屏上显示时间秒
void task01()
{
	OLED_Init();
	Task01_Timer_Init();
	
	OLED_ShowString(1,1,"Num:");
	while(1)
	{
		OLED_ShowNum(1,5,num,6);
	}
}

//任务2 定时器外部时钟
//对射式红外传感器接A0,遮挡传感器计数值count+1,满十次使num+1
void task02()
{
	OLED_Init();
	Task02_Timer_Init();
	
	OLED_ShowString(1,1,"Count:");
	while(1)
	{
		OLED_ShowNum(1,6,Timer_GetCounter(),6);
	}
}

int main(void)
{

	while (1)
	{
		
	}
}

//TIM2中断回调函数
void TIM2_IRQHandler(void)
{
	if(TIM_GetITStatus(TIM2,TIM_IT_Update) == SET)
	{
		num++;
		TIM_ClearITPendingBit(TIM2,TIM_IT_Update);
	}
}

time.c

#include "Device/Include/stm32f10x.h"   // Device header
/*
	开启时钟步骤
	1.RCC开启时钟
	2.选择时基单元的时钟源,对于定时中断,选择内部时钟源
	3.配置时基单元,包括预分频器PSC,自动重装器ARR,计数器CNT等
	4.配置输出中断控制,允许更新中断输出到NVIC
	5.配置NVIC,在NVIC中打开定时器中断的通道,并分配优先级
	6.运行控制,使能定时器,编写中断函数
*/
void Task01_Timer_Init()//初始化TIM2通用定时器
{
	//开启时钟
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2,ENABLE);
	
	//选择时基单元的时钟
	TIM_InternalClockConfig(TIM2);
	
	//初始化时基单元    定时频率 = 72M / (PSC + 1) / (ARR + 1)
	TIM_TimeBaseInitTypeDef My_TimerBaseInitstructure;
	My_TimerBaseInitstructure.TIM_ClockDivision = TIM_CKD_DIV1; //预分频值 
	My_TimerBaseInitstructure.TIM_CounterMode = TIM_CounterMode_Up; //计数模式
	My_TimerBaseInitstructure.TIM_Period = 10000 - 1; //ARR自动重装器的值
	My_TimerBaseInitstructure.TIM_Prescaler = 7200 - 1; //PCS预分频器的值
	My_TimerBaseInitstructure.TIM_RepetitionCounter = 0; //重复计数器的值
	TIM_TimeBaseInit(TIM2,&My_TimerBaseInitstructure);
	
	
	TIM_ClearFlag(TIM2,TIM_CounterMode_Up);//避免刚初始化完就进行一次中断
	
	
	//使能定时器中断,TIM_IT_Update为更新中断
	TIM_ITConfig(TIM2,TIM_IT_Update,ENABLE);
	
	//配置中断控制器NVIC
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
	
	//配置中断通道以及优先级相关,开启中断
	NVIC_InitTypeDef My_NVICStructure;
	My_NVICStructure.NVIC_IRQChannel = TIM2_IRQn;
	My_NVICStructure.NVIC_IRQChannelCmd = ENABLE;
	My_NVICStructure.NVIC_IRQChannelPreemptionPriority = 2;
	My_NVICStructure.NVIC_IRQChannelSubPriority = 1;
	NVIC_Init(&My_NVICStructure);
	
	//启动定时器
	TIM_Cmd(TIM2,ENABLE);
}

//编写TIM2的中断函数模板
//void TIM2_IRQHandler(void)
//{
//	if(TIM_GetITStatus(TIM2,TIM_IT_Update) == SET)
//	{
//		
//		TIM_ClearITPendingBit(TIM2,TIM_IT_Update);
//	}
//}

void Task02_Timer_Init()//初始化TIM2通用定时器
{
	//开启TIM2时钟
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2,ENABLE);
	
	//通过ETR引脚的外部时钟模式2配置
	TIM_ETRClockMode2Config(TIM2,TIM_ExtTRGPSC_OFF,TIM_ExtTRGPolarity_NonInverted,0x00);
	
	//初始化时基单元    定时频率 = 72M / (PSC + 1) / (ARR + 1)
	TIM_TimeBaseInitTypeDef My_TimerBaseInitstructure;
	My_TimerBaseInitstructure.TIM_ClockDivision = TIM_CKD_DIV1; //预分频值 
	My_TimerBaseInitstructure.TIM_CounterMode = TIM_CounterMode_Up; //计数模式
	My_TimerBaseInitstructure.TIM_Period = 10000 - 1; //ARR自动重装器的值
	My_TimerBaseInitstructure.TIM_Prescaler = 7200 - 1; //PCS预分频器的值
	My_TimerBaseInitstructure.TIM_RepetitionCounter = 0; //重复计数器的值
	TIM_TimeBaseInit(TIM2,&My_TimerBaseInitstructure);
	
	
	TIM_ClearFlag(TIM2,TIM_CounterMode_Up);//避免刚初始化完就进行一次中断
	
	
	//使能定时器中断,TIM_IT_Update为更新中断
	TIM_ITConfig(TIM2,TIM_IT_Update,ENABLE);
	
	//配置中断控制器NVIC
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
	
	//配置中断通道以及优先级相关,开启中断
	NVIC_InitTypeDef My_NVICStructure;
	My_NVICStructure.NVIC_IRQChannel = TIM2_IRQn;
	My_NVICStructure.NVIC_IRQChannelCmd = ENABLE;
	My_NVICStructure.NVIC_IRQChannelPreemptionPriority = 2;
	My_NVICStructure.NVIC_IRQChannelSubPriority = 1;
	NVIC_Init(&My_NVICStructure);
	
	//启动定时器
	TIM_Cmd(TIM2,ENABLE);
	
	//配置GPIO口
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
	GPIO_InitTypeDef My_GPIO_InitStructure;
	My_GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;
	My_GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
	My_GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOA,&My_GPIO_InitStructure);
}

uint16_t Timer_GetCounter(void)
{
	return TIM_GetCounter(TIM2);
}

6-3TIM输出捕获

PWM配置步骤:

1.开启RCC时钟,将要使用的定时器和GPIO外设时钟打开

2.配置时基单元,时钟源选择

3.配置输出比较单元,设置CCR的值,输出比较模式,极性选择,输出使能这些参数

4.配置GPIO,初始化为复用推挽输出的配置

5.运行控制,启动计数器

6-4 PWM驱动LED呼吸灯&PWM驱动直流电机

一个定时器TIM有四个通道,每个通道均可输出PWM波,但当我们用一个定时器输出4路PWM时,因为共用一个计数器,频率必须是一样的,占空比由各自通道的CCR决定,四路通道的相位也是一样的。

main.c

#include "stm32f10x.h"                  // Device header
#include "delay.h"
#include "OLED.h"	
#include "PWM.h"
#include "servo.h"	
#include "motor.h"
	
//任务1 PWM驱动LED呼吸灯
//A0接LED
void task01()
{
	uint8_t i;
	OLED_Init();
	Task01_PWM_Init();
	while(1)
	{
		for(i = 0;i < 100;i++)
		{
			Task01_PWM_SetComparel(i);
			Delay_ms(10);
		}
		for(i = 0;i < 100;i++)
		{
			Task01_PWM_SetComparel(100-i);
			Delay_ms(10);
		}
	}
}



//任务2 PWM驱动舵机
//A1接舵机的信号线  PA1是TIM2的CH2  B1接一个按键控制PWM改变,即把io口配置为上拉输入
void Task02()
{
	OLED_Init();
	Servo_Init();
	Servo_SetAngle(0);//初始把舵机设置为0度
	
	uint16_t Angle = 0;
	while(1)
	{
		if(GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_1) == RESET)//检测按键是否按下
		{
			Delay_ms(10);
			while(GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_1) == RESET);
			Angle += 20;
		}
//		for(Angle = 0;Angle <= 180; Angle+=20)
//		{
//			Servo_SetAngle(Angle);
//			Delay_ms(50);
//		}
//		for(Angle = 0;Angle <= 180; Angle+=20)
//		{
//			Servo_SetAngle(180-Angle);
//			Delay_ms(50);
//		}
		if(Angle > 180)
		{
			Angle = 0;
		}
		
		
	}
}

//任务3 PWM驱动直流电机
//用TB6612来驱动直流电机
/*
	AO1接电机正极,AO2接电机负极 VM接5V VCC接3.3V GND共地 STBY接3.3V
	PWMA接PA2,AIN1接PA4,AIN2接PA5      PA2是TIM2的CH3
	按键接B1,端口为上拉输入
*/
void Task03()
{
    OLED_Init();
    Task03_PWM_Init();
    
	int8_t temp = 0;//Speed的范围是0到100
	while(1)
	{
		if(GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_1) == RESET)
		{
			while(GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_1) == RESET){}
            temp+=20;
            if(temp > 100)
            {
                temp = -100;
            }
			Motor_SetSpeed(temp);
		}
	}
}

int main(void)
{

	Task03();
	
	while (1)
	{
		
	}
}

 PWM.c

#include "PWM.h"


/*
PWM配置步骤:
1.开启RCC时钟,将要使用的定时器和GPIO外设时钟打开
2.配置时基单元,时钟源选择
3.配置输出比较单元,设置CCR的值,输出比较模式,极性选择,输出使能这些参数
4.配置GPIO,初始化为复用推挽输出的配置
5.运行控制,启动计数器

PWM频率: Freq = CK_PSC / (PSC + 1) / (ARR + 1)
PWM占空比: Duty = CCR / (ARR + 1)
PWM分辨率: Reso = 1 / (ARR + 1)
*/


void Task01_PWM_Init()
{
	//RCC开启
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2,ENABLE);
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
	
	//重映射将TIM2的CH1的PWM输出转到复用引脚
//	RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE);
//	GPIO_PinRemapConfig(GPIO_PartialRemap1_TIM2,ENABLE);
//	GPIO_PinRemapConfig(GPIO_Remap_SWJ_JTAGDisable,ENABLE);
	
	//选择内部时钟
	TIM_InternalClockConfig(TIM2);
	
	//初始化时基单元
	TIM_TimeBaseInitTypeDef My_TimeBaceInitStructure;
	My_TimeBaceInitStructure.TIM_ClockDivision = TIM_CKD_DIV1;  //选择预分配倍数
	My_TimeBaceInitStructure.TIM_CounterMode = TIM_CounterMode_Up; //选择向上计数模式
	My_TimeBaceInitStructure.TIM_Period = 100 - 1; //ARR
	My_TimeBaceInitStructure.TIM_Prescaler = 720 - 1; //PSC
	My_TimeBaceInitStructure.TIM_RepetitionCounter = 0; 
	TIM_TimeBaseInit(TIM2,&My_TimeBaceInitStructure);
	
	//配置输出比较单元
	TIM_OCInitTypeDef My_TIM_OCInitStructure;
	TIM_OCStructInit(&My_TIM_OCInitStructure);	
    My_TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;
    My_TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;
    My_TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
    My_TIM_OCInitStructure.TIM_Pulse = 30;//CCR
	TIM_OC1Init(TIM2,&My_TIM_OCInitStructure);
	
	//配置GPIO输出,A0为TIM2_CH1
	GPIO_InitTypeDef My_GPIO_InitStructure;
	My_GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0; //GPIO_Pin_15 TIM2CH1复用时使用
	My_GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;//复用推挽输出
	My_GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOA,&My_GPIO_InitStructure);
	
	//启动定时器
	TIM_Cmd(TIM2,ENABLE);
}

void Task01_PWM_SetComparel(uint16_t Compare)//输入值改变占空比
{
	TIM_SetCompare1(TIM2,Compare);
}

void Task02_PWM_Init()
{
	//开启RCC
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2,ENABLE); //开启TIM2的时钟
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE); //A1是PWM的CH2输出口
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE); //开启GPIOB的时钟,B1要接一个按键控制pwm值改变,这样就可以靠按键实现舵机转动
	
	//配置GPIO输出,A1为TIM2_CH2
	GPIO_InitTypeDef My_GPIOInitStructure;
	My_GPIOInitStructure.GPIO_Pin = GPIO_Pin_1;
	My_GPIOInitStructure.GPIO_Mode = GPIO_Mode_AF_PP;//复用推挽输出
	My_GPIOInitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOA,&My_GPIOInitStructure);
	//再配置按键的B1
	My_GPIOInitStructure.GPIO_Pin = GPIO_Pin_1;
	My_GPIOInitStructure.GPIO_Mode = GPIO_Mode_IPU;//上拉输入
	My_GPIOInitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOB,&My_GPIOInitStructure);
	
	
	//选择TIM的时钟源,选内部时钟
	TIM_InternalClockConfig(TIM2);
	
	//初始化时基单元
	TIM_TimeBaseInitTypeDef My_TimeBaceInitStructure;
	My_TimeBaceInitStructure.TIM_ClockDivision = TIM_CKD_DIV1;
	My_TimeBaceInitStructure.TIM_CounterMode = TIM_CounterMode_Up;
	My_TimeBaceInitStructure.TIM_Period = 20000 - 1;//ARR
	My_TimeBaceInitStructure.TIM_Prescaler = 72 - 1;//PSC
	My_TimeBaceInitStructure.TIM_RepetitionCounter = 30;
	TIM_TimeBaseInit(TIM2,&My_TimeBaceInitStructure);
	
	//配置输出比较单元
	TIM_OCInitTypeDef My_OCInitStructure;
	TIM_OCStructInit(&My_OCInitStructure);
	My_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;
    My_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;
    My_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
    My_OCInitStructure.TIM_Pulse = 0;//CCR   500到2500
	TIM_OC2Init(TIM2,&My_OCInitStructure);
	
	//启动定时器
	TIM_Cmd(TIM2,ENABLE);
}

void Task02_PWM_SetComparel(uint16_t Compare)//输入数值改变PWM占空比
{
	TIM_SetCompare2(TIM2,Compare);
}


void Task03_PWM_Init()
{
	//开启RCC时钟
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2,ENABLE);
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE);
	
	//配置时基单元,选择时钟源
	TIM_InternalClockConfig(TIM2);
	
	TIM_TimeBaseInitTypeDef My_TimeBaseInitStructure;
	My_TimeBaseInitStructure.TIM_ClockDivision = TIM_CKD_DIV1;
	My_TimeBaseInitStructure.TIM_CounterMode = TIM_CounterMode_Up;
	My_TimeBaseInitStructure.TIM_Period = 20000 - 1;//ARR
	My_TimeBaseInitStructure.TIM_Prescaler = 72 - 1;//PSC
	My_TimeBaseInitStructure.TIM_RepetitionCounter = 0;
	TIM_TimeBaseInit(TIM2,&My_TimeBaseInitStructure);
	
	//配置输出比较单元
	TIM_OCInitTypeDef My_TIM_OCInitStructure;
	TIM_OCStructInit(&My_TIM_OCInitStructure);
	My_TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;
    My_TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;
    My_TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
    My_TIM_OCInitStructure.TIM_Pulse = 30;//CCR
	TIM_OC3Init(TIM2,&My_TIM_OCInitStructure);
	
	//配置GPIO A4和A5分别是AIN1和AIN2  按键是B1
	//并且IO口如果不是默认功能,要使用复用功能时,也要配置 A2是TIM2的CH3
	GPIO_InitTypeDef My_GPIOInitStructure;
	My_GPIOInitStructure.GPIO_Pin = GPIO_Pin_1;
	My_GPIOInitStructure.GPIO_Mode = GPIO_Mode_IPU;
	My_GPIOInitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOB,&My_GPIOInitStructure);//配置PB1为按键,上拉输入
	
	My_GPIOInitStructure.GPIO_Pin = GPIO_Pin_4;
	My_GPIOInitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
	GPIO_Init(GPIOA,&My_GPIOInitStructure);
	
	My_GPIOInitStructure.GPIO_Pin = GPIO_Pin_5;
	My_GPIOInitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
	GPIO_Init(GPIOA,&My_GPIOInitStructure);//PA4和PA5是控制电机旋转方向的,推挽输出即可
	
	My_GPIOInitStructure.GPIO_Pin = GPIO_Pin_2;
	My_GPIOInitStructure.GPIO_Mode = GPIO_Mode_AF_PP;//设置PA2为复用推挽输出,这样就可以输出PWM了
	GPIO_Init(GPIOA,&My_GPIOInitStructure);
	
	//启动控制器
	TIM_Cmd(TIM2,ENABLE);
}

//输入改变TIM2的CH3的PWM占空比
void Task03_PWM_SetComparel(uint16_t Compare)
{
	TIM_SetCompare3(TIM2,Compare);
}

servo.c

#include "Device/Include/stm32f10x.h"   // Device header
#include "PWM.h"

void Servo_Init(void)
{
	Task02_PWM_Init();
}

//0度对于500,180度对于2500
void Servo_SetAngle(float Angle)
{
	Task02_PWM_SetComparel(Angle / 180 * 2000 + 500);
}

 motor.c

#include "motor.h"


void Motor_Init()
{
    //初始化AIN1和AIN2两个引脚,控制正反转
    RCC_APB2PeriphClockCmd(RCC_APBPeriph_AIN,ENABLE);
    
    GPIO_InitTypeDef My_GPIO_InitStructure;
    My_GPIO_InitStructure.GPIO_Pin = AIN1 | AIN2;
    My_GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
    My_GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(AIN1_Port,&My_GPIO_InitStructure);
    
    //默认将电机锁住,防止乱转
    GPIO_ResetBits(AIN1_Port,AIN1);
    GPIO_ResetBits(AIN1_Port,AIN2);
}

void Motor_SetSpeed(int8_t Speed)
{
    if(Speed > 0)//正转
    {
        GPIO_SetBits(AIN1_Port,AIN1);
        GPIO_ResetBits(AIN1_Port,AIN2);
        Task03_PWM_SetComparel(Speed);
    }
    
    if(Speed < 0)//反转
    {
         GPIO_ResetBits(AIN1_Port,AIN1);
        GPIO_SetBits(AIN1_Port,AIN2);
        Task03_PWM_SetComparel(-Speed);
    }
}

6-5 TIM输入捕获

高级定时器和基本定时器有输入捕获通道,但基本定时器没有。 

PWMI模式是专门测量输入的频率和占空比的。

TIM输入捕获也可配置为主从触发模式,从而实现硬件全自动测量。

测频率就是测量一秒钟内有几个周期,测频法适用于测量高频率,测周法适用于测低频率,频率是高还是低就看中介频率。

配置输入捕获的步骤:

1.RCC开启时钟,把GPIO和TIM的时钟打开

2.GPIO初始化,将GPIO配置成输入模式,上拉输入或浮空输入

3.配置时基单元,让CNT计数器在内部时钟的驱动下自增运行

4.配置输入捕获单元,包括滤波器、极性、直连通道还是交叉通道,分频器这些参数

5.选择从模式的触发源,这里选择TI1FP1

6.选择触发后执行的操作,执行Reset操作

7.调用TIM_Cmd函数,开启定时器

6-6 输入捕获模式测频率&PWMI模式测频率占空比

main.c

#include "stm32f10x.h"                  // Device header
#include "delay.h"
#include "task01.h"
#include "task02.h"
#include "OLED.h"

//任务1 输入捕获模式测频率
//PA0输出PWM信号,用PA6输入捕获来测量信号
//PA0是TIM2的CH1   PA6是TIM3的CH1
void Task01()
{
    OLED_Init();
    Task01_Init();
    
    OLED_ShowString(1,1,"Freq:00000Hz");
    
    Task01_PWM_SetPrescaler(720 - 1); //Freq = 72M / (PSC + 1) / 100
    Task01_PWM_SetComparel(50); //Duty = CCR / 100
    while(1)
    {
        OLED_ShowNum(1,6,Task01_IC_GetFreq(),5);
        
    }
        
}

//任务2 PWMI模数测频率占空比
void Task02()
{
    OLED_Init();
    Task02_Init();
    
    OLED_ShowString(1,1,"Freq:00000Hz");
    OLED_ShowString(2,1,"Duty:00%");
    
    Task01_PWM_SetPrescaler(7200 - 1); //Freq = 72M / (PSC + 1) / 100
    Task01_PWM_SetComparel(50); //Duty = CCR / 100
    while(1)
    {
        OLED_ShowNum(1,6,Task02_IC_GetFreq(),5);
        OLED_ShowNum(2,6,Task02_IC_GetDuty(),2);
       
    }
        
}


int main(void)
{
//    Task02();
	while (1)
	{
		
	}
}

 task01.c

#include "task01.h"

//PA0和PA6
void Task01_Init()
{
    //初始化时钟
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE);
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2,ENABLE);
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3,ENABLE);
    
    //选择内部时钟
    TIM_InternalClockConfig(TIM2);
    TIM_InternalClockConfig(TIM3);
    
    //配置TIM2时基单元
    TIM_TimeBaseInitTypeDef My_TIM_TimeBaseInitStructure;
    My_TIM_TimeBaseInitStructure.TIM_ClockDivision = TIM_CKD_DIV1;
    My_TIM_TimeBaseInitStructure.TIM_CounterMode = TIM_CounterMode_Up;
    My_TIM_TimeBaseInitStructure.TIM_Period = 100 - 1;//ARR
    My_TIM_TimeBaseInitStructure.TIM_Prescaler = 720 - 1;//PSC
    My_TIM_TimeBaseInitStructure.TIM_RepetitionCounter = 0;
    TIM_TimeBaseInit(TIM2,&My_TIM_TimeBaseInitStructure);//TIM2的CH1作为PWM输出
    
    //配置PA0io口作为PWM输出
    GPIO_InitTypeDef My_GPIOInitStructure;
    My_GPIOInitStructure.GPIO_Pin = GPIO_Pin_0;
    My_GPIOInitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
    My_GPIOInitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(GPIOA,&My_GPIOInitStructure);
    
    //设置输出比较单元
    TIM_OCInitTypeDef My_TIM_OCInitStructure;
    TIM_OCStructInit(&My_TIM_OCInitStructure);
    My_TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;//输出模式选择
    My_TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;//极性选择
    My_TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;//使能
    My_TIM_OCInitStructure.TIM_Pulse = 20;//RCC
    TIM_OC1Init(TIM2,&My_TIM_OCInitStructure);
    
    //启动定时器TIM2
    TIM_Cmd(TIM2,ENABLE);
    
    //配置TIM3时基单元
    My_TIM_TimeBaseInitStructure.TIM_ClockDivision = TIM_CKD_DIV1;
    My_TIM_TimeBaseInitStructure.TIM_CounterMode = TIM_CounterMode_Up;
    My_TIM_TimeBaseInitStructure.TIM_Period = 65535 - 1;//ARR
    My_TIM_TimeBaseInitStructure.TIM_Prescaler = 72 - 1;//PSC
    My_TIM_TimeBaseInitStructure.TIM_RepetitionCounter = 0;
    TIM_TimeBaseInit(TIM3,&My_TIM_TimeBaseInitStructure);//TIM3的CH1作为输入捕获
    
    //配置TIM3输入捕获单元
    TIM_ICInitTypeDef My_TIM_InitStructure;
    My_TIM_InitStructure.TIM_Channel = TIM_Channel_1;//选择定时器通道
    My_TIM_InitStructure.TIM_ICFilter = 0xF;//滤波数值
    My_TIM_InitStructure.TIM_ICPolarity = TIM_ICPolarity_Rising;//触发模式,选上升沿触发
    My_TIM_InitStructure.TIM_ICPrescaler = TIM_ICPSC_DIV1;//预分频值
    My_TIM_InitStructure.TIM_ICSelection = TIM_ICSelection_DirectTI;//选择触发信号从哪个引脚输入
    TIM_ICInit(TIM3,&My_TIM_InitStructure);
    
    //配置PA6GPIO口为输入模式
    My_GPIOInitStructure.GPIO_Pin = GPIO_Pin_6;
    My_GPIOInitStructure.GPIO_Mode = GPIO_Mode_IPU;//上拉输入
    My_GPIOInitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(GPIOA,&My_GPIOInitStructure);
    
    //配置从模式的触发源
    TIM_SelectInputTrigger(TIM3,TIM_TS_TI1FP1);
    
    //配置从模式为Reset
    TIM_SelectSlaveMode(TIM3,TIM_SlaveMode_Reset);
    
    //启动定时器TIM3
    TIM_Cmd(TIM3,ENABLE);
}

void Task01_PWM_SetComparel(uint16_t Comparel)
{
    TIM_SetCompare1(TIM2,Comparel);
}

void Task01_PWM_SetPrescaler(uint16_t Prescaler)
{
    TIM_PrescalerConfig(TIM2,Prescaler,TIM_PSCReloadMode_Immediate);
}

uint32_t Task01_IC_GetFreq(void)
{
    return 1000000 / (TIM_GetCapture1(TIM3) + 1);//+1消除误差
}

 task02.c

#include "task02.h"

void Task02_Init()
{
    //初始化时钟
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE);
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2,ENABLE);
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3,ENABLE);
    
    //选择内部时钟
    TIM_InternalClockConfig(TIM2);
    TIM_InternalClockConfig(TIM3);
    
    //配置TIM2时基单元
    TIM_TimeBaseInitTypeDef My_TIM_TimeBaseInitStructure;
    My_TIM_TimeBaseInitStructure.TIM_ClockDivision = TIM_CKD_DIV1;
    My_TIM_TimeBaseInitStructure.TIM_CounterMode = TIM_CounterMode_Up;
    My_TIM_TimeBaseInitStructure.TIM_Period = 100 - 1;//ARR
    My_TIM_TimeBaseInitStructure.TIM_Prescaler = 720 - 1;//PSC
    My_TIM_TimeBaseInitStructure.TIM_RepetitionCounter = 0;
    TIM_TimeBaseInit(TIM2,&My_TIM_TimeBaseInitStructure);//TIM2的CH1作为PWM输出
    
    //配置PA0io口作为PWM输出
    GPIO_InitTypeDef My_GPIOInitStructure;
    My_GPIOInitStructure.GPIO_Pin = GPIO_Pin_0;
    My_GPIOInitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
    My_GPIOInitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(GPIOA,&My_GPIOInitStructure);
    
    //设置输出比较单元
    TIM_OCInitTypeDef My_TIM_OCInitStructure;
    TIM_OCStructInit(&My_TIM_OCInitStructure);
    My_TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;//输出模式选择
    My_TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;//极性选择
    My_TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;//使能
    My_TIM_OCInitStructure.TIM_Pulse = 20;//RCC
    TIM_OC1Init(TIM2,&My_TIM_OCInitStructure);
    
    //启动定时器TIM2
    TIM_Cmd(TIM2,ENABLE);
    
    //配置TIM3时基单元
    My_TIM_TimeBaseInitStructure.TIM_ClockDivision = TIM_CKD_DIV1;
    My_TIM_TimeBaseInitStructure.TIM_CounterMode = TIM_CounterMode_Up;
    My_TIM_TimeBaseInitStructure.TIM_Period = 65535 - 1;//ARR
    My_TIM_TimeBaseInitStructure.TIM_Prescaler = 72 - 1;//PSC
    My_TIM_TimeBaseInitStructure.TIM_RepetitionCounter = 0;
    TIM_TimeBaseInit(TIM3,&My_TIM_TimeBaseInitStructure);//TIM3的CH1作为输入捕获
    
    //配置TIM3输入捕获单元
    TIM_ICInitTypeDef My_TIM_InitStructure;
    My_TIM_InitStructure.TIM_Channel = TIM_Channel_1;//选择定时器通道
    My_TIM_InitStructure.TIM_ICFilter = 0xF;//滤波数值
    My_TIM_InitStructure.TIM_ICPolarity = TIM_ICPolarity_Rising;//触发模式,选上升沿触发
    My_TIM_InitStructure.TIM_ICPrescaler = TIM_ICPSC_DIV1;//预分频值
    My_TIM_InitStructure.TIM_ICSelection = TIM_ICSelection_DirectTI;//选择触发信号从哪个引脚输入
    TIM_ICInit(TIM3,&My_TIM_InitStructure);
    
    //裴PWMI
    TIM_PWMIConfig(TIM3,&My_TIM_InitStructure);
    
    //配置PA6GPIO口为输入模式
    My_GPIOInitStructure.GPIO_Pin = GPIO_Pin_6;
    My_GPIOInitStructure.GPIO_Mode = GPIO_Mode_IPU;//上拉输入
    My_GPIOInitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(GPIOA,&My_GPIOInitStructure);
    
    //配置从模式的触发源
    TIM_SelectInputTrigger(TIM3,TIM_TS_TI1FP1);
    
    //配置从模式为Reset
    TIM_SelectSlaveMode(TIM3,TIM_SlaveMode_Reset);
    
    //启动定时器TIM3
    TIM_Cmd(TIM3,ENABLE);
}

void Task02_PWM_SetComparel(uint16_t Comparel)
{
    TIM_SetCompare1(TIM2,Comparel);
}

void Task02_PWM_SetPrescaler(uint16_t Prescaler)
{
    TIM_PrescalerConfig(TIM2,Prescaler,TIM_PSCReloadMode_Immediate);
}

uint32_t Task02_IC_GetFreq(void)
{
    return 1000000 / (TIM_GetCapture1(TIM3) + 1);//+1消除误差
}

uint32_t Task02_IC_GetDuty(void)
{
    return (TIM_GetCapture2(TIM3) + 1) * 100 / (TIM_GetCapture1(TIM3) + 1);
}


6-7 TIM编码器接口

配置编码器测量步骤:

1.RCC开启时钟,开启GPIO和定时器时钟

2.配置相关GPIO,将CH1和CH2的IO口设置为输入模式

3.配置时基单元,预分频器一般不分频,自动重装一般给最大65535

4.配置输入捕获单元,只需配置通道、滤波器和极性即可,其他参数用不上

5.配置编码器接口模式,直接调用库函数

6.调用TIM_Cmd启动定时器


6-8 编码器接口测速

main.c

#include "stm32f10x.h"                  // Device header
#include "encoder.h"
#include "OLED_I2C.h"
#include "delay.h"
#include <stdio.h>
//编码器接口测速
//PA6接A相  PA7接B相  分别是TIM3的CH1  和  TIM3的CH2 

uint16_t temp = 0;

void DisplayIntegerValue(int value)
{
    char str[16]; // 用于存储转换后的字符串
    snprintf(str, sizeof(str), "temp: %d", value); // 将整数转换为字符串
    OLED_ShowStr(1, 1, (unsigned char *)str, 1); // 在OLED上显示字符串
}

int main(void)
{
    DelayInit();
    I2C_Configuration();
    OLED_Init();
    
    Encoder_Init();
    OLED_Fill(0xFF);
    DelayS(2);

    OLED_CLS();
	while (1)
	{
      temp = Encoder_Get();
      DisplayIntegerValue(temp);
        DelayS(1);
	}
}

 encoder.c

#include "encoder.h"

void Encoder_Init()
{
    //开启RCC时钟
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3,ENABLE);
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
    
    //配置GPIO,CH1和CH2都配成输入模式  PA6   PA7
    GPIO_InitTypeDef My_GPIO_InitStructure;
    My_GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7;
    My_GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
    My_GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(GPIOA,&My_GPIO_InitStructure);
    
    //配置时基单元
    TIM_TimeBaseInitTypeDef My_TIM_TimeBaseInitStructure;
    My_TIM_TimeBaseInitStructure.TIM_ClockDivision = TIM_CKD_DIV1;
    My_TIM_TimeBaseInitStructure.TIM_CounterMode = TIM_CounterMode_Up;
    My_TIM_TimeBaseInitStructure.TIM_Period = 65535 - 1;//ARR
    My_TIM_TimeBaseInitStructure.TIM_Prescaler = 1-1;//PSC
    My_TIM_TimeBaseInitStructure.TIM_RepetitionCounter = 0;
    TIM_TimeBaseInit(TIM3,&My_TIM_TimeBaseInitStructure);
    
    //配置输入捕获单元
    TIM_ICInitTypeDef My_TIM_ICInitStructure;
    TIM_ICStructInit(&My_TIM_ICInitStructure);
    My_TIM_ICInitStructure.TIM_Channel = TIM_Channel_1; 
    My_TIM_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_Rising;
    My_TIM_ICInitStructure.TIM_ICFilter = 0xF;
    TIM_ICInit(TIM3,&My_TIM_ICInitStructure);
    My_TIM_ICInitStructure.TIM_Channel = TIM_Channel_2; 
    My_TIM_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_Rising;
    My_TIM_ICInitStructure.TIM_ICFilter = 0xF;
    TIM_ICInit(TIM3,&My_TIM_ICInitStructure);
    
    //配置编码器接口
    TIM_EncoderInterfaceConfig(TIM3,TIM_EncoderMode_TI12,TIM_ICPolarity_Rising,TIM_ICPolarity_Rising);
    
    //启动定时器
    TIM_Cmd(TIM2,ENABLE);
}

int16_t Encoder_Get(void)
{
    int16_t temp;
    temp = TIM_GetCounter(TIM3);
    TIM_SetCounter(TIM3,0);
    return temp;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值