STM32f103C8定时器输出PWM波信号

STM32f103C8定时器输出PWM波信号,第1张

利用stm32高级定时器输出PWM,模拟呼吸灯的效果带刹车功能。由于没有示波器查看输出的pwm波形图,所以本次实验使用普通直流电机模拟的。

本文章为学习笔记,其中有些地方解释的不是那么的好,即本笔记可参考、可借鉴、可指点!


简单介绍: STM32F103C8T6采用 LQFP48方式封装,一共拥有 37个 I/O引脚,被分为PA(15个)、PB(15个)、PC(3个)、PD(2个)、PE(0个)五个组,所有 I/O接口可以映像到 16个外部中断,并且大部份端口都可以可以兼容5V信号。每个 I/O端口可以接受或输出8mA电流,灌电流则可达到20mA。 STM32F1 系列中,除了互联型的产品,共有 8 个定时器,分为基本定时器,通用定时器和高级 定时器。基本定时器 TIM6 TIM7 是一个 16 位的只能向上计数的定时器,只能定时,没有外部 IO 。通用定时器 TIM2/3/4/5 是一个 16 位的可以向上 / 下计数的定时器,可以定时,可以输出比较, 可以输入捕捉,每个定时器有四个外部 IO 。高级定时器 TIM1/8 是一个 16 位的可以向上 / 下计数 的定时器,可以定时,可以输出比较,可以输入捕捉,还可以有三相电机互补输出信号,每个定 时器有 8 个外部 IO    用到的相关结构体
typedef struct { 
    uint16_t TIM_Prescaler;       // 预分频器
    uint16_t TIM_CounterMode;     // 计数模式
    uint32_t TIM_Period;          // 定时器周期
    uint16_t TIM_ClockDivision;   // 时钟分频
    uint8_t TIM_RepetitionCounter;// 重复计算器
} TIM_TimeBaseInitTypeDef;

备注:
只要用到了TIM定时器就会用到这个结构体
typedef struct { 
    uint16_t TIM_OCMode;          // 比较输出模式
    uint16_t TIM_OutputState;     // 比较输出使能
    uint16_t TIM_OutputNState;    // 比较互补输出使能
    uint32_t TIM_Pulse;           // 脉冲宽度
    uint16_t TIM_OCPolarity;      // 输出极性
    uint16_t TIM_OCNPolarity;     // 互补输出极性
    uint16_t TIM_OCIdleState;     // 空闲状态下比较输出状态
    uint16_t TIM_OCNIdleState;    // 空闲状态下比较互补输出状态
} TIM_OCInitTypeDef;

备注:
只要需要输出PWM波,就需要这个结构体
typedef struct { 
     uint16_t TIM_OSSRState;       // 运行模式下的关闭状态选择
     uint16_t TIM_OSSIState;       // 空闲模式下的关闭状态选择
     uint16_t TIM_LOCKLevel;       // 锁定配置
     uint16_t TIM_DeadTime;        // 死区时间
     uint16_t TIM_Break;           // 断路输入使能控制
     uint16_t TIM_BreakPolarity;   // 断路输入极性
     uint16_t TIM_AutomaticOutput; // 自动输出使能
} TIM_BDTRInitTypeDef;

备注:
这个是中断PWM输出的结构体,也叫PWM死区控制
直接上代码吧!

头文件里面定义的宏,为什么要这么定义,下面注释有解释

/*****************
根据实验所得,用TIM1(即PA引脚组)输出pwm的时候会影响串口1的通信
所以这里将PWM换至其他组,但会丢弃刹车功能
*****************/
#if 0   //修改这个参数选择TIM1高级定时器还是TIM3通用定时器
	#define TIMX_Config            1
	#define RCC_APBxPeriphClockCmd RCC_APB2PeriphClockCmd
	#define RCC_APB2Periph_GPIOx   RCC_APB2Periph_GPIOA
	#define GPIO_Pin_x 			   GPIO_Pin_11
	#define GPIOx				   GPIOA
	#define RCC_APBxPeriph_TIMx	   RCC_APB2Periph_TIM1
	#define TIMx				   TIM1
	
#else
	#define TIMX_Config            0
	#define RCC_APBxPeriphClockCmd RCC_APB1PeriphClockCmd
	#define RCC_APB2Periph_GPIOx   RCC_APB2Periph_GPIOB
	#define RCC_APBxPeriph_TIMx	   RCC_APB1Periph_TIM3
	#define GPIO_Pin_x 			   GPIO_Pin_1
	#define GPIOx				   GPIOB
	#define TIMx				   TIM3
#endif

下面代码解释:但选用高级定时器TIM1的时候,对应的输出引脚是PA11,刹车引脚是PB12;

当选用通用定时器TIM3的时候,对应PWM输出引脚PB1,通用没有刹车功能

关于pwm波输出引脚和刹车中断引脚的初始化
static void TIM_GPIO_Init()
{
	GPIO_InitTypeDef GPIO_InitStructure;
	//PWM输出引脚
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOx, ENABLE);
	GPIO_InitStructure.GPIO_Pin=GPIO_Pin_x;
	GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AF_PP;
	GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
	GPIO_Init(GPIOx,&GPIO_InitStructure);

#if TIMX_Config
	//死区刹车引脚
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOx, ENABLE);
	GPIO_InitStructure.GPIO_Pin=GPIO_Pin_12;
	GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AF_PP;
	GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
	GPIO_Init(GPIOB,&GPIO_InitStructure);
	GPIO_ResetBits(GPIOx,GPIO_Pin_12);
#endif
}

下面代码解释:配置的基本定时器的定时为

ARR+1:自动重装载寄存器的值;其中(ARR+1)为TIM_Period的值
PSC+1:预分频值 ;其中(PSC+1)为TIM_Prescaler的值

一个计数器单次计数的频率:Cnt_CLK=Tclk/(PSC+1)=72M/(PSC+1);周期 T=(PSC+1)/Tclk=(PSC+1)/72M;ARR+1为你需要定时这么多个单次计数频率或周期。

总定时时间: Tout(us) = (重装载值+1)*((预分频值+1) / 内部时钟 ) = (ARR+1)*(PSC+1)/Tclk(单位MHz) ;
即定时器(PWM)一个定时周期 :Tout=(ARR+1)*(PSC+1)/Tclk ;频率f=1/Tout=Tclk/(ARR+1)*(PSC+1) 。

占空比 P=CCR/(ARR+1)=TIM_Pulse/(ARR+1)=TIM_Pulse/TIM_Period。

下面配置的是(ARR+1)=10;(PSC+1)=72;即计算出定时周期为10us 频率为100KHz;
通过TIM_SetCompare1(TIM1, Compare1),来修改占空比的值;则占空比100%的时候Compare1=10;0%占空比的时候Compare1=0。

着重注意:例如 TIM_OC4Init(TIMx, &TIM_OCInitStructure); 初始化的时候,别把通道选错了

关于TIM、pwm、pwm死区等相关配置和初始化
static void TIM_Mode_Config()
{
	TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;//计时器结构体初始化
	TIM_OCInitTypeDef  TIM_OCInitStructure;//输出比较结构体
	TIM_BDTRInitTypeDef TIM_BDTRInitStructure;//刹车和死区结构体初始化
	
	RCC_APBxPeriphClockCmd(RCC_APBxPeriph_TIMx,ENABLE);
	TIM_TimeBaseStructure.TIM_ClockDivision=TIM_CKD_DIV1;
	TIM_TimeBaseStructure.TIM_CounterMode=TIM_CounterMode_Up;//向上计数
	TIM_TimeBaseStructure.TIM_Period=10-1;// 自动重装载寄存器的值ARR
	TIM_TimeBaseStructure.TIM_Prescaler= 72-1;// 时钟预分频值 PSC
	TIM_TimeBaseStructure.TIM_RepetitionCounter=0;//不用管
	TIM_TimeBaseInit(TIMx, &TIM_TimeBaseStructure);//初始化
	
	TIM_OCInitStructure.TIM_OCMode=TIM_OCMode_PWM1;//选择PWM1模式
	TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;// 输出使能
	TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;// 输出通道电平极性配置
	TIM_OCInitStructure.TIM_Pulse = 5;// 设置占空比大小 50%
	TIM_OCInitStructure.TIM_OCIdleState = TIM_OCIdleState_Reset;// 输出通道空闲电平极性配置
	TIM_OC4Init(TIMx, &TIM_OCInitStructure);
	TIM_OC4PreloadConfig(TIMx, TIM_OCPreload_Enable);//自动重装载
	
#if TIMX_Config
	TIM_BDTRInitStructure.TIM_OSSRState = TIM_OSSRState_Enable;//运行模式下的关闭状态选择
    TIM_BDTRInitStructure.TIM_OSSIState = TIM_OSSIState_Enable;//空闲模式下的关闭状态选择
    TIM_BDTRInitStructure.TIM_LOCKLevel = TIM_LOCKLevel_1;//锁定级别配置
	TIM_BDTRInitStructure.TIM_DeadTime = 11;// 输出比较信号死区时间配置  这里配置的死区时间为152ns 
    TIM_BDTRInitStructure.TIM_Break = TIM_Break_Enable;//刹车功能使能
	TIM_BDTRInitStructure.TIM_BreakPolarity = TIM_BreakPolarity_High;//刹车输入检测极性,即外部输入高电平为刹车还是低电平
	TIM_BDTRInitStructure.TIM_AutomaticOutput = TIM_AutomaticOutput_Enable;//自动输出使能
	TIM_BDTRConfig(TIMx, &TIM_BDTRInitStructure);
#endif

	TIM_Cmd(TIMx, ENABLE);	// 使能计数器
	
#if TIMX_Config
	TIM_CtrlPWMOutputs(TIMx, ENABLE);// 主输出使能,高级定时器才需要配置下面的函数
#endif
}

下面代码解释:下面设置的每次增加的占空比为10%,如果需要更加细致的话,则需要修改上面的TIM相关参数,把每个PWM的分得更加细,这样就可以1%的步进进行调节了。 

着重注意:选择通道几,就要对应配置这个函数的x   “TIM_SetCompareX()"

/****************************
函数:uint8_t Motor_PWM_Fun(void)
参数:
功能:通过PWM实现类似呼吸灯效果的输出
说明://TIM_SetCompare1(TIM1, Compare1);//Compare1 范围0~10 自定义
        只要配置好了,即可直接调用该函数
****************************/
uint8_t Motor_PWM_Fun(void)
{
	value=pwm_value;
	if(pwm_value>10)
	{
		if(pwm_value==20)
		{
			pwm_value=0;
			value=0;
		}
		else
		{
			value=10-value%10;
		}
		TIM_SetCompare4(TIMx,value);//Compare1 范围0~10 自定义
	}
	else
	{
				TIM_SetCompare4(TIMx,value);//Compare1 范围0~10 自定义
	}
	sprintf(PWM_value,"\tPWM:value=%d%%\r\n",value*10);
	Usart1_SendString(PWM_value);
	pwm_value++;
	
	return 0;
}

pwm简易模拟呼吸灯

关注显示器上面的PWM的值的变化,对比车轮的转速变化(这里可能看起不明显) 

PWM调速电机

 注意:

STM32F103C8T6拥有 7个定时器:其中 1个用于电机控制的 16位 PWM高级控制定时器、3个 16位通用定时器、2个看门狗定时器(包含独立型的和窗口型)、1个 24位自减型系统嘀嗒定时器。
高级控制定时器 TIM1:TIM1可以被视为分配到 6个通道的三相 PWM发生器,具有带死区插入的互补 PWM输出,还可以用作完整的通用定时器;其四个独立通道可分别用于:输入捕获、输出比较、产生边缘或中心对齐模式的PWM、单脉冲输出。当配置为 16位普通定时器时,与TIM2、TIM3、TIM4具有相同功能;配置为 16位 PWM发生器时,具有0 ~ 100%的全调制能力。
通用定时器 TIM2、TIM3、TIM4:STM32F103C8T6内置有 3个可同步运行的标准定时器,每个定时器都拥有一个 16位自动加载递加/递减计数器、一个 16位预分频器、4个独立通道,每个通道都可用于输入捕获、输出比较、PWM、单脉冲输出,它们还可以通过定时器链接功能与高级控制定时器 TIM1协同工作,从而提供同步或事件链接功能。

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/langs/1331236.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-06-12
下一篇 2022-06-12

发表评论

登录后才能评论

评论列表(0条)

保存