PWM的驱动使用(呼吸灯)

这篇具有很好参考价值的文章主要介绍了PWM的驱动使用(呼吸灯)。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

目录

一、初始化步骤

二、PWM所需函数

 三、PWM初始化与引脚使用

1、输出比较模式

2、极性的选择

3、初始化:

怎么给结构体赋初始值

4、引脚的使用(引脚定义表)

四、代码(PWM呼吸灯)

1、PWM.c

2、PWM.h

3、main.c

4、模式的选择(复用推挽输出)

 5、PWM参数的计算

 6、效果


一、初始化步骤

PWM的驱动使用(呼吸灯)

 图1-1PWM基本结构

第一步,RCC开启时钟,把我们要用的TIM外设和GPIO外设时钟开打

第二步,配置时基单元,包括前面的时钟源选择和时基单元

第三步,配置输出比较单元,包括CCR的值,输出比较模式,极性选择,输出使能这些参数

第四步,配置GPIO,把PWM对应的GPIO口,初始化为复用推挽输出的配置

第五步,运行控制,启动计数器,就能输出PWM

二、PWM所需函数

TIM_OC(1234)Init(TIM_TypeDef* TIMx, TIM_OCInitTypeDef* TIM_OCInitStruct);

这四个函数就是用来配置输出比较模块的,OC就是Output Compare,输出比较,这四个函数是配置上一章节的PWM基本结构中的输出比较单元x4这一块的,一个函数配置一个单元

参数:TIMx,选择定时器;第二个,结构体,输出比较的那些参数

是用结构体来初始化输出比较单元的

补充:这个函数仅高级定时器使用,在使用高级定时器输出PWM时,需要调用这个函数,使能主输出,否则PWM将不能正常输出。

TIM_OCStructInit(TIM_OCInitTypeDef* TIM_OCInitStruct);

是用来给输出比较结构体赋一个默认值

TIM_ForcedOC(1234)Config(TIM_TypeDef* TIMx, uint16_t TIM_ForcedAction);

使用来配置前置输出模式的,如果在运行中,想要暂停输出波形并且强制输出高或低电平,则可以使用此函数,但是使用情况不多,因为强制输出高电平和设置100%占空比是一样的

TIM_OC(1234)PreloadConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCPreload);

这四个函数是用来配置CCR寄存器的预装功能(影子寄存器)的;影子寄存器:写入的值不会立刻生效,而是在更新事件才会发生。

TIM_OC(1234)FastConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCFast);

这四个函数是用来配置快速使能的

TIM_ClearOC(1234)Ref(TIM_TypeDef* TIMx, uint16_t TIM_OCClear);

外部事件时清除REF信号

TIM_OC(1234)PolarityConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCPolarity);

TIM_OC(123)NPolarityConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCNPolarity);

是用来单独设置输出比较的极性的,带个N的就是高级定时器里互补通道的配置,OC4没有互补通道,所以没有OC4N的函数。在结构体初始化的那个函数里可以设置极性。

注:两个地方设置极性的作用是一样的,只不过是用结构体是一起初始化的。这里是单独的函数进行修改的。一般来说,结构体的参数,都会有一个单独的函数可以进行更改。这7个函数就是用来单独更改输出极性的。

TIM_CCxCmd(TIM_TypeDef* TIMx, uint16_t TIM_Channel, uint16_t TIM_CCx);

TIM_CCxNCmd(TIM_TypeDef* TIMx, uint16_t TIM_Channel, uint16_t TIM_CCxN);

是用来单独修改输出使能参数的。

TIM_SelectOCxM(TIM_TypeDef* TIMx, uint16_t TIM_Channel, uint16_t TIM_OCMode);

选择输出比较模式,这个是用来单独更改输出比较模式的函数。

TIM_SetCompare(1234)(TIM_TypeDef* TIMx, uint16_t Compare1);  重要

这四个函数是用来单独更改CCR寄存器值的函数。在运行的时候,更改占空比。

 三、PWM初始化与引脚使用

在这次项目的使用引脚是PB6引脚

1、输出比较模式

模式 模式参数
冻结模式 TIM_OCMode_Timing
相等时置有效电平 TIM_OCMode_Active
相等时置无效电平 TIM_OCMode_Inactive
相等时电平翻转 TIM_OCMode_Toggle
PWM模式1 TIM_OCMode_PWM1
PWM模式2 TIM_OCMode_PWM2

PWM的驱动使用(呼吸灯)

 图3-1强制输出模式

2、极性的选择

PWM的驱动使用(呼吸灯)

 图3-2极性的选择

参数1:high,高极性,就是极性不翻转,REF波形直接输出;或者说是有效电平是高电平,REF有效时,输出高电平

参数2:low,低极性,就是REF电平取反,或者说是有效电平为低电平

3、初始化:

1、打开时钟,选择内部时钟,初始化时基单元,因为我们是使用PB6引脚,所以在这里我们使用的是TIM2定时器。

2、在时基单元初始化下,初始化输出比较单元,在TIM.h文件中,TIM_OC(x)Init的4个初始化函数,对应的4个输出比较单元/输出比较通道,需要哪个初始化哪个通道,就调用哪个函数,不同通道的对应GPIO口也是不一样的,按照GPIO口需求来。我们使用的是PB6口,所以对应的是OC1_Init函数

PWM的驱动使用(呼吸灯)

图3-3初始化 

 注:在这里,我们这个结构体现在没有给所有的成员赋值,对于这个结构体来说,它现在是一个局部变量,如果不给他的成员赋初始值,它成员的值就是不确定的,会导致出现问题。

例:想把高级定时器当做定时器输出PWM时,自然会把TIM2、3、4改成为TIM1,这样的话,这个结构体原本用不到的成员,现在就需要使用到了。而这些之前没有使用到的成员你没有赋值,就会导致高级定时器输出PWM出现一些奇怪的问题。

问题例子:像高级定时器输出4路PWM,如果把初始化函数放在程序的第一行,则不会出现问题,如果初始化函数之前出现了其他代码,那4路PWM就会有3路不能输出。

原因:就是结构体成员没有配置完整,也没有给结构体赋初始值

正确做法:

方法1:把结构体所有成员都配置完整

方法2:先给结构体成员都赋一个初始值,在修改部分结构体成员

怎么给结构体赋初始值

使用Struct_Init函数,Struct_Init函数,就是用来给结构体赋初始值的

用途:使用Struct_Init赋一个初始值,再更改所需要的值即可,无需一一列出所有成员。

4、引脚的使用(引脚定义表)

PWM的驱动使用(呼吸灯)

 图3-4引脚定义表

 引脚定义表:默认复用功能就是片上外设的端口和GPIO的连接关系,如PA0,有TIM2_CH1_ETR,说明TIM2的ETRE引脚和通道1的引脚,都是借用了PA0这个引脚的位置的。

注:我们要使用TIM2的OC1也就是CH1通道,输出PWM,只能在PA0的引脚上输出,不能任意选择引脚输出,这些关系是定死的,是不能改变的。

 重映射:如PA2,如果你想用USART2的TX引脚,又要使用TIM2的CH3通道,无法同时使用,则可以在重定义列表中寻找,如果重定义的列表找不到,那外设复用的GPIO就不能挪位置。配置重映射是用AFIO来完成。

四、代码(PWM呼吸灯)

1、PWM.c

#include "stm32f10x.h"                  // Device header


void PWM_Init(void)
{
		RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4,ENABLE);//注意是开启APB1的时钟函数,因为TIM2是APB1总线的外设
		RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);//选择时基单元的时钟
	 
	  
	  GPIO_InitTypeDef GPIO_InitStructure;
	  GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AF_PP;//复用推挽输出
	  GPIO_InitStructure.GPIO_Pin=GPIO_Pin_6;
	  GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
	  GPIO_Init(GPIOB,&GPIO_InitStructure);
	
		TIM_InternalClockConfig(TIM4);
	  //定时器上电后默认是使用内部时钟,如果不调用,也是使用内部时钟,可以不写
	  
	
	
		//TIM_ETRClockMode2Config(TIM2, TIM_ExtTRGPSC_OFF, TIM_ExtTRGPolarity_NonInverted, 0x00);
	  //通过ETR引脚的外部时钟模式2配置
	
		TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;
	    TIM_TimeBaseInitStructure.TIM_ClockDivision =TIM_CKD_DIV1;//指定时钟分频
	    TIM_TimeBaseInitStructure.TIM_CounterMode =TIM_CounterMode_Up;//计数器模式
		TIM_TimeBaseInitStructure.TIM_Period = 100 - 1; //周期,ARR自动重装器的值
		TIM_TimeBaseInitStructure.TIM_Prescaler = 720 - 1;//PSC 预分频器的值
		TIM_TimeBaseInitStructure.TIM_RepetitionCounter = 0;//重复计数器的值,是高级计数器才有的
	  TIM_TimeBaseInit(TIM4,&TIM_TimeBaseInitStructure);
		//配置时基单元
		
	  TIM_OCInitTypeDef TIM_OCInitStructure;
		TIM_OCStructInit(&TIM_OCInitStructure);//给结构体赋初始值,不用一一列出
		TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1 ;//设置输出比较的模式
		TIM_OCInitStructure.TIM_OCNPolarity = TIM_OCPolarity_High ;//设置输出比较的极性
		TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;//设置输出使能
		TIM_OCInitStructure.TIM_Pulse = 0;//设置CCR
		TIM_OC1Init(TIM4, &TIM_OCInitStructure);
		
		//周期ARR;预分频PSC;CCR这三个值,共同决定输出PWM的周期和占空比
		
		
		TIM_Cmd(TIM4,ENABLE);//启动定时器

}

void PWM_Setcompare1(uint16_t Compare)
{
	TIM_SetCompare1(TIM4, Compare);
}




2、PWM.h

#ifndef __PWM_H
#define __PWM_H

void PWM_Init(void);
void PWM_Setcompare1(uint16_t Comparel);

#endif

3、main.c

#include "stm32f10x.h"                  // Device header
#include  "Delay.h"
#include  "Timer.h"
//#include  "OLED.h"
#include  "PWM.h"


uint8_t i;//定义一个16位得全局变量Num

int main(void)
{
    OLED_Init(); 
	  PWM_Init();
	
	
	while(1)
	{
			for (i = 0;i <= 100; i++)
		{
					PWM_Setcompare1(i);//设置CCR寄存器的值,并不是直接占空比,占空比是CCR和ARR+1决定的
					Delay_ms(10);
		}
		for (i = 0;i <= 100; i++)
		{
					PWM_Setcompare1(100 - i);
					Delay_ms(10);
		}
	}
}


4、模式的选择(复用推挽输出)

在PWM.c中,我们选择的GPIO口是PB6引脚,选择的是TIM4定时器(普通定时器),当中的模式我们选择的是复用推挽输出。

PWM的驱动使用(呼吸灯)

 图4-1开漏/推挽输出

PWM的驱动使用(呼吸灯)

 图4-2复用开漏/推挽输出

由图4-1可以知道普通开漏/推挽输出:引脚的控制权是来自于输出数据寄存器

如果想用定时器的控制引脚,需要使用复用开漏/推挽输出的模式,这里的输出数据寄存器被断开输出控制权将转移给片上外设,片上外设连接的TIM2的CH1通道,所以只有GPIO设置成复用推挽输出,引脚控制权才能交给片上外设,PWM波形才能通过引脚输出。

 5、PWM参数的计算

PWM的驱动使用(呼吸灯)

 图4-3参数计算

 周期ARR;预分频PSC;CCR这三个值,共同决定输出PWM的周期和占空比

假设设置一个1KHz,占空比50%,分辨率为1%的PWM波形

ARR = 99             CCR = 50               PSC+1 = 720

程序中,我们需要做的是呼吸灯,所以我们把CCR设置为0,在main.c中使用for函数达到呼吸灯的效果

PWM的驱动使用(呼吸灯)

 图4-4for函数

 6、效果

呼吸灯


本章写的是PWM的使用,项目是使用PWM的呼吸灯,在参考本章内容中,如果遇到不懂的可以参考上三章的内容

 TIM定时中断(定时器介绍)_tz得像个小孩的博客-CSDN博客_tim计时器

 定时器定时中断&定时器外部时钟_tz得像个小孩的博客-CSDN博客

 TIM输出比较(PWM)_tz得像个小孩的博客-CSDN博客文章来源地址https://www.toymoban.com/news/detail-432911.html


到了这里,关于PWM的驱动使用(呼吸灯)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包赞助服务器费用

相关文章

  • PWM的驱动使用(呼吸灯)

    PWM的驱动使用(呼吸灯)

    目录 一、初始化步骤 二、PWM所需函数  三、PWM初始化与引脚使用 1、输出比较模式 2、极性的选择 3、初始化: 怎么给结构体赋初始值 4、引脚的使用(引脚定义表) 四、代码(PWM呼吸灯) 1、PWM.c 2、PWM.h 3、main.c 4、模式的选择(复用推挽输出)  5、PWM参数的计算  6、效果

    2024年02月02日
    浏览(19)
  • Hive初始化遇到的问题:org.apache.hadoop.hive.metastore.HiveMetaException: 失败加载驱动程序

    Hive初始化遇到的问题:org.apache.hadoop.hive.metastore.HiveMetaException: 失败加载驱动程序 在大数据领域,Hive是一个常用的数据仓库工具,它构建在Hadoop之上,提供了一种类似于SQL的查询语言,用于处理大规模的数据集。然而,有时在Hive的初始化过程中,可能会遇到一些错误。其中

    2024年02月08日
    浏览(13)
  • Hive初始化异常:org.apache.hadoop.hive.metastore.HiveMetaException: 加载驱动程序大数据失败

    近年来,随着大数据技术的快速发展,越来越多的企业开始关注和运用大数据处理和分析。然而,在使用Hive进行大数据处理时,有时会遇到一些问题,比如在初始化过程中出现了加载驱动程序大数据失败的异常。本文将介绍这个异常的原因和解决方法,并提供相应的源代码示

    2024年02月04日
    浏览(13)
  • 【stm32L152】段码屏驱动注解、MX_LCD_Init()初始化失败的解决方法

    【stm32L152】段码屏驱动注解、MX_LCD_Init()初始化失败的解决方法

    已经有大神写过较详细的教程:https://blog.csdn.net/CSDN_Gao_16/article/details/115463499,但这篇博文仍然比较抽象,我看了好多遍才看明白-_-||,为了节省和我一样看的云里雾里的小白的宝贵的时间,这里是对原文的一些难以理解地方的解释: DISP_NUM[3] = {2, 5, 7} 这里应该结合原文使用

    2024年02月15日
    浏览(15)
  • 初始化列表的使用

    初始化列表的使用

    问题 类中是否可以定义 const 成员? 可以的 下面的类定义是否合法? 如果合法,ci 的值是什么,存储在哪里? 上面的 Test 类定义是合法的,但是要定义 Test 类对象的时候,编译器会报错,提示 const 成员变量 ci 没初始化 类中的 const 成员 我们对上面的代码进行编译,编译直

    2024年02月09日
    浏览(8)
  • Pytorch基本使用—参数初始化

    Pytorch基本使用—参数初始化

    深度学习模型参数初始化是指在训练深度神经网络时,对网络的权重和偏置进行初始化的过程。合适的参数初始化可以加速模型的收敛,并提高模型的性能。 在深度学习中, 常用的参数初始化方法有以下几种: 零初始化(Zero Initialization):将所有权重和偏置初始化为0。然

    2024年02月16日
    浏览(6)
  • 详解STM32的GPIO八种输入输出模式,GPIO各种输入输出的区别、初始化的步骤详解,看这文章就行了(超详细)

    详解STM32的GPIO八种输入输出模式,GPIO各种输入输出的区别、初始化的步骤详解,看这文章就行了(超详细)

    在STM32微控制器中,常见的输入输出(GPIO)模式有八种,分别是推挽输出、开漏输出、复用推挽输出、复用开漏输出、浮空输入、上拉输入、下拉输入和模拟输入。下面我将为你解释每种模式的特点和区别,并提供相应的示例代码。 推挽输出(Push-Pull Output):推挽输出模式是最常

    2024年02月15日
    浏览(41)
  • AliLinux的使用Docker初始化服务(详细)

    AliLinux是基于CentOS的。 1、java 环境 2、mysql环境 3、kafka环境 4、flink环境 5、dinky环境 这些环境,本想直接dnf安装在宿主机上,思来想去,还是用docker方便学习,也方便统一管理和使用 sudo dnf update sudo dnf upgrade 2.1、熟悉docker的命令 2.2、添加Docker存储库 需要注意不同的linux的版本

    2024年02月21日
    浏览(7)
  • 【物联网】详解STM32的GPIO八种输入输出模式,GPIO各种输入输出的区别、初始化的步骤详解,看这文章就行了(超详细)

    【物联网】详解STM32的GPIO八种输入输出模式,GPIO各种输入输出的区别、初始化的步骤详解,看这文章就行了(超详细)

    在STM32微控制器中,常见的输入输出(GPIO)模式有八种,分别是推挽输出、开漏输出、复用推挽输出、复用开漏输出、浮空输入、上拉输入、下拉输入和模拟输入。下面我将为你解释每种模式的特点和区别,并提供相应的示例代码。 推挽输出(Push-Pull Output):推挽输出模式是最常

    2024年02月14日
    浏览(42)
  • C语言:结构体数组的使用和初始化:

    前文:在C语言中,结构体是经常会用到的自定义数据类型,通常在使用结构体时,我们会进行单一的结构体初始化。但在使用同一个结构体,初始化不同的数据时,则可以用到结构体数组来进行初始化。 结构体数组是指在一个数组中存储多个结构体对象的集合。结构体是一

    2024年02月04日
    浏览(12)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包