STM32F103C8T6驱动舵机SG90 配置定时器TIM2,TIM3,TIM4的多种重映射模式下的不同IO口

2023-11-18

STM32F103C8T6驱动舵机SG90 配置定时器TIM2,TIM3,TIM4的多种重映射模式下的不同IO口

1.使用到的工具介绍
2.整个简单介绍
3.程序的介绍
1.使用到的工具介绍:
keil5,烧写软件FlyMcu.exe,硬件为STM32F103C8T6板,SG90舵机还有按键。

2.整个简单介绍:
通过对舵机的了解我这里使用的是sg90舵机可旋转180度,使用的芯片是stm32f103c8t6。在配置2个按键来进行舵机角度加减,通过加减来改变舵机的角度变化;

在这里插入图片描述

SG90舵机红线 VCC线(接5v)
SG90舵机棕线 GND线
SG90舵机黄线 控制信号线

在这里插入图片描述

需要通过PWM来配置出各种角度的占空比,STM32F103的PWM可配置的IO口如下图,对TIM2,TIM3,TIM4都进行了配置也对各种重映射情况下的IO口配置。
简单方便使用时调用即可。再配置2个按键来改变TIM_SetCompare4(TIM3, i);中的i变量,就可以改变舵机的角度;i变量的取值范围在175-195之间变化对应0-180角度的范围。

TIM_SetCompare4(TIM3, i);//改变i的变量就可以改变舵机角度

在这里插入图片描述
(1)根据STM32F103C8T6型号对TIM2的配置
①没有重映射 可以配置的IO口有CH1 PA0,CH2 PA1,CH3 PA2,CH4 PA3;
②部分重映射1 可以配置的IO口有CH1 PA15,CH2 PB3,CH3 PA2,CH4 PA3;
TIM2的部分重映射1使用到了PA15和PB3所以需要禁用掉JTAG功能,代码里加入

GPIO_PinRemapConfig(GPIO_Remap_SWJ_JTAGDisable,
ENABLE);//这条是关闭PB3,PB4,PA15做普通IO

③部分重映射2 可以配置的IO口有CH1 PA0,CH2 PA1,CH3 PB10,CH4 PB11;
④完全重映射 可以配置的IO口有CH1 PA15,CH2 PB3,CH3 PB10,CH4 PB11;
TIM2的完全重映射使用到了PA15和PB3所以需要禁用掉JTAG功能,代码里加入

GPIO_PinRemapConfig(GPIO_Remap_SWJ_JTAGDisable,
ENABLE);//这条是关闭PB3,PB4,PA15做普通IO

(2)根据STM32F103C8T6型号对TIM3的配置
①没有重映射 可以配置的IO口有CH1 PA6,CH2 PA7,CH3 PB0,CH4 PB1;
②部分重映射 可以配置的IO口有CH1 PB4,CH2 PB5,CH3 PB0,CH4 PB1;
TIM3的部分重映射使用到了PB4所以需要禁用掉JTAG功能,代码里加入

GPIO_PinRemapConfig(GPIO_Remap_SWJ_NoJTRST, ENABLE);//单独关闭PB4的JTAG功能

(3)根据STM32F103C8T6型号对TIM4的配置
①TIM4_REMAP = 0 没有重映射 可以配置的IO口有CH1 PB6,CH2 PB7,CH3 PB8,CH4 PB9;

3.程序的介绍
SG90.H中的代码

#ifndef __SG90_H
#define __SG90_H	 
#include "sys.h"
//这里使用到的是stm32f103c8t6  有些io口配置不到
//这里只配置了普通定时器 TIM2 TIM3 TIM4


//SG90舵机驱动 0-180 角度
//通过变量来改变i这个数值就能改变舵机的角度
//这里的i的变量为175-195之中间就是0-180度的角度了
//	TIM_SetCompare1(TIM3, i);
//	TIM_SetCompare2(TIM3, i);	
//	TIM_SetCompare3(TIM3, i);
//	TIM_SetCompare4(TIM3, i);
//  在key.h中有使用到
//  通过两按键实现加和键这个变量,进行角度的变化


//mode 0 1 2 3 有这4中模式
//0 没有重映射   可以配置的IO口有CH1 PA0,CH2 PA1,CH3 PA2,CH4 PA3;
//1 部分重映射1  可以配置的IO口有CH1 PA15,CH2 PB3,CH3 PA2,CH4 PA3;
//2 部分重映射2  可以配置的IO口有CH1 PA0,CH2 PA1,CH3 PB10,CH4 PB11;
//3 完全重映射   可以配置的IO口有CH1 PA15,CH2 PB3,CH3 PB10,CH4 PB11;
void TIM2_PwmSG90_Init(u8 mode);
//mode 0 1 2 有这3中模式模式
//0 没有重映射  可以配置的IO口有CH1 PA6,CH2 PA7,CH3 PB0,CH4 PB1;
//1 部分重映射  可以配置的IO口有CH1 PB4,CH2 PB5,CH3 PB0,CH4 PB1;
//2 完全重映射  在stm32f103c8t6上没有这些pin口所以这里没有配置 可以配置的IO口有CH1 PC6,CH2 PC7,CH3 PC8 ,CH4 PC9;
void TIM3_PwmSG90_Init(u8 mode);

//mode 0 1 有这2中模式模式
//0 TIM4_REMAP = 0 没有重映射  可以配置的IO口有CH1 PB6,CH2 PB7,CH3 PB8,CH4 PB9;
//1 TIM4_REMAP = 1 部分重映射  在stm32f103c8t6上没有这些pin口所以这里没有配置 可以配置的IO口有CH1 PD12,CH2 PD13,CH3 PD14,CH4 PD15;
void TIM4_PwmSG90_Init(u8 mode);





#endif

SG90.c中的代码

#include "SG90.H"
//这里我使用的是stm32f103c8t6



//mode 0 1 2 3 有这4中模式
//0 没有重映射   可以配置的IO口有CH1 PA0,CH2 PA1,CH3 PA2,CH4 PA3;
//1 部分重映射1  可以配置的IO口有CH1 PA15,CH2 PB3,CH3 PA2,CH4 PA3;
//2 部分重映射2  可以配置的IO口有CH1 PA0,CH2 PA1,CH3 PB10,CH4 PB11;
//3 完全重映射   可以配置的IO口有CH1 PA15,CH2 PB3,CH3 PB10,CH4 PB11;
void TIM2_PwmSG90_Init(u8 mode)
{
	GPIO_InitTypeDef PWM_Initstructure;  //定义GPIO端口结构体
	TIM_TimeBaseInitTypeDef TIM_Initstructure;	//定义TIM结构体
	TIM_OCInitTypeDef OC_Initstructure;	//定义输出比较结构体
	
	if(mode==0)
	{
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_AFIO, ENABLE); //打开端口和复用时钟	
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);	//打开定时器的时钟
  		
	//这里设置的是没有重映射的设置所以可以配置的IO口有CH1 PA0,CH2 PA1,CH3 PA2,CH4 PA3;			
	PWM_Initstructure.GPIO_Pin = GPIO_Pin_0|GPIO_Pin_1|GPIO_Pin_2|GPIO_Pin_3;
	PWM_Initstructure.GPIO_Mode = GPIO_Mode_AF_PP;
	PWM_Initstructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOA, &PWM_Initstructure);		
	}
	
	
	if(mode==1)
	{	
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB |RCC_APB2Periph_GPIOA| RCC_APB2Periph_AFIO, ENABLE); //打开端口和复用时钟	
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);	//打开定时器的时钟
  
	GPIO_PinRemapConfig(GPIO_PartialRemap1_TIM2, ENABLE);//设置端口重映射:
	//这里设置的是部分重映射1 可以配置的IO口有CH1 PA15,CH2 PB3,CH3 PA2,CH4 PA3;
	
//  //	GPIO_PinRemapConfig(GPIO_Remap_SWJ_Disable, ENABLE);; //使用PA15,PB3所需要关掉的下载口需要禁用JTAG才能使用 这条是关闭5个IO口
  GPIO_PinRemapConfig(GPIO_Remap_SWJ_JTAGDisable, ENABLE);//这条是关闭PB3,PB4,PA15做普通IO
   
  //GPIO_Remap_SWJ_Disable 关闭所有跟JTAG有关的引脚
	
	PWM_Initstructure.GPIO_Pin = GPIO_Pin_15|GPIO_Pin_2|GPIO_Pin_3;
	PWM_Initstructure.GPIO_Mode = GPIO_Mode_AF_PP;
	PWM_Initstructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOA, &PWM_Initstructure);
		
	PWM_Initstructure.GPIO_Pin = GPIO_Pin_3;
	PWM_Initstructure.GPIO_Mode = GPIO_Mode_AF_PP;
	PWM_Initstructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOB, &PWM_Initstructure);
		
	}
	if(mode==2)
	{
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB |RCC_APB2Periph_GPIOA| RCC_APB2Periph_AFIO, ENABLE); //打开端口和复用时钟	
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);	//打开定时器的时钟
  
	GPIO_PinRemapConfig(GPIO_PartialRemap2_TIM2, ENABLE);//设置端口重映射:
	//这里设置的是部分重映射2 可以配置的IO口有CH1 PA0,CH2 PA1,CH3 PB10,CH4 PB11;
	
	PWM_Initstructure.GPIO_Pin = GPIO_Pin_0|GPIO_Pin_1;
	PWM_Initstructure.GPIO_Mode = GPIO_Mode_AF_PP;
	PWM_Initstructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOA, &PWM_Initstructure);
		
	PWM_Initstructure.GPIO_Pin = GPIO_Pin_10|GPIO_Pin_11;
	PWM_Initstructure.GPIO_Mode = GPIO_Mode_AF_PP;
	PWM_Initstructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOB, &PWM_Initstructure);	
	}
	if(mode==3)
	{
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB |RCC_APB2Periph_GPIOA| RCC_APB2Periph_AFIO, ENABLE); //打开端口和复用时钟	
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);	//打开定时器的时钟
  
	GPIO_PinRemapConfig(GPIO_FullRemap_TIM2, ENABLE);//设置端口重映射:
	//这里设置的是部分重映射2 可以配置的IO口有CH1 PA15,CH2 PB3,CH3 PB10,CH4 PB11
	
//  //	GPIO_PinRemapConfig(GPIO_Remap_SWJ_Disable, ENABLE);; //使用PA15,PB3所需要关掉的下载口需要禁用JTAG才能使用 这条是关闭5个IO口
  GPIO_PinRemapConfig(GPIO_Remap_SWJ_JTAGDisable, ENABLE);//这条是关闭PB3,PB4,PA15做普通IO
   
  //GPIO_Remap_SWJ_Disable 关闭所有跟JTAG有关的引脚
	
	PWM_Initstructure.GPIO_Pin = GPIO_Pin_15;
	PWM_Initstructure.GPIO_Mode = GPIO_Mode_AF_PP;
	PWM_Initstructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOA, &PWM_Initstructure);
		
	PWM_Initstructure.GPIO_Pin = GPIO_Pin_3|GPIO_Pin_10|GPIO_Pin_11;
	PWM_Initstructure.GPIO_Mode = GPIO_Mode_AF_PP;
	PWM_Initstructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOB, &PWM_Initstructure);		
	}	
	

//下面的配置都一样
	
	TIM_Initstructure.TIM_ClockDivision = TIM_CKD_DIV1;   //不分频
	TIM_Initstructure.TIM_CounterMode = TIM_CounterMode_Up;  //向上计数
	TIM_Initstructure.TIM_Period = 200-1;
	TIM_Initstructure.TIM_Prescaler = 7200-1;
	TIM_TimeBaseInit(TIM2, &TIM_Initstructure);
	TIM_Cmd(TIM2, ENABLE);	//使能时钟

	OC_Initstructure.TIM_OCMode = TIM_OCMode_PWM1;	//采用PWM1模式
	OC_Initstructure.TIM_OutputState = TIM_OutputState_Enable;  //配置输出使能OR使能
	OC_Initstructure.TIM_OCPolarity = TIM_OCPolarity_Low; //比较输出极性
	TIM_OC1Init(TIM2, &OC_Initstructure);		//输出比较初始化
	TIM_OC1PreloadConfig(TIM2, TIM_OCPreload_Enable);		//启用CCR2上的TIM3外围预加载寄存器。
	
	OC_Initstructure.TIM_OCMode = TIM_OCMode_PWM1;	//采用PWM1模式
	OC_Initstructure.TIM_OutputState = TIM_OutputState_Enable;  //配置输出使能OR使能
	OC_Initstructure.TIM_OCPolarity = TIM_OCPolarity_Low; //比较输出极性
	TIM_OC2Init(TIM2, &OC_Initstructure);		//输出比较初始化
	TIM_OC2PreloadConfig(TIM2, TIM_OCPreload_Enable);		//启用CCR2上的TIM3外围预加载寄存器。

	OC_Initstructure.TIM_OCMode = TIM_OCMode_PWM1;	//采用PWM1模式
	OC_Initstructure.TIM_OutputState = TIM_OutputState_Enable;  //配置输出使能OR使能
	OC_Initstructure.TIM_OCPolarity = TIM_OCPolarity_Low; //比较输出极性
	TIM_OC3Init(TIM2, &OC_Initstructure);		//输出比较初始化
	TIM_OC3PreloadConfig(TIM2, TIM_OCPreload_Enable);		//启用CCR2上的TIM3外围预加载寄存器。
	
	OC_Initstructure.TIM_OCMode = TIM_OCMode_PWM1;	//采用PWM1模式
	OC_Initstructure.TIM_OutputState = TIM_OutputState_Enable;  //配置输出使能OR使能
	OC_Initstructure.TIM_OCPolarity = TIM_OCPolarity_Low; //比较输出极性
	TIM_OC4Init(TIM2, &OC_Initstructure);		//输出比较初始化
	TIM_OC4PreloadConfig(TIM2, TIM_OCPreload_Enable);		//启用CCR2上的TIM3外围预加载寄存器。
}



//mode 0 1 2 有这3中模式
//0 没有重映射  可以配置的IO口有CH1 PA6,CH2 PA7,CH3 PB0,CH4 PB1;
//1 部分重映射  可以配置的IO口有CH1 PB4,CH2 PB5,CH3 PB0,CH4 PB1;
//2 完全重映射  在stm32f103c8t6上没有这些pin口所以这里没有配置 可以配置的IO口有CH1 PC6,CH2 PC7,CH3 PC8 ,CH4 PC9;
void TIM3_PwmSG90_Init(u8 mode)
{
	GPIO_InitTypeDef PWM_Initstructure;  //定义GPIO端口结构体
	TIM_TimeBaseInitTypeDef TIM_Initstructure;	//定义TIM结构体
	TIM_OCInitTypeDef OC_Initstructure;	//定义输出比较结构体
	
	if(mode==0)
	{
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB|RCC_APB2Periph_GPIOA| RCC_APB2Periph_AFIO, ENABLE); //打开端口和复用时钟	
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);	//打开定时器的时钟
  
	//这里设置的是没有重映射的设置所以可以配置的IO口有CH1 PA6,CH2 PA7,CH3 PB0,CH4 PB1;			
	PWM_Initstructure.GPIO_Pin = GPIO_Pin_6|GPIO_Pin_7;
	PWM_Initstructure.GPIO_Mode = GPIO_Mode_AF_PP;
	PWM_Initstructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOA, &PWM_Initstructure);		
		
	PWM_Initstructure.GPIO_Pin = GPIO_Pin_0|GPIO_Pin_1;
	PWM_Initstructure.GPIO_Mode = GPIO_Mode_AF_PP;
	PWM_Initstructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOB, &PWM_Initstructure);
	}
	
	if(mode==1)
	{
	
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB | RCC_APB2Periph_AFIO, ENABLE); //打开端口和复用时钟	
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);	//打开定时器的时钟
  
	GPIO_PinRemapConfig(GPIO_PartialRemap_TIM3, ENABLE);//设置端口重映射:
	//这里设置的是部分重映射可以配置的IO口有CH1 PB4,CH2 PB5,CH3 PB0 ,CH4 PB1; 
	
 	//GPIO_PinRemapConfig(GPIO_Remap_SWJ_Disable,ENABLE);//使用PB4所需要关掉的下载口需要禁用JTAG才能使用
	//GPIO_Remap_SWJ_Disable 关闭所有跟JTAG有关的引脚
	GPIO_PinRemapConfig(GPIO_Remap_SWJ_NoJTRST, ENABLE);//单独关闭PB4的JTAG功能 
	
	PWM_Initstructure.GPIO_Pin = GPIO_Pin_0|GPIO_Pin_1|GPIO_Pin_4|GPIO_Pin_5;
	PWM_Initstructure.GPIO_Mode = GPIO_Mode_AF_PP;
	PWM_Initstructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOB, &PWM_Initstructure);
  }
	
//下面的配置都一样
	TIM_Initstructure.TIM_ClockDivision = TIM_CKD_DIV1;   //不分频
	TIM_Initstructure.TIM_CounterMode = TIM_CounterMode_Up;  //向上计数
	TIM_Initstructure.TIM_Period = 200-1;
	TIM_Initstructure.TIM_Prescaler = 7200-1;
	TIM_TimeBaseInit(TIM3, &TIM_Initstructure);
	TIM_Cmd(TIM3, ENABLE);	//使能时钟

	OC_Initstructure.TIM_OCMode = TIM_OCMode_PWM1;	//采用PWM1模式
	OC_Initstructure.TIM_OutputState = TIM_OutputState_Enable;  //配置输出使能OR使能
	OC_Initstructure.TIM_OCPolarity = TIM_OCPolarity_Low; //比较输出极性
	TIM_OC1Init(TIM3, &OC_Initstructure);		//输出比较初始化
	TIM_OC1PreloadConfig(TIM3, TIM_OCPreload_Enable);		//启用CCR2上的TIM3外围预加载寄存器。
	
	OC_Initstructure.TIM_OCMode = TIM_OCMode_PWM1;	//采用PWM1模式
	OC_Initstructure.TIM_OutputState = TIM_OutputState_Enable;  //配置输出使能OR使能
	OC_Initstructure.TIM_OCPolarity = TIM_OCPolarity_Low; //比较输出极性
	TIM_OC2Init(TIM3, &OC_Initstructure);		//输出比较初始化
	TIM_OC2PreloadConfig(TIM3, TIM_OCPreload_Enable);		//启用CCR2上的TIM3外围预加载寄存器。

	OC_Initstructure.TIM_OCMode = TIM_OCMode_PWM1;	//采用PWM1模式
	OC_Initstructure.TIM_OutputState = TIM_OutputState_Enable;  //配置输出使能OR使能
	OC_Initstructure.TIM_OCPolarity = TIM_OCPolarity_Low; //比较输出极性
	TIM_OC3Init(TIM3, &OC_Initstructure);		//输出比较初始化
	TIM_OC3PreloadConfig(TIM3, TIM_OCPreload_Enable);		//启用CCR2上的TIM3外围预加载寄存器。
	
	OC_Initstructure.TIM_OCMode = TIM_OCMode_PWM1;	//采用PWM1模式
	OC_Initstructure.TIM_OutputState = TIM_OutputState_Enable;  //配置输出使能OR使能
	OC_Initstructure.TIM_OCPolarity = TIM_OCPolarity_Low; //比较输出极性
	TIM_OC4Init(TIM3, &OC_Initstructure);		//输出比较初始化
	TIM_OC4PreloadConfig(TIM3, TIM_OCPreload_Enable);		//启用CCR2上的TIM3外围预加载寄存器。
}




//mode 0 1 有这2中模式
//0 TIM4_REMAP = 0 没有重映射  可以配置的IO口有CH1 PB6,CH2 PB7,CH3 PB8,CH4 PB9;
//1 TIM4_REMAP = 1 部分重映射  在stm32f103c8t6上没有这些pin口所以这里没有配置 可以配置的IO口有CH1 PD12,CH2 PD13,CH3 PD14,CH4 PD15;
void TIM4_PwmSG90_Init(u8 mode)
{
	GPIO_InitTypeDef PWM_Initstructure;  //定义GPIO端口结构体
	TIM_TimeBaseInitTypeDef TIM_Initstructure;	//定义TIM结构体
	TIM_OCInitTypeDef OC_Initstructure;	//定义输出比较结构体
	
	if(mode==0)
	{
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB|RCC_APB2Periph_AFIO, ENABLE); //打开端口和复用时钟	
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4, ENABLE);	//打开定时器的时钟
  		
	//这里设置的是没有重映射的设置所以可以配置的IO口有CH1 PB6,CH2 PB7,CH3 PB8,CH4 PB9;			
	PWM_Initstructure.GPIO_Pin = GPIO_Pin_6|GPIO_Pin_7|GPIO_Pin_8|GPIO_Pin_9;
	PWM_Initstructure.GPIO_Mode = GPIO_Mode_AF_PP;
	PWM_Initstructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOB, &PWM_Initstructure);		
		
	}

//下面的配置都一样
	TIM_Initstructure.TIM_ClockDivision = TIM_CKD_DIV1;   //不分频
	TIM_Initstructure.TIM_CounterMode = TIM_CounterMode_Up;  //向上计数
	TIM_Initstructure.TIM_Period = 200-1;
	TIM_Initstructure.TIM_Prescaler = 7200-1;
	TIM_TimeBaseInit(TIM4, &TIM_Initstructure);
	TIM_Cmd(TIM4, ENABLE);	//使能时钟

	OC_Initstructure.TIM_OCMode = TIM_OCMode_PWM1;	//采用PWM1模式
	OC_Initstructure.TIM_OutputState = TIM_OutputState_Enable;  //配置输出使能OR使能
	OC_Initstructure.TIM_OCPolarity = TIM_OCPolarity_Low; //比较输出极性
	TIM_OC1Init(TIM4, &OC_Initstructure);		//输出比较初始化
	TIM_OC1PreloadConfig(TIM4, TIM_OCPreload_Enable);		//启用CCR2上的TIM3外围预加载寄存器。
	
	OC_Initstructure.TIM_OCMode = TIM_OCMode_PWM1;	//采用PWM1模式
	OC_Initstructure.TIM_OutputState = TIM_OutputState_Enable;  //配置输出使能OR使能
	OC_Initstructure.TIM_OCPolarity = TIM_OCPolarity_Low; //比较输出极性
	TIM_OC2Init(TIM4, &OC_Initstructure);		//输出比较初始化
	TIM_OC2PreloadConfig(TIM4, TIM_OCPreload_Enable);		//启用CCR2上的TIM3外围预加载寄存器。

	OC_Initstructure.TIM_OCMode = TIM_OCMode_PWM1;	//采用PWM1模式
	OC_Initstructure.TIM_OutputState = TIM_OutputState_Enable;  //配置输出使能OR使能
	OC_Initstructure.TIM_OCPolarity = TIM_OCPolarity_Low; //比较输出极性
	TIM_OC3Init(TIM4, &OC_Initstructure);		//输出比较初始化
	TIM_OC3PreloadConfig(TIM4, TIM_OCPreload_Enable);		//启用CCR2上的TIM3外围预加载寄存器。
	
	OC_Initstructure.TIM_OCMode = TIM_OCMode_PWM1;	//采用PWM1模式
	OC_Initstructure.TIM_OutputState = TIM_OutputState_Enable;  //配置输出使能OR使能
	OC_Initstructure.TIM_OCPolarity = TIM_OCPolarity_Low; //比较输出极性
	TIM_OC4Init(TIM4, &OC_Initstructure);		//输出比较初始化
	TIM_OC4PreloadConfig(TIM4, TIM_OCPreload_Enable);		//启用CCR2上的TIM3外围预加载寄存器。
}

key.h中的代码

#ifndef __KEY_H
#define __KEY_H	 
#include "sys.h"
  	 
#define KEY0 PAin(0) 
#define KEY1 PAin(7)	
void KEY_Init(void);//IO初始
u8 KEY_OUT(void);
void TIM3_PWMSG90_RUN(void);
void TIM4_PWMSG90_RUN(void);
void TIM2_PWMSG90_RUN(void);


#endif

key.c中的代码

#include "stm32f10x.h"
#include "key.h"
#include "sys.h" 
#include "delay.h"
  

u8 KEY_jia_jian=195;

//按键初始化函数
void KEY_Init(void) //IO初始化
{ 
 	GPIO_InitTypeDef GPIO_InitStructure;
 
 	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);//使能PORTA,PORTE时钟

	GPIO_InitStructure.GPIO_Pin  = GPIO_Pin_0|GPIO_Pin_7;//KEY0-KEY2
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; //设置成上拉输入
 	GPIO_Init(GPIOA, &GPIO_InitStructure);//初始化GPIOE2,3,4

}



//返回KEY_jia_jian按键加减数据

u8 KEY_OUT(void)//
{
	if(KEY0==0)
	{
		if(KEY_jia_jian<196)
		{
		KEY_jia_jian++;
			return KEY_jia_jian;
		}
		if(KEY_jia_jian==196)
		{
			KEY_jia_jian=175;
			return KEY_jia_jian;
		}
	}
	if(KEY1==0)
	{
		if(KEY_jia_jian==174)
		{
			KEY_jia_jian=195;
			return KEY_jia_jian;
		}
		if(KEY_jia_jian>174)
		{
		  KEY_jia_jian--;
			return KEY_jia_jian;
		}
	}
  return KEY_jia_jian;
}



void TIM3_PWMSG90_RUN(void)
{
	u8 i;
	i=KEY_OUT();//设置一个变量来带提他
	TIM_SetCompare1(TIM3, i);
	TIM_SetCompare2(TIM3, i);	
	TIM_SetCompare3(TIM3, i);
	TIM_SetCompare4(TIM3, i);
		
}

void TIM4_PWMSG90_RUN(void)
{
	u8 i;
	i=KEY_OUT();//设置一个变量来带提他
	TIM_SetCompare1(TIM4, i);
	TIM_SetCompare2(TIM4, i);	
	TIM_SetCompare3(TIM4, i);
	TIM_SetCompare4(TIM4, i);
		
}

void TIM2_PWMSG90_RUN(void)
{
	u8 i;
	i=KEY_OUT();//设置一个变量来带提他
	TIM_SetCompare1(TIM2, i);
	TIM_SetCompare2(TIM2, i);	
	TIM_SetCompare3(TIM2, i);
	TIM_SetCompare4(TIM2, i);
		
}

mian.c中的代码

#include "sys.h"
#include "delay.h"
#include "usart.h"
#include "led.h"
#include "SG90.H"
#include "key.h" 






 int main(void)
 {	
	 delay_init();	    //延时函数初始化	  
	 TIM3_PwmSG90_Init(1);//pwm函数初始化	  
	 //TIM4_PwmSG90_Init(0);
	 //TIM2_PwmSG90_Init(1);
	 KEY_Init();//按键初始化
	while(1)
	{		
		   TIM3_PWMSG90_RUN();
		  // TIM3_PWMSG90_RUN();
		   //TIM2_PWMSG90_RUN();
			 delay_ms(500);


	}
 }

以后就是全部的代码了

源码下载地址

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

STM32F103C8T6驱动舵机SG90 配置定时器TIM2,TIM3,TIM4的多种重映射模式下的不同IO口 的相关文章

  • 传指针和传引用的区别以及指针和引用的区别

    一 引用 引用的定义 引用是给另外一个变量其别名 所以引用不会分配内存空间 引用是引入了对象的一个同义词 例如 Point pt1 10 10 Point pt2 pt1 上述的代码 定义了pt2为pt1的引用 通过这样的定义 pt2和pt
  • 让生产活动更高效,物料管理场景的RPA应用

    作为制造业 供应链领域常见环节 物料管理 Material Management 通常是对企业生产经营活动所需各种物料的采购 验收 供应 保管 发放 使用等一系列计划与控制活动的总称 物料管理科学与否 将会影响到组织各职能部门间的协调 生产
  • 文件的上传与下载

    一 文件上传 文件上传程序步骤 1 如何在web页面中添加上传输入项

随机推荐

  • python数据驱动测试设计_Python+unittest+DDT实现的数据驱动测试

    前言 数据驱动测试 避免编写重复代码 数据与测试脚本分离 通过使用数据驱动测试 来验证多组数据测试场景 通常来说 多用于单元测试和接口测试 ddt介绍 Data Driven Tests DDT 即数据驱动测试 可以实现不同数据运行同一个测
  • Gcov 详解 + 内核函数覆盖率测试方法详述及产生错误解决办法

    1 gcov是什么 Gcov is GCC Coverage 是一个测试代码覆盖率的工具 是一个命令行方式的控制台程序 伴随GCC发布 配合GCC共同实现对C C 文件的语句覆盖和分支覆盖测试 与程序概要分析工具 profiling too
  • 小白也能学会的爬虫教学(超详细,每一步都配图,不怕你学不会,图文并茂,看完直呼‘爽’)

    详细且简单的爬虫简单教学 小白看了之后直呼 爬虫就这 安装pycharm 一 新建一个工程 二 安装scrapy 三 创建Scrapy工程 四 如何使用scrapy 1 新建一个begin py文件 2 编辑begin py中的内容 3 修
  • hbase MapReduce程序样例入门

    hbase MapReduce程序样例入门 1 先看一个标准的hbase作为数据读取源和输出源的样例 Configuration conf HBaseConfiguration create Job job new Job conf job
  • 定时器:Quartz框架

    文章目录 简介 简单Demo cron 规则 参考 简介 Quartz是 OpenSymphony 开源组织在 Job scheduling 领域的开源项目 是由 java 开发的一个开源的任务日程管理系统 Quartz 是一个功能丰富的开
  • 如何下载安装VS2017下载 vs2017社区版

    如何下载安装VS2017下载 vs2017社区版 https blog csdn net zyhse article details 105362609 1 下载vs2017的引导程序 官方并没有为vs2017提供离线安装包 所以我们选择在
  • 操作系统课程设计

    关于完整代码 更详细内容 实验一环境配置 请访问github仓库地址 GitHub zzering OS course design 操作系统课设 系统调用 磁盘调度算法 文件调用 进程管理 分页置换算法 进程通信 实验一 为Linux系统
  • python二元操作符是什么_python笔记—06 讲:Pyhon 之常用操作符

    本期内容详解 1 算术运算符 加 减 乘 除 幂运算 地板除 1 和 的区别 在 Python 中的除运算符与其它程序语言的不太一样 表示真正的除号 例如 1 3 0 3333333333333333 而 4 2 的值为 2 0 说明两个数
  • Flask处理前台POST过来的JSON

    POST JSON数据的JS代码 ajax url http 127 0 0 1 5000 calc type post dataType json headers Content Type application json charset
  • 数据结构——线性表(C++)

    线性表 一 线性表的定义 二 线性表的抽象数据类型 三 线性表的顺序存储 1 顺序存储定义 2 顺序存储的实现方式 四 线性表的链式存储 五 其他线性表 参考 一 线性表的定义 线性表 零个或多个数据元素的有限序列 线性表是最常用且是最简单
  • 开启防火墙脚本

    sc config MpsSvc start AUTO net start MpsSvc
  • VMware ESX与VMware ESXi区别

    VMware ESX 与 VMware ESXi 区别 现在来讲vSphere就是ESXI 只是两种叫法而已 我们来看看VMware服务器虚拟化产品的历程 Vmware 服务器虚拟化第一个产品叫ESX 该产品只有60天测试 没有官方认可的免
  • DAY18:Xss 靶场通关手册

    DAY18 Xss 靶场通关手册 常见的xss注入 lt img src x onerror alert 1 gt
  • nvidia深度学习加速库apex简单介绍

    介绍地址 https docs nvidia com deeplearning sdk mixed precision training index html 本人英文水平有限 有误请指正 使用理由 使用精度低于32位浮点的数值格式有许多好
  • 设计模式(二十二) 策略模式

    有时候对象需要按照某种策略改变行为 我们可以利用策略模式 将策略或算法提取出来 作为单独的类实现 使用策略模式 可以让具体算法和应用对象分离 方便的根据不同条件替换策略 下面举一个例子 我们有一个计算器 它会按照快和慢两种策略来计算结果 所
  • 解决Linux普通用户使用Wireshark的权限不足的问题

    dumpcap需要root权限才能使用 如果是普通用户 Wireshark就没有权限使用dumpcap进行截取封包 解决方法 将dumpcap更改为Wireshark用户组 sudo chgrp wireshark usr bin dump
  • vue3_父子组件传参

    最近在看b站 小满zs 的vue3教程 巩固一下 1 父 gt 子组件 父组件自定义一个属性 用v bind 绑定在子组件上
  • couldn't find native method

    有两个原因 1 java这边native方法没有 native void renderFrameStart 2 c这边没有实现native方法 12 29 15 52 27 901 32735 32735 com ffmpegtest E
  • vue模板语法(上)

    目录 一 插值 什么是插值 建立一个html来编写插值 输出结果 二 指令 什么是指令 建立一个html来编写指令 输出结果 编辑 动态参数 输出结果 三 过滤器 什么是过滤器 建立一个html来编写过滤器 输出结果 4 计算属性 监听属性
  • STM32F103C8T6驱动舵机SG90 配置定时器TIM2,TIM3,TIM4的多种重映射模式下的不同IO口

    STM32F103C8T6驱动舵机SG90 配置定时器TIM2 TIM3 TIM4的多种重映射模式下的不同IO口 1 使用到的工具介绍 2 整个简单介绍 3 程序的介绍 1 使用到的工具介绍 keil5 烧写软件FlyMcu exe 硬件为