STM32 生成7路PWM波

发布者:幸福时光最新更新时间:2016-10-11 来源: eefocus关键字:STM32  PWM波 手机看文章 扫描二维码
随时随地手机看文章
STM32的定时器中的两个高级定时器TIM1与TIM8可以生成7路PWM波,因为他们分别有7路引脚通道:
 通道1  TIM1_CH1  PA8
 通道1  TIM1_CH1N  PB13
 通道2  TIM1_CH2  PA9
 通道2  TIM1_CH2N  PB14
 通道3  TIM1_CH3  PA10
 通道3  TIM1_CH3N  PB15
 通道4  TIM1_CH4  PA11   
 通道1  TIM8_CH1  PC6
 通道1  TIM8_CH1N  PA7
 通道2  TIM8_CH2  PC7
 通道2  TIM8_CH2N  PB0
 通道3  TIM8_CH3  PC8
 通道3  TIM8_CH3N  PB1
 通道4  TIM8_CH4  PC9
上面的表格中可以看到,通道1(下面都以TIM1为例子说明)其实有两个输出通道对应它:TIM1_CH1与TIM1_CH1N,这里的TIM1_CH1N称作为TIM1_CH1的互补通道,之所以叫做互补通道是因为TIM1_CH1N可以输出与TIM1_CH1相反的波形(极性相反,TIM1_CH1输出高电平时,TIM1_CH1N则输出低电平……)。当然,TIM1_CH1N也可以按照其他方式设置,但是还是与TIM1_CH1的配置有关,下面讲到它的相关代码的时候就明白了。
通道2、通道3与通道1一样,除了一个正常通道外,还有一个互补通道!然而对于通道4来说,它只有一个通道了:TIM1_CH4,而没有对应的互补通道。为什么不给通道4也弄个互补通道呢,愿意我也不知道!
综上,对于TIM1与TIM8这两个定时器就可以输出7路PWM波了。
下面就来讲讲怎么实现7路PWM波输出。还是以我的规范工程作为模板进行修改添加!
1、工程的修改
1)这里讲的是定时器,所以需要添加stm32f10x_tim.c文件添加到STM32F10x_StdPeriod_Driver工程组中。
2)打开stm32f10x_conf.h文件,将原先屏蔽的:#include "stm32f10x_tim.h"语句的屏蔽去掉。
3)新建7PWMOutput.c与7PWMOutput.h两个文件分别保存到BSP文件夹下的src与inc两个文件中。并将7PWMOutput.c文件添加到BSP工程组中。
 
2、7PWMOutput.c与7PWMOutput.h的程序编写
最首先要做的是要初始化下TIM1与TIM8个通道对对应的输出引脚了。它们个通道的输出引脚已将在上面的两个表格中给出了!它的代码如下:

/*************************************************************
Function : PWM_GPIO_Init
Description: TIM1对应通道引脚初始化
Input : none
return : none
*************************************************************/
static void PWM_GPIO_Init(void)
{
GPIO_InitTypeDef GPIO_InitStructure;

RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOB, ENABLE);
//TIM1的TIM_CH1/TIM_CH2/TIM_CH3/TIM1_CH4对应的引脚(PA9引脚与串口1的TX引脚复用,记得关闭串口1后在使用)
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8 | GPIO_Pin_9 | GPIO_Pin_10 | GPIO_Pin_11;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;//设置成复用推挽输出
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);
//TIM1的TIM1_CH1N/TIM1_CH2N/TIM1_CH3N对应的引脚
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13 | GPIO_Pin_14 | GPIO_Pin_15;
GPIO_Init(GPIOB, &GPIO_InitStructure);

//TIM8的TIM8_CH1/TIM8_CH2/TIM8_CH3/TIM8_CH4对应的引脚
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7 | GPIO_Pin_8 | GPIO_Pin_9;
GPIO_Init(GPIOC, &GPIO_InitStructure);
//TIM8的TIM8_CH1N对应的引脚
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_7;
GPIO_Init(GPIOA, &GPIO_InitStructure);
//TIM8的TIM8_CH2N/TIM8_CH3N对应的引脚
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1;
GPIO_Init(GPIOB, &GPIO_InitStructure);
}

引脚配置完后,就需要配置定时器了,先看看TIM1的初始化代码:

u16 CCR1_Val = 2047;
u16 CCR2_Val = 1535;
u16 CCR3_Val = 1023;
u16 CCR4_Val = 511;

/*************************************************************
Function : PWM_TIM1_Init
Description: 定时器1的7路PWM初始化
Input : none
return : none
*************************************************************/
static void PWM_TIM1_Init(void)
{
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
TIM_OCInitTypeDef TIM_OCInitStructure;

RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1, ENABLE);

TIM_TimeBaseStructure.TIM_Prescaler = 0;//不预分频
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;//增计数
TIM_TimeBaseStructure.TIM_Period = 4095;//定时器周期为4095
TIM_TimeBaseStructure.TIM_ClockDivision = 0;//时钟不分频
TIM_TimeBaseInit(TIM1, &TIM_TimeBaseStructure);

TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM2;//TIM_OCMode_PWM1 PWM1/PWM2模式
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;//输出使能
TIM_OCInitStructure.TIM_OutputNState = TIM_OutputNState_Enable;//输出使能
TIM_OCInitStructure.TIM_Pulse = CCR1_Val;//设置通道1的跳变值
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_Low;//有效电平为低电平
TIM_OCInitStructure.TIM_OCNPolarity = TIM_OCNPolarity_High;//有效电平为高电平
TIM_OCInitStructure.TIM_OCIdleState = TIM_OCIdleState_Set;//空闲时的状态为有效电平
TIM_OCInitStructure.TIM_OCNIdleState = TIM_OCIdleState_Reset;//空闲时的状态为无效电平
TIM_OC1Init(TIM1, &TIM_OCInitStructure);//初始化TIM1的通道1

TIM_OCInitStructure.TIM_Pulse = CCR2_Val;//设置通道2的跳变值
TIM_OC2Init(TIM1, &TIM_OCInitStructure);//初始化TIM1的通道2

TIM_OCInitStructure.TIM_Pulse = CCR3_Val;//设置通道3的跳变值
TIM_OC3Init(TIM1, &TIM_OCInitStructure);//初始化TIM1的通道3

TIM_OCInitStructure.TIM_Pulse = CCR4_Val;//初始化通道4的跳变值
TIM_OC4Init(TIM1, &TIM_OCInitStructure);//初始化TIM1的通道4

TIM_Cmd(TIM1, ENABLE);//使能定时器1
TIM_CtrlPWMOutputs(TIM1, ENABLE);//打开定时器主输出(一定要有这句话)
}

首先需要配置下TIM1的时基来决定输出PWM波的频率,上面与TIM_TimeBase名字相匹配的代码就是时基的配置,这里我不对时钟频率进行分频,设置的周期值为4095,所以对应的输出PWM的频率为72M/(4095 + 1)=17.578kHz。接下去是对各通道的配置。TIM1的通道1需要同时设置TIM1_CH1与TIM1_CH1N这两个通道,上面的代码中可以看到,通道设置成PWM2模式(在《STM32 定时器要点》这篇文章中已将讲过与PWM1模式的区别,这里就不重复讲诉了),接着打开TIM_CH1与TIM1_CH1N的引脚输出,设定占空比,然后设置TIM1_CH1的有效电平为低电平,空闲时的电平为低电平,而TIM1_CH1N设置成有效电平为高电平,空闲时的电平也为低电平。所以对于TIM1_CH1来说,输出的一个周期的PWM波点电平变化为:高-低;对于TIM1_CH1N的一个周期的PWM波的电平变化为:低-高。这样的话就将TIM1_CH1yuTIM1_CH1N配置成一个互补输出的PWM波了。当然这里也可以设置,TIM1_CH1与TIM1_CH1N的有效电平相同,这样的话就会输出相同的PWM波了,不过这样设置一点意义也没有,所以一般是TIM1_CH1与TIM1_CH1N的逼向设置成互补的!TIM1_CH2与TIM1_CH2N、TIM1_CH3和TIM3_CH3N也是同样配置成互补输出PWM波。对于TIM1_CH4只要最普通的配置就可以。最后的话再打开TIM1的主输出(TIM_CtrlPWMOutputs(TIM1, ENABLE))。
TIM8与TIM1也是相类似的配置,就不多讲了,代码如下:

/*************************************************************
Function : PWM_TIM8_Init
Description: 定时器8的7路PWM初始化
Input : none
return : none
*************************************************************/
static void PWM_TIM8_Init(void)
{
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
TIM_OCInitTypeDef TIM_OCInitStructure;

RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM8, ENABLE);

TIM_TimeBaseStructure.TIM_Prescaler = 0;//不预分频
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;//增计数
TIM_TimeBaseStructure.TIM_Period = 4095;//定时器周期为4095
TIM_TimeBaseStructure.TIM_ClockDivision = 0;//时钟不分频
TIM_TimeBaseInit(TIM8, &TIM_TimeBaseStructure);

TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM2;//TIM_OCMode_PWM1 PWM1/PWM2模式
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; //输出使能
TIM_OCInitStructure.TIM_OutputNState = TIM_OutputNState_Enable;//输出使能
TIM_OCInitStructure.TIM_Pulse = CCR1_Val;//设置通道1的跳变值
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_Low;//有效电平为低电平
TIM_OCInitStructure.TIM_OCNPolarity = TIM_OCNPolarity_High;//有效电平为高电平
TIM_OCInitStructure.TIM_OCIdleState = TIM_OCIdleState_Set;//空闲时的状态为有效电平
TIM_OCInitStructure.TIM_OCNIdleState = TIM_OCIdleState_Reset;//空闲时的状态为无效电平
TIM_OC1Init(TIM8, &TIM_OCInitStructure);//初始化TIM8的通道1

TIM_OCInitStructure.TIM_Pulse = CCR2_Val;//设置通道2的跳变值
TIM_OC2Init(TIM8, &TIM_OCInitStructure);//初始化TIM8的通道2

TIM_OCInitStructure.TIM_Pulse = CCR3_Val;//设置通道3的跳变值
TIM_OC3Init(TIM8, &TIM_OCInitStructure);//初始化TIM8的通道3

TIM_OCInitStructure.TIM_Pulse = CCR4_Val;//初始化通道4的跳变值
TIM_OC4Init(TIM8, &TIM_OCInitStructure);//初始化TIM8的通道4

TIM_Cmd(TIM8, ENABLE);//使能定时器1
TIM_CtrlPWMOutputs(TIM8, ENABLE);//打开定时器主输出(一定要有这句话)
}

接着还是老规矩,编写一个总函数:PWM_Init()来初始化与定时器相关的初始化代码。代码如下:

/*************************************************************
Function : PWM_Init
Description: PWM初始化
Input : none
return : none
*************************************************************/
void PWM_Init(void)
{
PWM_GPIO_Init();
PWM_TIM1_Init();
PWM_TIM8_Init();
}

为了让总总初始化函数PWM_Init()增在其他文件被调用,需要将它在7PWMOutput.h中声明下,7PWMOutput.h的代码如下:

#ifndef __7PWMOUTPUT_H__
#define __7PWMOUTPUT_H__
#include "stm32f10x.h"

void PWM_Init(void);

#endif

3、main函数
main函数中只要只要调用PWM_Init()函数就可以初始化话PWM相关代码了,它的代码如下:

/*************************************************************
Function : main
Description: main入口
Input : none
return : none
*************************************************************/
int main(void)
{
BSP_Init();
PWM_Init();
PRINTF("\nmain() is running!\r\n");
while(1)
{
LED1_Toggle();
Delay_ms(1000);
}
}

4、测试
可以用双通道示波器测量引脚PA8(TIM1_CH1对应的引脚)与PB13(TIM1_CH1N对应的引脚)。在示波器中可以看到两路频率为17.6kHz左右,占空比为50%的互补PWM波。同样测试TIM1与TIM8其它互补的通道引脚,也可以得到互补的PWM波。最后测量TIM1_CH4与TIM8_CH4对应的PA11与PC9,得到占空比为6.25%的PWM波!
关键字:STM32  PWM波 引用地址:STM32 生成7路PWM波

上一篇:STM32 定时器输出比较时间模式
下一篇:STM32 GPIO的8中种配置模式

推荐阅读最新更新时间:2024-03-16 15:14

STM32基于固件库学习笔记(9)TM3产生PWM调LED亮度
PWM   脉冲宽度调制模式可以产生一个由TIMx_ARR寄存器确定频率、由TIMx_CCRx寄存器确定占空比的信号,也就是说对脉冲宽度的控制。   STM32 的定时器除了 TIM6 和 7。其他的定时器都可以用来产生 PWM 输出。其中高级定时器 TIM1 和 TIM8 可以同时产生多达 7 路的 PWM 输出。而通用定时器也能同时产生多达 4路的 PWM 输出,这样,STM32 最多可以同时产生 30 路 PWM 输出!    在TIMx_CCMRx寄存器中的OCxM位写入’110’(PWM模式1)或’111’(PWM模式2),能够独立地设置每个OCx输出通道产生一路PWM。必须设置TIMx_CCMRx寄存OCxPE
[单片机]
新建基于MDK的STM32工程模板
一。开发环境和固定库版本 二。准备工作 三。建立工程模板 1. 建立一个Template的文件夹 2.在Template文件夹下建立下面3个文件夹 CORE 用来存放核心文件和启动文件, OBJ 是用来存放编译过程文件以及 hex 文件, STM32F10x_FWLib 文件夹顾名思义用来存放 ST 官方提供的库函数源码文件。USER 目录除了用来放工程文件外,还用来存放主函数文件 main.c,以及其他包括 system_stm32f10x.c 等等。 3. 在STM32F10x_StdPeriph_Lib_V3.5.0\Libraries\STM32F10x_StdPeriph_Driver 下面,将目录下
[单片机]
新建基于MDK的<font color='red'>STM32</font>工程模板
STM32实验一:GPIO之流水灯
前面写过一篇关于STM32单片机的GPIO的文章,本来是打着从实用角度来做的实验,但是发现不积跬步无以至千里啊,咱们从头开始,先做一个最简单的,入门级的,单片机系统中的hello world,流水灯实验! 我手中有一个神舟3的开发板,我就用这个板子来做实验,板子中的实验一共用到4个LED灯来做流水灯的实验,这里我们也用这4个灯,他们分别是GPIOF中的6、7、8、9这4个。 1、首先我们复制我们之前做过的模板工程到一个新建文件夹中,(如,你可以取个名字叫流水灯实验的文件夹)神舟开发板的例程中在项目中添加了两个文件,分别是led.c和led.h,这是一种习惯,每做一个项目的时候都在其中添加一个.c和对应的.h文件,这样可以是
[单片机]
<font color='red'>STM32</font>实验一:GPIO之流水灯
STM32--低功耗模式
STM32F10xxx有三中低功耗模式: ●睡眠模式(Cortex?-M3内核停止,外设仍在运行) ●停止模式(所有的时钟都以停止) ●待机模式(1.8V电源关闭) 时钟频率72MHz时,从闪存执行代码,STM32功耗36mA,是32位市场上功耗最低的产品,相当于0.5mA/MHz。 上电,默认使用内部HSI时钟8M,经测试10mA左右。待机模式可实现系统的最低功耗。 可将电流消耗降至两微安。 在待机模式下,所有的I/O引脚处于高阻态,除了以下的引脚: ●复位引脚(始终有效) ●当被设置为防侵入或校准输出时的TAMPER引脚 ●被使能的唤醒引脚 /*按钮GPIOB9进入睡眠,WKUP pin(GP
[单片机]
STM32--低功耗模式
STM32之低功耗——WKUP待机唤醒(LCD显示)
单片机的低功耗 很多单片机有低功耗模式,STM32也不例外。在系统或者电源复位后,微控制器出于运行状态之下,HCLK为CPU提供时钟,内核执行代码。当CPU不需要继续运行时,可以利用多种低功耗模式来节省功耗,例如等待某个事件触发。 STM32电源框图 STM32的三种低功耗模式 睡眠模式:内核停止,外设如NVIC,系统时钟Systick仍运行。 停止模式:所有时钟都已停止。1.8V内核电源工作。 PLL,HIS和HSE RC振荡器功能禁止。 寄存器和SRAM内容保留。 待机模式:1.8V内核电源关闭。 只有备份寄存器和待机电路
[单片机]
<font color='red'>STM32</font>之低功耗——WKUP待机唤醒(LCD显示)
STM32学习笔记——使用函数库编程控制GPIO口输出
看了网上许多人的代码以及各类开发板所带的例程,大多数使用的都是官方发布的函数库来编程,通过查询后发现,使用函数库来编程可以简化开发过程,并不需要追溯到各个寄存器,通过查看库手册,新手也可以快速应用STM32,因此,决定先从函数库开始入门! 1. 建立带函数库的IAR项目工程 先从网上下载3.5版(据说3.0版以后的固件库才逐渐稳定)stm32固件库(stm32f10x_stdperiph_lib)。由于与固件库版本兼容问题,重新下载安装了IAR6.30版。 1.1 创建项目文件夹 project ; 1.2 解压 stm32f10x_stdperiph_lib.rar 后, 将...stm32f10x_stdperi
[单片机]
<font color='red'>STM32</font>学习笔记——使用函数库编程控制GPIO口输出
STM32如何使用内部时钟源当系统时钟
由于最近老师让做一个项目,要用到STM32但是考虑成本问题,决定不用外部时钟,所以在网上搜集整理了一些资料,加上自己的一些想法。 参考资料: http://bbs.ednchina.com/BLOG_ARTICLE_3011869.HTM http://bbs.21ic.com/icview-587714-1-1.html 首先在主程序中注释掉SystemInit(); 然后使用下面的函数做为系统时钟的初始化函数 void RCC_Configuration(void) { RCC_DeInit();//将外设 RCC寄存器重设为缺省值 RCC_HSICmd(ENABLE);//使能HSI
[单片机]
<font color='red'>STM32</font>如何使用内部时钟源当系统时钟
基于STM32的GSM短信报警系统的设计与实现
引言 随着我国经济建设的迅速发展和人民群众生活水平的极大提高,人们越来越注重自身所处的环境是否安全。特别是当家中无人或者仅有老人孩子时,家庭成员的生命和财产的安全性越来越受到重视。因此,家庭防盗已成为一个重要的社会问题。目前,许多住宅小区的安防主要依靠传统的机械式(防盗网、防盗窗)防盗系统。这样不仅有碍美观,不符合火灾逃生的要求,而且不能有效地防止坏人的侵入。随着电子技术的飞速发展,防盗报警系统已迫切从原来的简单化、局部化向智能化、集成化发展。当前,GSM短信息服务已作为GSM网络的一种基本业务,基于GSM短信模块与单片机相连接应用于家庭无线防盗报警系统中,让家庭防盗更及时、更方便,以最直观的中文短消息形式,直接把案发地点的情况
[单片机]
基于<font color='red'>STM32</font>的GSM短信报警系统的设计与实现
小广播
添点儿料...
无论热点新闻、行业分析、技术干货……
设计资源 培训 开发板 精华推荐

最新单片机文章
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

换一换 更多 相关热搜器件
电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved