STM32 F103 PWM定时器实验

实验目的

通过上一张的学习,我们知道知道STM32的通用定时器和高级定时器拥有PWM输出功能,本章我们将利用TIM3的CH3通道输出波形,数据手册请参看第14章中的相关内容。

实验简介

脉宽调制器(PWM),是英文“Pulse Width Modulation”的缩写,简称脉宽调制,是利用微处理器的数字输出来对模拟电路进行控制的一种非常有效的技术。简单一点,就是对脉冲宽度的控制。

STM32的定时器除了TIM6和TIM7,其他的定时器都可以用来产生PWM输出,其中高级定时器TIM1和TIM8可以同时产生多达7路的PWM输出。而通用定时器也能同时产生多达4路的PWM输出,这样,STM32最多可以同时产生30路PWM输出。这里我们仅利用TIM3的CH3产生一路PWM输出。

PWM原理

在这里插入图片描述
上图就是一个简单的 PWM 原理示意图。图中,我们假定定时器工作在向上计数 PWM 模式,且当 CNT<CCRx 时,输出 0,当 CNT>=CCRx 时输出 1。那么就可以得到如上的 PWM 示意图:当 CNT 值小于 CCRx 的时候,IO 输出低电平(0),当 CNT 值大于等于 CCRx 的时候, IO 输出高电平(1),当 CNT 达到 ARR 值的时候,重新归零,然后重新向上计数,依次循环。 改变 CCRx 的值,就可以改变 PWM 输出的占空比,改变 ARR 的值,就可以改变 PWM 输出的 频率,这就是 PWM 输出的原理。

电路设计

TIM3的CH3通道映射到PB0上,外接了红色LED灯D4,PWM输出波形可以控制LED的亮度,改变占空比,可以改变LED亮度,电路图如下图。
在这里插入图片描述

有关寄存器

捕获/比较模式寄存器 1(TIMx_CCMR1)
在这里插入图片描述
在这里插入图片描述
这里我们主要了解 110和111这两种相反的模式

** 捕获/比较使能寄存器(TIMx_CCER) **
在这里插入图片描述
在这里插入图片描述
因为TIM3的CH3通道映射到PB0上

捕获/比较寄存器 1(TIMx_CCR1)
在这里插入图片描述
小、中和大容量产品的寄存器映像和位定义
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

寄存器代码

test.c

#include "sys.h"
#include "delay.h"
#include "usart.h"
#include "led.h"
#include "timer.h"

int main(void)
{
	u16 led0pwmval = 0;
	u8 dir = 1;
	Stm32_Clock_Init(9);
	uart_init(72,115200);
	delay_init(72);
	LED_Init();
	TIM3_PWM_Init(899,0);
	//频率= 72000/(899+1)=80khz
	
	while(1)
	{
		delay_ms(10);
		if(dir)
			led0pwmval++;
		else
			led0pwmval--;
		if(led0pwmval > 300)
			dir = 0;
		if(led0pwmval == 0)
			dir = 1;
		LED3_PWM_VAL = led0pwmval;
		//捕捉/比较 寄存器3 使用的TIM3_CH3
	}
}

timer.h

#ifndef __TIMER_H
#define __TIMER_H

#include "sys.h"

#define LED3_PWM_VAL  TIM3->CCR3

void TIM3_Int_Init(u16 arr,u16 psc);
void TIM3_PWM_Init(u16 arr,u16 psc);

#endif

timer.c

#include "timer.h"
#include "led.h"

void TIM3_IRQHandler(void)
{
	if(TIM3->SR & 0x0001)
	//溢出中断
	{
		LED2 = !LED2;
	}
	TIM3->SR &= ~(1<<0);
	//清除中断标志位
}

void TIM3_Int_Init(u16 arr,u16 psc)
{
	RCC->APB1ENR |= 1<<1; 
	//TIM3使能
	TIM3->ARR = arr;
	//设置计数器自动重装值
	TIM3->PSC = psc;  
	//预分频器
	TIM3->DIER |= 1<<0;  
	//允许中断更新
	TIM3->CR1  |= 0x01;  
	//使能定时器3
	
	MY_NVIC_Init(1,3,TIM3_IRQn,2);
	//抢占1 子优先级3 组 2
}


void TIM3_PWM_Init(u16 arr,u16 psc)
//PWM初始(自动重装值,时钟预分频数)
{
	RCC->APB1ENR |= 1<<1;
	//TIM3时钟使能
	RCC->APB2ENR |= 1<<3;
	//使能PORTB时钟
	GPIOB->CRL &= 0xFFFFFFF0;
	GPIOB->CRL |= 0x0000000B;
	//复用推挽输出
	
	RCC->APB2ENR |= 1<<0; 
	//辅助时钟
	//在配置AFIO,相关寄存器的时候,必须开启辅助
	//功能
	AFIO->MAPR &= 0xFFFFF3FF;
	//清除MAPR的【11:10】;
  AFIO->MAPR |= 1<<11;  
  //部分重映射  TIM3_CH3->PB0
	
	TIM3->ARR = arr;
	//设定计数器自动重装值
	TIM3->PSC = psc;
	//预分频器不分频
	
	TIM3->CCMR2 |= 7<<4;
	//CH3 PWM模式
	TIM3->CCMR2 |= 1<<3;
	//CH3 预装载使能
	TIM3->CCER |= 1<<8;
	//OC3输出使能
	TIM3->CR1 = 0x0080;
	//ARPE使能
	TIM3->CR1 |= 0x01;
	//使能定时器3
}


HAL库代码

main.c

#include "MyIncludes.h"

int main()
{
 u8 dir = 0;
 u16 duty = 1;

 System_Init();
 SysTick_Init(NULL);
 PWM_Init(1000,duty);

 while(1)
 {
   delay_ms(10);
   if(dir == 0)
   {
     if(duty < 100)
     duty++;
     else
     dir = 1;
     
   }
   else if(dir == 1)
   {
    if(duty > 1)
    duty -- ;
    else
    dir = 0;
   }
   PWM_Init(10000,duty);
 }
}

pwm.h

#ifndef __PWM_H_
#define __PWM_H_

#include "stm32f1xx.h"
#include "stm32_types.h"
#include "stm32f1xx_hal.h"

void PWM_Init(u32 Freq, u32 Duty_Cycle);
//PWM脉冲调制初始化(PWM频率,占空比)
#endif

pwm.c

#include "pwm.h"

TIM_HandleTypeDef PWMHandle;
//TIM句柄结构变量声明
TIM_OC_InitTypeDef sConfig;
//TIM输出比较配置结构变量声明

uint32_t uwPeriodValue = 0;
//定时器ARR自动重装寄存器值

void HAL_TIM_PWM_MspInit(TIM_HandleTypeDef *htim)
//在HAL_TIM_PWM_Init中调用
{
  GPIO_InitTypeDef GPIO_InitStruct;
  
  __GPIOB_CLK_ENABLE();
  __TIM3_CLK_ENABLE();
  
  GPIO_InitStruct.Pin = GPIO_PIN_0;
  GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
  GPIO_InitStruct.Pull = GPIO_PULLUP;
  HAL_GPIO_Init(GPIOB,&GPIO_InitStruct);
}

void PWM_Init(u32 Freq,u32 Duty_Cycle)
//PWM(脉冲调制)初始化(PWM频率,占空比)
{
  uwPeriodValue = (uint32_t)((SystemCoreClock/2/Freq) - 1);
 //uwPeriodValue = (72000000/2/1000)-1
 // = 3599
 PWMHandle.Instance = TIM3;
 //TIM3_CH3产生PWM
 PWMHandle.Init.Prescaler = 0;
 //设置计数频率为 0 
 PWMHandle.Init.Period = uwPeriodValue;
 //设置自动重装值
 PWMHandle.Init.ClockDivision = 0;
 //时钟不分频,来自RCC
 PWMHandle.Init.CounterMode = TIM_COUNTERMODE_UP;
 //递增计数
 PWMHandle.Init.RepetitionCounter = 0;
  //指定重复计数器值 为 0
 if(HAL_TIM_PWM_Init(&PWMHandle) != HAL_OK)
 {
    while(1);
 }
 //如果初始化未完成将一直循环
 sConfig.OCMode = TIM_OCMODE_PWM1;
 //PWM1模式
 sConfig.OCPolarity = TIM_OCPOLARITY_LOW;
 //输出极性低电平
 sConfig.OCFastMode = TIM_OCFAST_DISABLE;
 //输出比较快速使能禁止
 sConfig.OCNPolarity = TIM_OCNPOLARITY_HIGH;
// 指定互补输出极性
 sConfig.OCNIdleState = TIM_OCNIDLESTATE_RESET;
 //指定空闲状态期间的TIM输出比较管脚状态。
 sConfig.OCIdleState = TIM_OCIDLESTATE_SET;
 //指定空闲状态期间的TIM输出比较管脚状态。
 
 sConfig.Pulse = (Duty_Cycle *(uwPeriodValue - 1))/100;
 //设置占空比
 //占空比是指高电平的时间占整个周期的比例。
 //pulse =  Duty_Cycle*(3599-1)/100 = 34.98Duty_Cycle;
 if(HAL_TIM_PWM_ConfigChannel(&PWMHandle,&sConfig,TIM_CHANNEL_3) != HAL_OK )
 {
   while(1);
 }
 if(HAL_TIM_PWM_Start(&PWMHandle,TIM_CHANNEL_3) != HAL_OK)
 //PWM启动
 {
   while(1);
 }
}
  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
STM32F103C8是一款常用的Cortex-M3内核的微控制器芯片,它具有丰富的外设资源,包括多个定时器模块。对于定时器4 (Timer4) 的PWM输出,以下是具体的步骤和代码实现。 1. 首先,需要初始化定时器4的时钟。定时器4使用的是APB1总线时钟,需要将APB1总线时钟使能,并设置合适的分频系数。 RCC_APB1PeriphClockCmd(RCC_APB1Periph_Timer4, ENABLE); // 使能定时器4时钟 RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4, ENABLE); // 启用定时器4外设 2. 进行定时器4的配置,设置相关寄存器的值,包括设置PWM输出的周期和占空比。 TIM_TimeBaseStructure.TIM_Period = 999; // 设置周期值,决定PWM输出的频率 TIM_TimeBaseStructure.TIM_Prescaler = 71; // 设置预分频系数,用于将时钟源除以一定倍数 TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1; // 设置时钟分频 TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; // 设置计数模式为向上计数 TIM_TimeBaseInit(TIM4, &TIM_TimeBaseStructure); // 初始化定时器4 TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1; // 设置定时器4的PWM模式 TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; // 启用定时器4的输出比较 TIM_OCInitStructure.TIM_Pulse = 500; // 设置占空比,决定PWM信号高电平持续时间 TIM_OC1Init(TIM4, &TIM_OCInitStructure); // 初始化定时器4的通道1 TIM_OC1PreloadConfig(TIM4, TIM_OCPreload_Enable); // 启用定时器4的通道1的预装载功能 3. 最后,需要使能定时器4并启动PWM输出。 TIM_CtrlPWMOutputs(TIM4, ENABLE); // 使能定时器4的PWM输出 TIM_Cmd(TIM4, ENABLE); // 启动定时器4 通过上述步骤和代码,我们可以实现定时器4的PWM输出。其中,周期值和占空比可以根据具体需求进行调整,以得到期望的PWM波形。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值