ARM体系结构及编程 实验四 PWM实验

一、实验目的

      1. 深入了解STM32定时器结构和工作原理;

      2. 掌握定时器PWM功能的配置方法;

      3. 掌握定时器常用的固件函数和使用方法;

      4. 掌握PWM应用程序的编写方法。

二、实验内容

      使用库函数开发模版编写编写PWM应用程序,使用TIM13的CH1通道输出PWM控制LED灯D1的明暗程度或蜂鸣器声音的大小。

三、实验设备仪器和材料

      硬件:STM32开发板, PC 机;

      软件:MDK5集成开发环境,Windows 操作系统;

四、实验原理和接线

1. PWM简介

      STM32F4除了基本定时器TIM6和TIM7,其他定时器都可以产生PWM输出。其中高级定时器TIM1 和TIM8 可以同时产生多达7路的PWM输出。而通用定时器也能同时产生多达4路的PWM 输出(TIM9-TIM14最多能产生2路)。

      PWM的输出其实就是对外输出脉宽可调(即占空比调节)的方波信号,信号频率是由自动重装寄存器ARR的值决定,占空比由比较寄存器CCR的值决定。

      PWM常见有两种输出模式:PWM1和PWM2,这两种模式的区别是输出电平的极性不同。

模式计数器CNT计数方式说明
PWM1递增CNT<CCR,通道CH输出高电平
PWM1递减CNT>=CCR,通道CH输出低电平
PWM2递增CNT<CCR,通道CH输出低电平
PWM2递减CNT>=CCR,通道CH输出高电平

2. PWM—边沿对齐模式

      当TIMx_CR1 寄存器中的DIR位为低时执行递增计数,计数器CNT 从0计数到自动重载值(TIMx_ARR寄存器的内容),然后重新从0开始计数并生成计数器上溢事件。

      以PWM模式1为例。只要TIMx_CNT < TIMx_CCRx,PWM参考信号OCxREF便为高电平,否则为低电平。如果TIMx_CCRx中的比较值大于自动重载值(TIMx_ARR中),则OCxREF保持为“1”。如果比较值为0,则OCxREF保持为“0”。

      当TIMx_CR1寄存器中的DIR位为高时执行递减计数,计数器CNT从自动重载值(TIMx_ARR寄存器的内容)递减计数到0,然后重新从TIMx_ARR值开始计数并生成计数器下溢事件。

      以PWM模式1为例。只要TIMx_CNT >TIMx_CCRx,PWM参考信号OCxREF便为低电平,否则为高电平。如果TIMx_CCRx中的比较值大于自动重载值(TIMx_ARR 中),则OCxREF保持为“1”。此模式下不能产生0%的PWM波形。

3. PWM—中心对齐模式

      在中心对齐模式下,计数器CNT是工作做递增/递减模式下。开始的时候,计数器CNT从О开始计数到自动重载值减1(ARR-1),生成计数器上溢事件;然后从自动重载值开始向下计数到1并生成计数器下溢事件。之后从0开始重新计数。

      以ARR=8,CCRx=4为例。第一阶段计数器CNT工作在递增计数方式,从0开始计数,当TIMx_CNT< TIMx_CCRx 时,PWM参考信号OCxREF为高电平,当TIMx_CNT >= TIMx_CCRx 时,PWM参考信号OCxREF为低电平。第二阶段计数器CNT工作在递减计数方式,从ARR开始递减计数,当TIMx_CNT >TIMx_CCRx时,PWM参考信号OCxREF为低电平,当TIMx_CNT <= TIMx_CCRx 时,PWM参考信号OCxREF为高电平。

      中心对齐模式又分为中心对齐模式1/2/3三种,具体由寄存器CR1位CMS[1:0]配置。具体的区别就是比较中断标志位CCxIF在何时置1:中心模式1在CNT递减计数的时候置1,中心对齐模式2在CNT递增计数时置1,中心模式3在CNT递增和递减计数时都置1。

五、实验操作步骤

1. 编写led.c文件

#include "led.h"
void LED_Init()
{
	GPIO_InitTypeDef GPIO_InitStructure; //定义结构体变量,该语句的作用是将GPIO_InitTypeDef结构体命名为GPIO_InitStructure
	
	RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOF,ENABLE); //使能端口F时钟,
	
	GPIO_InitStructure.GPIO_Mode=GPIO_Mode_OUT;//设置输出模式
	GPIO_InitStructure.GPIO_Pin=GPIO_Pin_9|GPIO_Pin_10;//管脚设置为F9和F10
	GPIO_InitStructure.GPIO_Speed=GPIO_Speed_100MHz;//IO口速度为100M
	GPIO_InitStructure.GPIO_OType=GPIO_OType_PP;//推挽输出
	GPIO_InitStructure.GPIO_PuPd=GPIO_PuPd_UP;//上拉
	GPIO_Init(GPIOF,&GPIO_InitStructure); //初始化结构体,初始化PF口
	GPIO_SetBits(GPIOF,GPIO_Pin_9|GPIO_Pin_10);//输出高电平
}

2. 编写beep.c文件

      beep.c文件用于进行蜂鸣器的初始化


#include "beep.h"
void BEEP_Init(void) 
{
	GPIO_InitTypeDef GPIO_InitStructure; //定义结构体变量	
	RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOF,ENABLE); //使能端口F时钟
	
	GPIO_InitStructure.GPIO_Mode=GPIO_Mode_OUT; //输出模式
	GPIO_InitStructure.GPIO_Pin=BEEP_Pin;//管脚设置F8
	GPIO_InitStructure.GPIO_Speed=GPIO_Speed_100MHz;//速度为100M
	GPIO_InitStructure.GPIO_OType=GPIO_OType_PP;//推挽输出
	GPIO_InitStructure.GPIO_PuPd=GPIO_PuPd_UP;//上拉
	GPIO_Init(BEEP_Port,&GPIO_InitStructure); //初始化结构体
	
	GPIO_SetBits(BEEP_Port,BEEP_Pin); //关闭蜂鸣器
	
}

3. 编写pwm.c文件

操作步骤和思路:
    (1)使能定时器及端口时钟,并设置引脚复用映射

      使用TIM13的通道CH1输出PWM信号,所以使能TIM13时钟,将引脚设置为复用模式,调用库函数:RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM13,ENABLE)  GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AF

    (2)初始化定时器参数,包含自动重装值,分频系数,计数方式

    (3)初始化PWM输出参数,包括PWM模式、输出极性、使能

      配置TIM13的CH1为PWM1模式,输出极性为低电平,并且使能PWM输出

    (4)开启定时器,调用TIM_Cmd(TIM13,ENABLE)函数

#include "pwm.h"
void TIM13_CH1_PWM_Init(u16 per,u16 psc)
{
	TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;
	TIM_OCInitTypeDef TIM_OCInitStructure;
	GPIO_InitTypeDef GPIO_InitStructure;
	
	RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOF,ENABLE);
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM13,ENABLE);//使能TIM13时钟
	
	GPIO_PinAFConfig(GPIOF,GPIO_PinSource8,GPIO_AF_TIM13);//管脚复用
	GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AF; //复用输出模式
	GPIO_InitStructure.GPIO_Pin=GPIO_Pin_8;//管脚设置
	GPIO_InitStructure.GPIO_Speed=GPIO_Speed_100MHz;//速度为100M
	GPIO_InitStructure.GPIO_OType=GPIO_OType_PP;//推挽输出
	GPIO_InitStructure.GPIO_PuPd=GPIO_PuPd_UP;//上拉
	GPIO_Init(GPIOF,&GPIO_InitStructure); //初始化结构体
	
	
	TIM_TimeBaseInitStructure.TIM_Period=per;   //自动装载值
	TIM_TimeBaseInitStructure.TIM_Prescaler=psc; //分频系数
	TIM_TimeBaseInitStructure.TIM_ClockDivision=TIM_CKD_DIV1;
	TIM_TimeBaseInitStructure.TIM_CounterMode=TIM_CounterMode_Up; //设置向上计数模式
	TIM_TimeBaseInit(TIM13,&TIM_TimeBaseInitStructure);	
	
	TIM_OCInitStructure.TIM_OCMode=TIM_OCMode_PWM1;
	TIM_OCInitStructure.TIM_OCPolarity=TIM_OCPolarity_Low;
	TIM_OCInitStructure.TIM_OutputState=TIM_OutputState_Enable;
	TIM_OC1Init(TIM13,&TIM_OCInitStructure); //输出比较通道1初始化
	
	TIM_OC1PreloadConfig(TIM13,TIM_OCPreload_Enable); //使能TIMx在CCR1上的预装载寄存器
	TIM_ARRPreloadConfig(TIM13,ENABLE);//使能预装载寄存器
	
	TIM_Cmd(TIM13,ENABLE); //使能定时器
		
}

4. 编写main.c文件

操作步骤和思路:
    (1)首先初始化对应的硬件端口始终和IO口

    (2)调用TIM13_CH1_PWM_Init函数,设定定时器自动重装载值为500-1,预分频系数为84-1,定时周期为500us,即频率1KHz

    (3)通过变量fx控制i的方向,如果fx=0,i值累加,否则递减,将这个变化的i值传递给改变占空比TIM_SetComparel函数,因此可以控制蜂鸣器声音的强弱。

#include "system.h"
#include "SysTick.h"
#include "led.h"
#include "beep.h"
#include "pwm.h"
int main()
{
	u16 i;  
	u8 fx=0;
	SysTick_Init(168);
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);  //中断优先级分组 分2组
	//LED_Init();
	BEEP_Init();
	TIM13_CH1_PWM_Init(500-1,84-1); //频率是2kh
	while(1)
	{
		if(fx==0)
		{
			i++;
			if(i==300)
			{
				fx=1;
			}
		}
		else
		{
			i--;
			if(i==0)
			{
				fx=0;
			}
		}
		TIM_SetCompare1(TIM13,i);  //i值最大可以取499,因为ARR最大值是499		
		delay_ms(10);
	}
}

六、实验结果

      本次实验使用库函数开发模板编写PWM应用程序,使用TIM13的CH1通道输出PWM控制蜂鸣器声音的大小,可以听到蜂鸣器声音由小变大再逐渐变小,循环发声。

总结:
      PWM的基本原理就是对逆变电路开关器件的通断进行控制,使输出端得到一系列幅值相等的脉冲,用这些脉冲来代替正弦波或所需要的波形,也就是在输出波形的半个周期中产生多个脉冲,使各脉冲的等值电压为正弦波形,所获得的输出平滑且低次谐波少,按一定的规则对各脉冲的宽度进行调制,既可改变逆变电路输出电压的大小,也可改变输出频率。通过使用TIM13的CH1通道控制蜂鸣器的PWM输出,可以得到逐渐递增再递减的声音,实现渐变过程。

  • 20
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

布零酱

阿里嘎多!谢谢打赏嗷喵~

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值