蓝桥杯嵌入式PWM


在蓝桥杯嵌入式的比赛中PWM也是很经常考到的一个高频考点。因此掌握PWM的配置也是很重要的。
在本文就重点掌握两种PWM配置方式即:
●固定频率,占空比可调。
●频率、占空比可调。

在开始之前我们要懂得占空比和频率的计算公式是怎样的?即:
频率=(预装载值+1)*(分频系数+1)/72MHZ
占空比= TIMx->CCR/(预装载值为+1)

这个分析完了,我们再把视线拉倒主板上看看其硬件连接pwm是搭载在哪一个GPIO上。在省赛中大多的pwm的配置都是用到PA6和PA7的这两个引脚。在数据手册上。
在这里插入图片描述
这里我们知道PA6和PA7用到了定时器3的通道1和通道2。

这些知道了我们就可以开始配置函数了。

首先看看几个重要的函数。


RCC_APB2PeriphClockCmd();//配置时钟
GPIO_Init();  //IO初始化
TIM_TimeBaseInit(); //定时器初始化
TIM_OC1Init();  //定时器通道1
TIM_OC2PreloadConfig(); //使能预装载寄存器
TIM_Cmd(); //使能定时器。
TIM_SetCompare1(); //调节占空比

固定频率,占空比可调。

这里配置两路pwm频率固定,占空比可调。

void pwm_init(void)
{
    GPIO_InitTypeDef GPIO_InitStruct;
    TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStruct;
    TIM_OCInitTypeDef	TIM_OCInitStruct;
  
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);

    GPIO_InitStruct.GPIO_Pin = GPIO_Pin_6|GPIO_Pin_7;
    GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF_PP;
    GPIO_Init(GPIOA, &GPIO_InitStruct);

    TIM_TimeBaseInitStruct.TIM_Period = 999; //预装载值
    TIM_TimeBaseInitStruct.TIM_Prescaler =71; //分频系数
    TIM_TimeBaseInitStruct.TIM_ClockDivision = 0; 
    TIM_TimeBaseInitStruct.TIM_CounterMode = TIM_CounterMode_Up;//向上计数
    TIM_TimeBaseInit(TIM3, &TIM_TimeBaseInitStruct);
   
   TIM_OCInitStruct.TIM_OCMode = TIM_OCMode_PWM2;  //pwm2模式
 	TIM_OCInitStruct.TIM_OutputState = TIM_OutputState_Enable;//比较输出
	TIM_OCInitStruct.TIM_OCPolarity = TIM_OCPolarity_High; 
	TIM_OC1Init(TIM3, &TIM_OCInitStruct);
	TIM_OC1PreloadConfig(TIM3, TIM_OCPreload_Enable);  
	 
    TIM_OCInitStruct.TIM_OCMode = TIM_OCMode_PWM2;  //pwm2模式
 	TIM_OCInitStruct.TIM_OutputState = TIM_OutputState_Enable;//比较输出
	TIM_OCInitStruct.TIM_OCPolarity = TIM_OCPolarity_High; 
	TIM_OC2Init(TIM3, &TIM_OCInitStruct);
	TIM_OC2PreloadConfig(TIM3, TIM_OCPreload_Enable);  
	TIM_Cmd(TIM3, ENABLE);
}

可以看到我们这里配置的预装载值=999,分频系数=71。那么我们的频率为:(999+1)*(71+1)/72000000=1khz

我们在看看如何改变通道的占空比。即:

u16 ch1=100;
u16 ch2=200;
int main(void)
{
 pwm_init();
 while(1)
 {
   TIM_SetCompare2(TIM3,ch2);
   TIM_SetCompare1(TIM3,ch1);
 }
}

这里可以看到初始化的PA6占空比为0.1,PA7占空比为0.2。这里的ch1和ch2可以通过按键进行加减来对占空比的调节。

在来看看如何快速的配置这个模式。快速的配置就要用到比赛时官方给的固件库v3.5。

在这里插入图片描述
打开里面的这个路径:6-STM32固件库代码V3.5版\STM32F10x_StdPeriph_Lib_V3.5.0\Project\STM32F10x_StdPeriph_Examples\TIM\PWM_Output。找到main函数打开

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
这里两路的PWM配置就完成了。但是里面的有一部分还是要修改的。

●在使用APB2的时钟的时候我们只用到了GPIOA其他没有用到。多余的删除。
●在使用定时器初始化的时候要把预装载的值和分频系数的值修改。
●结构体TIM_Pulse的值可以不用设置。

频率、占空比可调。

这种模式与上一种模式的方法配置大致相同。定时器及PWM波的配置程序基本上没什么变化。主要就是使用到了中断服务函数和,输出模式的变化。即:

#include "pwm.h"

u16 CR2_val=10000; //100hz    72MHZ/72/10000=100HZ
u16 CR1_val=5000;  //200hz    72MHZ/72/5000=200HZ

float ch1=0.1;     //通道1占空比
float ch2=0.1;

u16 cata;
_Bool pa6=0;      //标志位
_Bool pa7=0;
void pwm_init(void)
{
  GPIO_InitTypeDef GPIO_InitStruct;
	TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStruct;
	NVIC_InitTypeDef NVIC_InitStruct;
	TIM_OCInitTypeDef TIM_OCInitStruct;
	
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3,ENABLE);
	
	GPIO_InitStruct.GPIO_Mode=GPIO_Mode_AF_PP;
	GPIO_InitStruct.GPIO_Pin=GPIO_Pin_6|GPIO_Pin_7;
	GPIO_InitStruct.GPIO_Speed=GPIO_Speed_50MHz;
	GPIO_Init(GPIOA,&GPIO_InitStruct);
	
	TIM_TimeBaseInitStruct.TIM_ClockDivision=0;
	TIM_TimeBaseInitStruct.TIM_CounterMode=TIM_CounterMode_Up;
	TIM_TimeBaseInitStruct.TIM_Period=65535;                   //65536-1
	TIM_TimeBaseInitStruct.TIM_Prescaler=71;                   
	TIM_TimeBaseInit(TIM3,&TIM_TimeBaseInitStruct);
	
	NVIC_InitStruct.NVIC_IRQChannel=TIM3_IRQn;
	NVIC_InitStruct.NVIC_IRQChannelCmd=ENABLE;
	NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority=0;
	NVIC_InitStruct.NVIC_IRQChannelSubPriority=0;
	NVIC_Init(&NVIC_InitStruct);
	
	TIM_OCInitStruct.TIM_OCMode=TIM_OCMode_Toggle;          //比较翻转
	TIM_OCInitStruct.TIM_OutputState=TIM_OutputState_Enable;
	TIM_OCInitStruct.TIM_OCPolarity=TIM_OCPolarity_High;
	TIM_OCInitStruct.TIM_Pulse=CR1_val;
	TIM_OC1Init(TIM3,&TIM_OCInitStruct);
	
	TIM_OC1PreloadConfig(TIM3,TIM_OCPreload_Disable); 
	
	TIM_OCInitStruct.TIM_OCMode=TIM_OCMode_Toggle;
	TIM_OCInitStruct.TIM_OutputState=TIM_OutputState_Enable;
	TIM_OCInitStruct.TIM_OCPolarity=TIM_OCPolarity_High;
	TIM_OCInitStruct.TIM_Pulse=CR2_val;
	TIM_OC2Init(TIM3,&TIM_OCInitStruct);
	
	TIM_OC2PreloadConfig(TIM3,TIM_OCPreload_Disable);	
	
	TIM_Cmd(TIM3,ENABLE);
	
	TIM_ITConfig(TIM3,TIM_IT_CC1|TIM_IT_CC2,ENABLE);
}

void TIM3_IRQHandler(void)
{
  if(TIM_GetITStatus(TIM3,TIM_IT_CC1)!=RESET)
	{
	  TIM_ClearITPendingBit(TIM3,TIM_IT_CC1);        
		cata=TIM_GetCapture1(TIM3);         //获取当前计数器的值
		if(pa6==0)
		{
		  TIM_SetCompare1(TIM3,cata+(u16)(CR1_val*ch1));
			pa6=1;
		}
		if(pa6==1)
		{
		  TIM_SetCompare1(TIM3,cata+(u16)(CR1_val*(1-ch1)));
			pa6=0;
		}
	}
	  if(TIM_GetITStatus(TIM3,TIM_IT_CC2)!=RESET)
	{
	  TIM_ClearITPendingBit(TIM3,TIM_IT_CC2);
		cata=TIM_GetCapture2(TIM3);
		if(pa7==0)
		{
		  TIM_SetCompare2(TIM3,cata+(u16)(CR2_val*ch2));
			pa7=1;
		}
		if(pa7==1)
		{
		  TIM_SetCompare2(TIM3,cata+(u16)(CR2_val*(1-ch2)));
			pa7=0;
		}
	}
}


在来看看如何快速配置。还是老样子利用到固件库V3.5。
打开路径:STM32固件库代码V3.5版\STM32F10x_StdPeriph_Lib_V3.5.0\Project\STM32F10x_StdPeriph_Examples\TIM\OCToggle。的main函数
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

这样就把初始化配置完成了。但是还是有部分要修改的。例如:
时钟的配置、分频系数为71。使用的通道为1、2多余的去掉。

接下来就是服务函数的配置。在相同路径下的stm32f10x_it.c 文件上

在这里插入图片描述

这里稍微修改加上标志位进行处理就可以使用了。

在对于频率和占空比的调节。主要也还是

u16 CR2_val=10000; //100hz    72MHZ/72/10000=100HZ
u16 CR1_val=5000;  //200hz    72MHZ/72/5000=200HZ
float ch1=0.1;     //通道1占空比
float ch2=0.1;

这几个参数的改变来进行控制。

extern float ch,ch;
extern u16 CR2_val,CR1_val;
u16 pinlv1 = 100,pinlv2 =200;//注意pinlv1和pinlv2的值必须分别初始化为72000000/72/CR1_Val和72000000/72/CR2_Val
extern float ch,ch;
extern u16 CR2_val,CR1_val;
u16 pinlv1 = 100,pinlv2 =200;//注意pinlv1和pinlv2的值必须分别初始化为72000000/72/CR1_Val和72000000/72/CR2_Val
unsigned char key_val;
int main(void)
{
  pwm_init();
  key_init();
  while(1)
  {
    key_val=key_scanf();
    if(key_val==1)  //第一个按键按下
    {
       pinlv1 += 100;//pinlv1增加,意味着CR1_Val减小,CCR1_Val减小意味着频率增大,即增加PWM频率,+100表示频率每次增加100Hz
		  CR1_val = (u16)(72000000/72/pinlv1);
    }
     if(key_val==2)  //第2个按键按下
    {
       pinlv1 -= 100;//pinlv1减小,意味着CR1_Val增大,CCR1_Val增大意味着频率减小,即减小PWM频率,-100表示频率每次减小100Hz
		  CR1_val = (u16)(72000000/72/pinlv1);
    }
     if(key_val==3) //第3个按键按下
     {
      ch1+=0.1;   //通道1占空比+10%
     } 
     if(key_val==4) //第4个按键按下
     {
      ch1-=0.1;    //通道1占空比-10%
     } 
  }
}
  • 4
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

叶同学要努力呀

你的鼓励将是我创作的最大动力

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

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

打赏作者

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

抵扣说明:

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

余额充值