STM32单脉冲模式

STM32定时器可以设置成单脉冲模式(OPM)。所谓的单脉冲就是通过程序在一定可控延时后,产生一个脉宽可控的脉冲。这里的延时时间与脉冲宽度都可以设置,主要通过比较:定时器的计数值TIM_CNT、定时器的比较值TIM_CCRx与定时器的周期值TIM_ARR 这三个值来得出。具体如下:

增计数模式:延时时间 = TIM_CCRx - 0                      脉冲宽度 =  TIM_ARR - TIM_CCRx

减计数模式:延时时间 = TIM_ARR - TIM_CCRx        脉冲宽度 = TIM_CCRx - 0

一个简单的单脉冲模式例子的如下图所示:

当定时器的通道2(即图中的TI2)检测一个上升沿后,经过tDelay延时后,通道1原先的低电平就变成了高电平,再经过tPULSE时间后,有倍拉低了,这里高电平的时间就是脉冲宽度。

接下去就讲讲怎么实现上面这个简单的例程:定时器的通道2检测到上升沿,后延时一定时间后输出一定时间的脉冲。还是基于我自己的规范工程。

1、工程的修改

1)这里用到了定时器,所以需要将stm32f10x_tim.h添加到STM32F10x_StdPeriod_Driver工程组中。

2)打开stm32f0x_conf.h文件,将其中原先被屏蔽的语句:#include "stm32f10x_tim.h"的注释去掉。

3)新建OnePulse.c与OnePulse.h两个文件,分别保存在BSP文件夹里下的src与inc中,然后在将OnePulse.c添加到BSP工程组。

 

2、OnePulse.c与OnePulse.h文件程序的编写

首先是引脚的初始化。在这里我选择定时器4,定时器4的通道1作为输出单脉冲的通道,定时器的通道2设置成输入捕获,用来捕获上升沿。所以TIM4通道1对应的引脚PB6设置成复用推挽输出,TIM4的通道2对应的引脚PB7设置成悬空输入。代码如下:

 

/*************************************************************
Function : OnePulse_GPIO_Init
Description: 定时器器的引脚初始化
Input : none
return : none
*************************************************************/
static void OnePulse_GPIO_Init(void)
{
GPIO_InitTypeDef GPIO_InitStructure;

RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);

GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6;//TIM4 CH1对应的引脚配置成复用输出
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOB, &GPIO_InitStructure);

GPIO_InitStructure.GPIO_Pin = GPIO_Pin_7;//TIM4 CH2对应的引脚配置成悬空输入
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
GPIO_Init(GPIOB, &GPIO_InitStructure);
}

接下去是定时器的配置。代码如下:

 

/*************************************************************
Function : OnePulse_TIM4_Init
Description: 定时器4配置
Input : none
return : none
*************************************************************/
static void OnePulse_TIM4_Init(void)
{
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
TIM_ICInitTypeDef TIM_ICInitStructure;
TIM_OCInitTypeDef TIM_OCInitStructure;

RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4, ENABLE);//初始化TIM4的时钟

/*---------------------------------------------------------
TIM4的定时时基为1/(72M/72)=1us
TIM4的CH1配置成PWM2输出模式,TIM4的CH2配置成输入捕获模式,
PWM2模式增计数下,计数值小于比较值为无效电平即低电平,
TIM2 CH2检测到一个上升沿后,经过一定的延时时间,输出一个脉冲,
延时时间 = 10000 * 1us = 10ms
脉冲宽度 = (65535 - 10000) * 1us = 65.535ms。
---------------------------------------------------------*/
TIM_TimeBaseStructure.TIM_Period = 65535;//定时器周期值
TIM_TimeBaseStructure.TIM_Prescaler = 72 - 1;//预分频
TIM_TimeBaseStructure.TIM_ClockDivision = 0;//时钟不分频
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;//增计数模式
TIM_TimeBaseInit(TIM4, &TIM_TimeBaseStructure);//初始化定时器时基

TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM2;//TIM4 CH1配置成PWM2输出模式
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;//输出使能
TIM_OCInitStructure.TIM_Pulse = 10000;//设置跳变值
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;//有效电平为高电平
TIM_OC1Init(TIM4, &TIM_OCInitStructure);

TIM_ICStructInit(&TIM_ICInitStructure);//初始化输入捕获结构体
TIM_ICInitStructure.TIM_Channel = TIM_Channel_2;//TIM4 CH2 配置为输入捕获模式
TIM_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_Rising;//上升沿捕获
TIM_ICInitStructure.TIM_ICSelection = TIM_ICSelection_DirectTI;//管教与寄存器直接对应
TIM_ICInitStructure.TIM_ICPrescaler = TIM_ICPSC_DIV1;//不与分频
TIM_ICInitStructure.TIM_ICFilter = 0;//不滤波
TIM_ICInit(TIM4, &TIM_ICInitStructure);//初始化TIM4 CH2

TIM_SelectOnePulseMode(TIM4, TIM_OPMode_Single);//选择定时器为单脉冲模式
TIM_SelectInputTrigger(TIM4, TIM_TS_TI2FP2);//选择触发源为IC2
TIM_SelectSlaveMode(TIM4, TIM_SlaveMode_Trigger);//选择定时器从模式为上升沿触发
}

先是设置定时器增计数,72预分频,然后设置周期值,这里设置为65535,也就是我们上面说过的TIM_ARR。接着设置定时器的通道1。上面讲过通道1是用来输出波形用的,所以采用PWM2模式,设定有效电平为高电平,然后设定它的比较值,也就是我们上面的TIM_CCRx,通道1就是TIM_CCR1了。在来设置通道2,通道2用于检查是否有上升沿,配置成输入捕获模式,不会上升沿。然后再设定定时器为单脉冲模式,触发源为IC2(也就是通道2),且上升沿触发。这样就配置好了定时器。由上面配置就可以计算出单脉冲的延长时间和脉冲宽度:

延长时间 = 1 / (72M/72/10000) = 10ms

脉冲宽度 = 1 / (72M/72/(65535 - 10000)) = 65.535ms

还要编写一个总函数:OnePulse_Init()来初始化下相关的代码:

 

/*************************************************************
Function : OnePulse_Init
Description: 单脉冲模式初始化
Input : none
return : none
*************************************************************/
void OnePulse_Init(void)
{
OnePulse_GPIO_Init();
OnePulse_TIM4_Init();
}

下面是OnePulse.h的代码,只是声明了OnePulse_Init()函数:

 

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

void OnePulse_Init(void);

#endif

3、main函数的编写

main函数很简单,只是调用下相关的初始化函数,代码如下:

 

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

4、测试

将示波器的探头连接到TIM4通道1对应的引脚PB6,然后用杜邦线将TIM4通道2对应的引脚PB7连接到GND接地引脚,然后马上在将杜邦线拔掉,这样来模拟一个上升沿。在示波器上就检测到了一个脉冲,如下图所示:

通过测量可以等到示波器上得到的单脉冲波形,脉冲的长度为65ms左右。类似下图:

  • 5
    点赞
  • 42
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
根据提供的引用内容,可以了解到在STM32F4中,可以通过TIM2和TIM3模块来实现PWM控制输出和脉冲计数。具体实现方法如下: 1. PWM控制输出 可以使用TIM2模块来控制PWM波的周期,使用TIM3模块来控制PWM波的脉冲数量。具体实现代码如下: ```c void Pulse_output(u32 cycle,u32 PulseNum) { TIM2_Config(cycle); // 配置TIM2的周期 TIM_Cmd(TIM2, ENABLE); // 使能TIM2 TIM3_Config(PulseNum); // 配置TIM3的脉冲数量 TIM_Cmd(TIM3, ENABLE); // 使能TIM3 } ``` 其中,`TIM2_Config()`和`TIM3_Config()`函数需要根据具体的需求进行配置,这里不再赘述。 2. 脉冲计数 在PWM波为低电平时,可以使用TIM3模块来进行脉冲计数。具体实现方法如下: ```c // 定义计数器 volatile uint32_t counter = 0; // TIM3中断处理函数 void TIM3_IRQHandler(void) { if (TIM_GetITStatus(TIM3, TIM_IT_Update) != RESET) { counter++; // 计数器加1 TIM_ClearITPendingBit(TIM3, TIM_IT_Update); // 清除中断标志位 } } // 初始化TIM3 void TIM3_Init(void) { TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure; NVIC_InitTypeDef NVIC_InitStructure; RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE); TIM_TimeBaseStructure.TIM_Period = 0xFFFF; TIM_TimeBaseStructure.TIM_Prescaler = 0; TIM_TimeBaseStructure.TIM_ClockDivision = 0; TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure); TIM_ITConfig(TIM3, TIM_IT_Update, ENABLE); NVIC_InitStructure.NVIC_IRQChannel = TIM3_IRQn; NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; NVIC_Init(&NVIC_InitStructure); TIM_Cmd(TIM3, ENABLE); } ``` 在上述代码中,`TIM3_Init()`函数用于初始化TIM3模块,并开启中断。在中断处理函数`TIM3_IRQHandler()`中,每当TIM3计数器溢出时,计数器`counter`就会加1。因此,可以通过读取计数器的值来获取PWM波的脉冲数量。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值