STM32 定时器输出比较翻转模式

发布者:WanderlustGaze最新更新时间:2016-10-11 来源: eefocus关键字:STM32  定时器输出  翻转模式 手机看文章 扫描二维码
随时随地手机看文章
STM32的定时器还有一个模式叫做输出比较翻转模式。这种模式,顾名思义,可以翻转电平,但是条件是:当计数值达到比较值时,才会在对应的通道引脚翻转原先的电平。利用这个特点,我们可以在引脚上生成PWM波。
下面就讲讲如何利用这个“翻转”这个特点,来输出PWM波。还是基于我自己的规工程。
1、工程的修改
1)这里用到了定时器,所以需要将stm32f10x_tim.h添加到STM32F10x_StdPeriod_Driver工程组中。
2)打开stm32f0x_conf.h文件,将其中原先被屏蔽的语句:#include "stm32f10x_tim.h"的注释去掉。
3)新建OCToggle.c与OCToggle.h两个文件,分别保存在BSP文件夹里下的src与inc中,然后在将OCToggle.c添加到BSP工程组。
 
2、OCToggle.c与OCToggle.h文件程序的编写
首先是引脚的初始化。我使用TIM2,所以需要初始化TIM2对应的引脚PA0、PA1、PA2、PA3这四个引脚将它们配置成复用推挽输出,代码如下:

/*************************************************************
Function : OCToggle_GPIO_Init
Description: 输出比较翻转模式下定时器对应通道引脚初始化
Input : none
return : none
*************************************************************/
static void OCToggle_GPIO_Init(void)
{
GPIO_InitTypeDef GPIO_InitStructure;

RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);

GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_2 | GPIO_Pin_3;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;//定时器各通道引脚配置成复用推挽输出
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);
}

接下去当然是要配置定时器了。它的代码如下:

/*************************************************************
Function : OCToggle_TIM2_Init
Description: 输出比较翻转模式定时器2初始化
Input : none
return : none
*************************************************************/
static void OCToggle_TIM2_Init(void)
{
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
TIM_OCInitTypeDef TIM_OCInitStructure;

RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);//初始化TIM2时钟

/* -------------------------------------------------------
TIM_OCMode_Toggle模式计数值等于比较值翻转电平
在PA0引脚输出频率为72M/CCR1_Val/2=732Hz,占空比为50%的PWM波
在PA1引脚输出频率为72M/CCR2_Val/2=1099Hz,占空比为50%的PWM波
在PA2引脚输出频率为72M/CCR3_Val/2=2197Hz,占空比为50%的PWM波
在PA3引脚输出频率为72M/CCR4_Val/2=4395Hz,占空比为50%的PWM波
---------------------------------------------------------*/
TIM_TimeBaseStructure.TIM_Period = 65535;//定时器计数周期
TIM_TimeBaseStructure.TIM_Prescaler = 1 - 1;//预分频
TIM_TimeBaseStructure.TIM_ClockDivision = 1 - 1;//时钟不分频
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;//增计数
TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure);//初始化定时器


TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_Toggle;//输出比较主动模式
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;//输出使能
TIM_OCInitStructure.TIM_Pulse = CCR1_Val;//设置比较值(跳变值)
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;//有效电平为高电平
TIM_OC1Init(TIM2, &TIM_OCInitStructure);//初始化输出比较寄存器
TIM_OC1PreloadConfig(TIM2, TIM_OCPreload_Disable);//关闭预转载

TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;//输出使能
TIM_OCInitStructure.TIM_Pulse = CCR2_Val;//设置比较值(跳变值)
TIM_OC2Init(TIM2, &TIM_OCInitStructure);//初始化输出比较寄存器
TIM_OC2PreloadConfig(TIM2, TIM_OCPreload_Disable);

TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;//输出使能
TIM_OCInitStructure.TIM_Pulse = CCR3_Val;//设置比较值(跳变值)
TIM_OC3Init(TIM2, &TIM_OCInitStructure);//初始化输出比较寄存器
TIM_OC3PreloadConfig(TIM2, TIM_OCPreload_Disable);

TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;//输出使能
TIM_OCInitStructure.TIM_Pulse = CCR4_Val;//设置比较值(跳变值)
TIM_OC4Init(TIM2, &TIM_OCInitStructure);//初始化输出比较寄存器
TIM_OC4PreloadConfig(TIM2, TIM_OCPreload_Disable);

TIM_ITConfig(TIM2, TIM_IT_CC1 | TIM_IT_CC2 | TIM_IT_CC3 | TIM_IT_CC4, ENABLE);//清除中断标志
TIM_Cmd(TIM2, ENABLE);//打开定时器2
}

不对定时器做任何分频,并且让它满计数,即计数周期为65535。接下去再设置个通道的的工作模式为输出比较翻转模式,设置通道1的比较值为CCR1_Val、CCR3_Val、CCR3_Val、CCR4_Val,它们的值在OCToggle.h中定义。然后打开个通道的输出比较事件的中断。最后在打开定时器。这样的话,定时器这段就配置完成了。
既然打开了中断,则需要配置下中断,设置TIM2的中断优先级为1,代码如下:

/*************************************************************
Function : OCToggle_Int_Init
Description: 输出比较翻转模式中断初始化
Input : none
return : none
*************************************************************/
static void OCToggle_Int_Init(void)
{
NVIC_InitTypeDef NVIC_InitStructure;

NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;//中断优先级为1
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;

NVIC_Init(&NVIC_InitStructure);
}

还要编写一个总函数:OCToggle_Init()函数将上面的初始化相关代码都在这个函数中调用,代码如下:

/*************************************************************
Function : OCToggle_Init
Description: 输出比较翻转模式初始化
Input : none
return : none
*************************************************************/
void OCToggle_Init(void)
{
OCToggle_GPIO_Init();
OCToggle_TIM2_Init();
OCToggle_Int_Init();
}

接下去OCToggle.h的代码:

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

#define CCR1_Val 49152
#define CCR2_Val 32768
#define CCR3_Val 16384
#define CCR4_Val 8192

void OCToggle_Init(void);

#endif

这里之所以将CCR1_Val的值在这个h文件中宏定义,而不在c文件中直接定义成变量,原因是为了在其他文件中调用方便,如果定义成变量的话,在其他文件还要用extern关键字来声明,比较麻烦!
 
3、stm32f10x_it.c文件的修改
TIM2的中断服务函数的程序如下:

/*************************************************************
Function : TIM2_IRQHandler
Description: 定时器2中断服务程序
Input : none
return : none
*************************************************************/
void TIM2_IRQHandler(void)
{
static u16 capture = 0;
if (TIM_GetITStatus(TIM2, TIM_IT_CC1) != RESET)//通道1检测到比较事件
{
TIM_ClearITPendingBit(TIM2, TIM_IT_CC1);//清除标志位
capture = TIM_GetCapture1(TIM2);
TIM_SetCompare1(TIM2, capture + CCR1_Val);//重新设置比较值
}
if (TIM_GetITStatus(TIM2, TIM_IT_CC2) != RESET)//通道1检测到比较事件
{
TIM_ClearITPendingBit(TIM2, TIM_IT_CC2);//清除标志位
capture = TIM_GetCapture2(TIM2);
TIM_SetCompare2(TIM2, capture + CCR2_Val);//重新设置比较值
}
if (TIM_GetITStatus(TIM2, TIM_IT_CC3) != RESET)//通道1检测到比较事件
{
TIM_ClearITPendingBit(TIM2, TIM_IT_CC3);//清除标志位
capture = TIM_GetCapture3(TIM2);
TIM_SetCompare3(TIM2, capture + CCR3_Val);//重新设置比较值
}
if (TIM_GetITStatus(TIM2, TIM_IT_CC4) != RESET)//通道1检测到比较事件
{
TIM_ClearITPendingBit(TIM2, TIM_IT_CC4);//清除标志位
capture = TIM_GetCapture4(TIM2);
TIM_SetCompare4(TIM2, capture + CCR4_Val);//重新设置比较值
}
}

在这个中断服务程序中,每当检测到输出比较时事件时,通道对应的引脚就会自动翻转电平,然后我们在中断中,重新设置它的比较值,在原来的计数值的基础上再增加与计数值相同的计数值作为下一次的比较值。这样的话,就会形成占空比为50%的PWM波。以通道1为例解释下。通道1原来设置的计数值为49152,当定时器的计数值达到这个数时,就翻转通道1对应的输出引脚PA0翻转电平,然后在设置新的计数值为49152+49152,因为定时器只有16位,会溢出,所以下一个比较值为32768,这样的话,如果49152计数值时间内引脚输出高电平的话,下一个49152计数值时间内就会输出低电平,形成频率为72M/49152/2=732Hz,占空比为50%的PWM波。同样的,通道2会输出频率为1099Hz,占空比为50%的PWM波;通道3输出频率为2197Hz,占空比为50%的PWM波;通道4输出频率为4395Hz,占空比为50%的PWM波。
 
4、main函数的编写
main函数很简单,只是调用一些初始化函数:

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

5、测试
用示波器的探头分别连接引脚PA0、PA1、PA2、PA3。可以看到下面的现象:
连接PA0可以检测到频率为732Hz,占空比为50%的PWM波。如下图所示:
STM32 定时器输出比较翻转模式 - ziye334 - ziye334的博客
连接PA1可以检测到频率为1099Hz,占空比为50%的PWM波。如下图所示:
 STM32 定时器输出比较翻转模式 - ziye334 - ziye334的博客
 
连接PA2可以检测到频率为2197Hz,占空比为50%的PWM波。如下图所示:
STM32 定时器输出比较翻转模式 - ziye334 - ziye334的博客
连接PA3可以检测到频率为4395Hz,占空比为50%的PWM波。如下图所示:
STM32 定时器输出比较翻转模式 - ziye334 - ziye334的博客

关键字:STM32  定时器输出  翻转模式 引用地址:STM32 定时器输出比较翻转模式

上一篇:STM32 定时器单脉冲模式
下一篇:STM32 定时器输出比较非主动模式

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

STM32驱动直流电机的程序与电路设计
本文介绍如何使用STM32F103单片机,通过官方固件库,设置高级定时器TIM1输出嵌入死区的互补PWM,来驱动直流电机的程序设计与电路设计。硬件电路采用IR2110S芯片作为mos管的驱动,驱动IRF840组成的H桥。IR2110S芯片使用中,有一个比较难理解的点——自举电容,本文对其原理也有涉及。 原理图文件 上图是系统的简化原理图,左侧是单片机。中间是IR2110S芯片,为了方便讲解,把芯片内部结构列出一些。右侧是MOS管组成的H桥。其中M是直流电机,有正反转。其中VCC是15V,MOTOR_VCC是24V,电压可以改变,最大不超过500V。单片机一般是3.3V或5V,无法直接驱动电机。可以借助H桥来实现对直流电机的
[单片机]
<font color='red'>STM32</font>驱动直流电机的程序与电路设计
STM32三种定时器
STM32三种定时器:高级控制定时器(TIM1与TIM8)、通用定时器(TIM2~TIM5)、基本定时器(TIM6与TIM7)。 TIM1与TIM8定时器的功能 (1)16位向上、向下、向上/下自动装载计数器 (2)16位可编程(可以实时修改)预分频器,计数器时钟频率的分频系数为1~65535之间的任意数值 (3)多达4个独立通道: ─ 输入捕获 ─ 输出比较 ─ PWM生成(边缘或中间对齐模式) ─ 单脉冲模式输出 (4)死区时间可编程的互补输出 (5)使用外部信号控制定时器和定时器互联的同步电路 (6)允许在指定数目的计数器周期之后更新定时器寄存器的重复计数器 (7)刹车输入信号可以将定时器输出信号置于复位状态或者一
[单片机]
<font color='red'>STM32</font>三种<font color='red'>定时器</font>
STM32以太网程序解析三
--------------------------------------------------------------------------------------------------------------------------- 首先判断以太网数据包的ETH首部(总第12和13字节)类型长度是否为ARP协议代码(0x0806),然后判断ARP首部中总第0x26字节至第0x29字节存储的目的IP时候与本机相符,如果没有问题,则返回1,否则返回0 29行,在判断是arp包,且为目的IP为本机IP的情况下,设置返回一个ARP响应包,该行函数的内部操作函数为 1. void make_arp_answer_f
[单片机]
STM32:Keil MDK(uVision v4.10)开发环境搭建
集成开发环境(IDE):Keil公司的RealView MDK(uVision V4.10) 源文件编辑器:EditPlus(我在用的)/UltraEdit/SourceInsight/IDE自带的编辑器 串口工具:SecureCRT(一个专业的超级终端工具,支持很多接口(包括串口)和协议,推荐使用。) RealView MDK 工程配置:(keil开发环境搭建核心步骤) 1、新建文件夹,文件夹名如:Template 2、在文件夹Template下新建文件夹:User/ Project/ Output/ Listing/ Libraries/CMSIS/ Libraries/FWlib/ Doc/ 3、在Project/文件
[单片机]
STM32 CAN总线应用程序,调试通过仅供参考
1、打开STM32 CAN系统工作时钟 RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_AFIO, ENABLE); RCC_APB1PeriphClockCmd(RCC_APB1Periph_CAN1, ENABLE); 2、开放系统中断,根据实际情况选择 NVIC_InitStructure.NVIC_IRQChannel = USB_LP_CAN1_RX0_IRQn; NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; NVIC_InitStructure.NV
[单片机]
STM32学习笔记(7) 超声波HSR04模块详解
一 超声波硬件详解 硬件参数 二 工作原理 采用(IO触发测距,至少给10us的高电平) 模块自动发送8个40kHz的方波,自动检测是否有信号返回 有信号返回时,通过IO输出一高电平、高电平持续时间就是超声波从发射到返回的时间 三 代码编写 程序流程图 GPIO结构体的初始化 EXTI外部中断结构体的初始化 NVIC中断结构体的初始化 TimeBase时基结构体的初始化 超声波Trig发送信号 外部中断服务函数接收返回信号并计算出距离(全局变量) 关键代码 /** * 函数名:HSR04_Init() * 功能:超声波的初始化 * 引脚:PB5(Trig) | PB4(Echo) * 占用的内设资源
[单片机]
<font color='red'>STM32</font>学习笔记(7) 超声波HSR04模块详解
STM32如何分配原理图IO
在画原理图之前,一般的做法是先把引脚分类好,然后才开始画原理图。 要想根据功能来分配 IO,那就得先知道每个 IO 的功能说明,这个我们可以从官方的数据手册里面找到。在学习的时候,有两个官方资料我们会经常用到,一个是参考手册(英文叫 Referencemanual),另外一个是数据手册(英文叫 Data Sheet)。两者的具体区别见下表。 数据手册主要用于芯片选型和设计原理图时参考,参考手册主要用于在编程的时候查阅。在数据手册中,有关引脚定义的部分在 Pinouts and pin description 这个小节中。数据手册中对引脚定义具体定义见下表。 对上表中引脚定义的解读,见下图。 举例,如果MCU 型号是 S
[单片机]
<font color='red'>STM32</font>如何分配原理图IO
STM32 FSMC学习笔记+补充(LCD的FSMC配置)
FSMC全称 静态存储器控制器 。 使用FSMC控制器后,可以把FSMC提供的FSMC_A 作为地址线,而把FSMC提供的FSMC_D 作为数据总线。 (1)当存储数据设为8位时,(FSMC_NANDInitStructure.FSMC_MemoryDataWidth = FSMC_MemoryDataWidth_8b) 地址各位对应FSMC_A ,数据位对应FSMC_D (2)当存储数据设为16位时,(FSMC_NANDInitStructure.FSMC_MemoryDataWidth = FSMC_MemoryDataWidth_16b) 地址各位对应FSMC_A ,数据位对应FSMC_D FSMC 包括4个
[单片机]
<font color='red'>STM32</font> FSMC学习笔记+补充(LCD的FSMC配置)
小广播
添点儿料...
无论热点新闻、行业分析、技术干货……
设计资源 培训 开发板 精华推荐

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

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

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