STM32之定时器产生PWM信号

定时器除了之前所述的可以固定的时间间隔产生中断之外,还能产生PWM信号。


void PWM_TIM(u16 arr, u16 psc)
{
	TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStruct;
	TIM_OCInitTypeDef TIM_OCInitTypeDefStruct;
	
	//使能定时器的时钟
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);
	
	//时钟一分频,时钟决定了计数一次需要花费的时间,系统时间为72MHz,则计数一次需要花费1/72us
	TIM_TimeBaseInitStruct.TIM_ClockDivision = TIM_CKD_DIV1;
	//定时器时钟的预分频值,即计数一次的时钟为1/(72*10e6/psc)=psc/(72*10e6)秒
	TIM_TimeBaseInitStruct.TIM_Prescaler = psc;
	//自动重装载值,即需要计数arr+1次,所花费的时间为psc/72*10e6*arr秒
	TIM_TimeBaseInitStruct.TIM_Period = arr;
	//向上计数
	TIM_TimeBaseInitStruct.TIM_CounterMode = TIM_CounterMode_Up;
	TIM_TimeBaseInit(TIM3, &TIM_TimeBaseInitStruct);
	//配置OC模式为PWM1
	TIM_OCInitTypeDefStruct.TIM_OCMode = TIM_OCMode_PWM1;
	//高电平为有效值
	TIM_OCInitTypeDefStruct.TIM_OCPolarity = TIM_OCPolarity_High;
	//使能比较输出
	TIM_OCInitTypeDefStruct.TIM_OutputState = TIM_OutputState_Enable;
	TIM_OC3Init(TIM3, &TIM_OCInitTypeDefStruct);
	//使能预装载
	TIM_OC3PreloadConfig(TIM3, TIM_OCPreload_Enable);
	TIM_ARRPreloadConfig(TIM3, ENABLE);
	//使能TIM3
	TIM_Cmd(TIM3, ENABLE);
}

除了对TIM_TimeBaseInitTypeDef结构体进行操作之外,想要产生PWM信号还需要利用TIM_OCInitTypeDef结构体进行设置。
在这里插入图片描述
上面的代码设置的是PWM1,递增计数,CNT<CCR,通道有效,有效值为高电平,CNT为计数的实时值,CCR为比较值,CNT会在0-arr之间自动递增。CCR是通过固件库函数TIM_SetCompare3(TIM3, CCR)设置。

	u16 i = 0;
	u8 flag = 0;
	key_init();
	led_init();
	PWM_TIM(2000-1, 36000-1); //pwm信号的周期为2000*36/72ms=1s
	
	while(1)
	{
		
//		if(flag == 0)
//		{
//			i++;
//			if(i == 300)
//			{
//				flag = 1;
//			}
//		}
//		else
//		{
//			i--;
//			if(i == 0)
//			{
//				flag = 0;
//			}
//		}
		TIM_SetCompare3(TIM3, 1000);
//		delay_nms(1);
//		GPIO_SetBits(GPIOB, GPIO_Pin_0);
//		GPIO_ResetBits(GPIOB, GPIO_Pin_1);
//		delay_nms(500);
//		GPIO_SetBits(GPIOB, GPIO_Pin_1);
//		GPIO_ResetBits(GPIOB, GPIO_Pin_0);
//		delay_nms(500);
	}


}

这里通过PWM对led进行每隔0.5s闪烁。
当然由于定时器上的端口连接到外设上是要用到外设复用功能,所以在led.c文件中应该通过打开GPIOB的时钟和复用功能外设的时钟,当然GPIO的模式也要设置成复用模式,这里设置的是复用推挽输出。

	GPIO_InitTypeDef InitStrcuture;
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);
	InitStrcuture.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1;
	InitStrcuture.GPIO_Mode = GPIO_Mode_AF_PP;
	InitStrcuture.GPIO_Speed = GPIO_Speed_10MHz;
	GPIO_Init(GPIOB, &InitStrcuture);

最后看一下main.c文件,通过arr和psc两个参数,这里输入的是2000-1和36000-1,所以PWM的周期为1s,再TIM_SetCompare3(TIM3, 1000)中的参数是1000,所以1000和2000比较,可以知道占空比为50%。
在这里插入图片描述
led端接收到的PWM电平信号。
在这里插入图片描述

还要注意的这里使用的通道是CH3,所以是TIM_SetCompare3。
再对比中文参考手册中的TM3复用功能重映射表
在这里插入图片描述
这里之所以选择TM3的CH3通道就是因为PB0只在这个定时器的这个通道。另外由于我使用的是stm32f103c8t6,是48脚的,所以不用设置重映射,否则需要使用部分重映射或完全重映射,选择的方法也是看该表。
重映射的函数:GPIO_PinRemapConfig(uint32_t GPIO_Remap, FunctionalState NewState)
位置应该可以放到led驱动GPIO_Init函数下方。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值