历史上的今天
返回首页

历史上的今天

今天是:2024年12月20日(星期五)

正在发生

2021年12月20日 | STM32定时器输出PWM

2021-12-20 来源:eefocus

一、PWM

1.定义

英文全称:PULSE WIDTH MODULATION,脉冲宽度调制。

脉冲:频率,方波

宽度:占空比(duty),高电平的宽度


2.用途

(1)控制输出的电压和电流

(2)灯光的亮度

(3)电机


二、编程细节

PWM输出是没有中断触发的,PWM由硬件输出波形,用了中断反而会影响系统定时的效率。


所以,记住以后使用定时器输出PWM都不需要使用到中断


1.如配置STM32F407的TIM14的通道1,10ms即100Hz.


1ms = 0.01s=100HZ

84000000 /8400 = 10000

10000/x = 100

x=100

得到周期8400-1,分频系数10-1


基本配置如下

2.然后还要再配置定时器的输出功能,可以参考固件库手册的例子TIM_PWMOutPut,

这里涉及到了一个寄存器

TIMx_CCMR1:capture/compare mode register 1 --捕获/比较模式寄存器1

在这里插入图片描述

从上图可以看出,我们设置占空比是可以动态调整的,关键就在于设置中间这个比较值的大小。

我们会使用到下面这个函数设置TIMx通道1比较值函数,如果使用到通道2,改1为2即可。

假如100hz内,比较值设置为80hz,那么0-79为高电平,80-100为低电平。


void TIM_SetCompare1(TIM_TypeDef* TIMx,uint16_t Comarex);


/* PWM1 Mode configuration: Channel1 */

TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;//pwm模式1,解释如上图所示

TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;//允许输出

TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;//有效的时候,输出高电平

TIM_OC1Init(TIM14, &TIM_OCInitStructure);

TIM_OC1PreloadConfig(TIM14, TIM_OCPreload_Enable);//因为要周期性输出,所以要自动重装载初值,不断输出PWM脉冲

TIM_ARRPreloadConfig(TIM14,ENABLE);//自动重载使能


3.下面讲一下设置gpio的注意事项

(1)将引脚设置为复用功能

(2)将引脚与定时器进行绑定,告知是复用定时器功能


GPIO_PinAFConfig(GPIOC,GPIO_PinSource6,GPIO_AF_TIM14);


(3)最好是按照固件库手册的例程来写,有些定时器使能需要配置下面这个函数


TIM_CtrlPWMOutputs(TIM1,ENABLE);


4.主函数部分


uint32_t pwm_cmp = 0;//新建一个比较值

添加两个延时函数


while(1)

{

for(pwm_cmp =1;pwm_cmp<100;pwm_cmp++)

{

//设置比较值,查看所接的LED渐灭,因为0点亮

//如果想要渐亮,设置pwm_cmp为从100--1即可

TIM_SetCompare1(TIM14,pwm_cmp);

delay_ms(10);

}

for(pwm_cmp=99;pwm_cmp>0;pwm_cmp--)

{

TIM_SetCompare1(TIM14,pwm_cmp);

delay_ms(10);

}

}


下面是使用野火开发板STM32F429写的PWM输出


#include "stm32f4xx.h"



//R 红色灯

#define LED1_PIN                  GPIO_Pin_10                 

#define LED1_GPIO_PORT            GPIOH                      

#define LED1_GPIO_CLK             RCC_AHB1Periph_GPIOH


static __IO u32 TimingDelay;

 

/**

  * @brief  启动系统滴答定时器 SysTick

  * @param  无

  * @retval 无

  */

void SysTick_Init(void)

{

/* SystemFrequency / 1000    1ms中断一次

* SystemFrequency / 100000 10us中断一次

* SystemFrequency / 1000000 1us中断一次

*/

if (SysTick_Config(SystemCoreClock / 100000))

/* Capture error */ 

while (1);

}

}


/**

  * @brief   us延时程序,10us为一个单位

  * @param  

  * @arg nTime: Delay_us( 1 ) 则实现的延时为 1 * 10us = 10us

  * @retval  无

  */

void Delay_us(__IO u32 nTime)

TimingDelay = nTime;


while(TimingDelay != 0);

}


/**

  * @brief  获取节拍程序

  * @param  无

  * @retval 无

  * @attention  在 SysTick 中断函数 SysTick_Handler()调用

  */

void TimingDelay_Decrement(void)

{

if (TimingDelay != 0x00)

TimingDelay--;

}

}


/*

1-初始化LED灯所在的GPIO引脚


PH10  定时器5的CH1 


2-查看说明手册,判断定时器是否有输出功能


16 位(TIM3 和 TIM4)或 32 位(TIM2 和 TIM5) 递增、递减和递增/递减自动重载计 

数器。

说明可用


3-编写GPIO初始化

4-编写定时器初始化

5-主函数调用

*/

void tim14_init(void)

{

/*定义一个GPIO_InitTypeDef类型的结构体*/

GPIO_InitTypeDef          GPIO_InitStructure;

TIM_TimeBaseInitTypeDef   TIM_TimeBaseStructure;

TIM_OCInitTypeDef TIM_OCInitStructure;

/*开启LED相关的GPIO外设时钟*/

RCC_AHB1PeriphClockCmd ( LED1_GPIO_CLK, ENABLE); 

RCC_APB1PeriphClockCmd ( RCC_APB1Periph_TIM5, ENABLE); 


GPIO_PinAFConfig(GPIOH,GPIO_PinSource10,GPIO_AF_TIM5);

GPIO_InitStructure.GPIO_Pin = LED1_PIN; /*选择要控制的GPIO引脚*/

GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;    /*设置引脚模式为输出模式*/

    GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;    /*设置引脚的输出类型为推挽输出*/

        GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;    /*设置引脚为上拉模式*/

GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz; /*设置引脚速率为2MHz */   

GPIO_Init(LED1_GPIO_PORT, &GPIO_InitStructure); /*调用库函数,使用上面配置的GPIO_InitStructure初始化GPIO*/

//90Mhz 设置到100HZ输出,90000000/9000/100 = 100hz

TIM_TimeBaseStructure.TIM_Period = 100-1;

  TIM_TimeBaseStructure.TIM_Prescaler = 9000-1;

TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;

TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;

TIM_TimeBaseInit(TIM5,&TIM_TimeBaseStructure);

TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;

TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;

TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;

TIM_OC1Init(TIM5,&TIM_OCInitStructure);

TIM_OC1PreloadConfig(TIM5,TIM_OCPreload_Enable);

TIM_ARRPreloadConfig(TIM5,ENABLE);

// 使能定时器

TIM_Cmd(TIM5, ENABLE);


}


int main(void)

{

uint32_t pwm_cmp = 0;//新建一个比较值

SysTick_Init();

tim14_init();


while(1)

{

for(pwm_cmp =1;pwm_cmp<100;pwm_cmp++)

{

//设置比较值,查看所接的LED渐灭,因为0点亮

//如果想要渐亮,设置pwm_cmp为从100--1即可

TIM_SetCompare1(TIM5,pwm_cmp);

Delay_us(5000);    // 1000 * 10us = 100ms

}

for(pwm_cmp=99;pwm_cmp>0;pwm_cmp--)

{

TIM_SetCompare1(TIM5,pwm_cmp);

Delay_us(5000);    // 100 * 10us = 1000us = 1ms    *100 = 100ms

}

}

}



/*********************************************END OF FILE**********************/


在stm32f4xx_it.c


void SysTick_Handler(void)

{

TimingDelay_Decrement();

}

推荐阅读

史海拾趣

Amplitronix LLC公司的发展小趣事

随着国内市场的饱和,Amplitronix LLC开始寻求国际合作,以拓展海外市场。他们与多家国际知名企业建立了战略合作关系,共同研发新产品,开拓新市场。通过国际合作,公司不仅提升了品牌影响力,还获得了更多的技术资源和市场渠道。同时,公司也积极参与国际行业交流活动,展示了其技术实力和市场竞争力。

Anaheim Automation公司的发展小趣事

随着公司技术的不断进步和产品质量的提升,AMOTECH在1996年被政府通讯部评为“光明前途企业”。这是对公司技术实力和市场潜力的认可,也为公司的后续发展提供了有力支持。同年,公司还获得了ISO9000认证,这标志着公司的质量管理体系达到了国际标准,为公司进一步拓展国际市场打下了坚实基础。

Grande Electronics Ltd公司的发展小趣事
遥控器跌落或强烈震动可能导致内部元件损坏,因此在使用时要避免剧烈震动和摔落。
Bourns公司的发展小趣事

Bourns公司的创立源自Marlan和Rosemary Bourns夫妇在自家车库中的创新努力。在1947年,这两位创始人成功研发出了创新的航天传感器,这一突破性的发明为飞行员提供了精确校正飞机垂直定位的方法。这一创新不仅解决了航空领域的关键问题,也为Bourns公司的诞生奠定了坚实的基础。

CONEXANT公司的发展小趣事

作为一家在半导体和通信领域具有深厚技术底蕴的公司,Conexant始终致力于技术创新和市场拓展。在不断变化的市场环境中,Conexant紧跟行业趋势,加大在新技术研发和市场推广方面的投入。通过持续创新和市场拓展,Conexant成功巩固了在行业内的领先地位,并为全球用户提供了更加优质的产品和服务。

这些故事只是CONEXANT公司在电子行业发展中的一部分,它们展示了公司在不同时期的战略决策、技术创新和市场拓展能力。这些成就不仅为CONEXANT公司赢得了业界的尊重和认可,也为整个电子行业的发展做出了重要贡献。

GC Electronics公司的发展小趣事
电路中的连接不良、短路或断路等问题,也可能导致报警电路误报。

问答坊 | AI 解惑

2009年电子大赛比赛中常用的模块

本帖最后由 paulhyde 于 2014-9-15 03:38 编辑 比赛中常用的模块有: 运算放大器模块 滤波器模块 AGC模块 DDS信号源模块 电机驱动模块 A/D模块 D/A模块 欢迎大家把资料共享,查找资料!  …

查看全部问答>

arm知识

本帖最后由 paulhyde 于 2014-9-15 09:28 编辑 大家看看..  …

查看全部问答>

关于总线的问题?

比如wishbone总线到AMBA总线的用Verilog写的转换协议; AMBA对NAND flash控制器的操作程序…

查看全部问答>

关于ARM CPU异常中断的问题?

各位大虾,本人使用的s3c2410的芯片,在裸机下编程时出现了一个问题,我写了一段程序用于触发CPU的异常中断,但是CPU中断时没有进入中断服务函数中,不知道各位大虾有没有碰到过这种情况,如何才能够让CPU异常中断进入我的中断服务函数中?…

查看全部问答>

请大虾们给我点MFC蓝牙编程方面的资料!

我要用MFC编写PC端蓝牙软件,有搜索、连接、加密和传输文件的功能,希望大虾们能给我点MFC关于蓝牙编程的资料,如果有源代码参考的话就更好了。我能给的分不多,还请大虾们能无私的帮小弟个忙。感激,感激! …

查看全部问答>

触摸屏校准程序!

现在是直接调用系统自带的校准程序,方法如下: 首先在头文件里加入函数指针定义: typedef  BOOL  (WINAPI *_TouchCalibrate)(); 然后使用如下代码,就会出现屏幕校准画面了。 HINSTANCE  hinstance = LoadLi ...…

查看全部问答>

IAR Embedded Workbench问题

以下出错信息: Error[e72]: Segment FIQ_STACK must be defined in a segment definition option (-Z, -b or -P) 我是这样定义的 MODULE        ?CSTARTUP         RSEG&nbs ...…

查看全部问答>

wince 读取xml 问题

我是用Visual Studio C#建的解决方案 我想读与exe文件同目录下的XML,怎么读取? 之前没接触过WINCE,请各位多指教…

查看全部问答>

键盘 scancodetovirtualkey

scancodetovirtualkey,我看了源码是调用*puiVk = MapVirtualKey(*puiSc, MAP_SC_TO_VK); 但这个函数我没找到。有谁知道的,帮忙解答下```…

查看全部问答>

求助:udp协议网络通信的实现

根据udp的协议,编写了服务器端和客户机端的程序,想验证一下收发数据是否正确,可以将收发的程序都下载到目标机下,通过自发自收来实现?vxworks下本机的ip还是:127.0.0.1吗??不知道这种方法是否可以实现??…

查看全部问答>