stm32定时器pwm模式输入捕获

发布者:PeacefulOasis最新更新时间:2018-07-06 来源: eefocus关键字:stm32  定时器  pwm模式  输入捕获 手机看文章 扫描二维码
随时随地手机看文章

stm32中的定时器,除了TIM6和TIM7,其他定时器都有输入捕获功能。这种模式通常用在对输入信号频率frequency、占空比duty、高低脉宽的计算中,具有很广泛的用途。

STM32的输入捕获,简单的说就是通过检测TIMx_CHx上的边沿信号,在边沿信号发生跳变(比如上升沿/下降沿)的时候,将当前定时器的值(TIMx_CNT)存放到对应的通道的捕获/比较寄存(TIMx_CCRx)里面,完成一次捕获。同时还可以配置捕获时是否触发中断/DMA 等。

PWM模式捕获方法:利用TIM3_CH1作PWM输出,TIM2_CH2捕获上述PWM信号,并测出频率和占空比。设置PWM频率为1KHz,占空比50%。 
具体步骤: 
1. 为了实现PWM输入捕获,TIM2占用了2个通道。第2通道的电平变化会被第一通道和第二通道引脚检测到,其中第一通道被设置为从机模式(如何快速判别主从机模式,规则如下:如果设置的是第二通道作为PWM输入捕获,则剩余的第一通道都为从机,反之亦然)。 
2. 假设输入的PWM从低电平开始跳变,在第一个上升沿到来时,1,2通道同时检测到上升沿。而从机设置为复位模式,所以将TIM2的计数值复位至0,此时不会产生一个中断请求。 
3. 下一个到来的电平是下降沿,此时通道1发生捕获事件,将计数值存入通道1的CCR1里。 
4. 然后是第二个上升沿到来后,此时通道2发生捕获事件,将此时的计数值存入通道2的CCR2里。复位模式此时又将TIM2计数值复位至0,等待第二个下降沿到来。 
5. 一次捕获过程完成,则PWM的频率f=72M/CCR2;占空比:duty=(CCR1/CCR2) X100%

注:图1,定时器内部结构 
PWM输入模式时,用到两个通道(一般用TIMx_CH1或TIMx_CH2),只给其中一个通道分配gpio时钟即可,另一个在内部使用。给一个通道分配gpio时钟后,需要设置另一个为从机且复位模式。(例如使用ch2,ch1就得设置成从机模式)。当一个输入信号(TI1或TI2)来临时,主通道捕获上升沿,从机捕获下降沿。 
在CH2通道中: 
TI2FP1和TI2FP2都来自同一信号TI2 的边沿检测,信号相同,同一个TIx输入映射了两个ICx信号。 
TI2FP1和TI2FP2可以分别由连接到的ICx (IC1或是IC2)相对应的控制寄存器设为上升沿或是下降沿触发,这两个ICx信号分别在相反的极性边沿有效。如果TI2FP2设置为上升沿触发,则TI2FP1设置为下降沿触发,二者极性相反。 
CH1,3,4相同。

具体程序: 
include “pbdata.h”

void RCC_Configuration(void); 
void GPIO_Configuration(void); 
void NVIC_Configuration(void); 
void TIM2_Configuration(void); 
void TIM3_Configuration(void); 
void USART_Configuration(void);

int fputc(int ch,FILE *f) 

USART_SendData(USART1,(u8)ch); 
while(USART_GetFlagStatus(USART1,USART_FLAG_TXE)==RESET); 
return ch; 
}

int main(void) 
{

RCC_Configuration(); //配置时钟 
GPIO_Configuration();//IO口配置 
TIM3_Configuration(); 
TIM2_Configuration(); 
NVIC_Configuration(); 
USART_Configuration();

while(1) 
{

if(flag==1) 

flag=0; 
printf(“the duty is %d/r/n”,duty); 
printf(“the frequency is %.2fKHz /r/n”,freq); 


}

void RCC_Configuration(void) 

SystemInit(); 
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_USART1,ENABLE); 
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2|RCC_APB1Periph_TIM3,ENABLE); 
RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE); 
}

void GPIO_Configuration(void) 

GPIO_InitTypeDef GPIO_InitStructure; 
//LED 
GPIO_InitStructure.GPIO_Pin=GPIO_Pin_9;//TX 
GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz; 
GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AF_PP; 
GPIO_Init(GPIOA,&GPIO_InitStructure);

GPIO_InitStructure.GPIO_Pin=GPIO_Pin_10;//RX 
GPIO_InitStructure.GPIO_Mode=GPIO_Mode_IN_FLOATING; 
GPIO_Init(GPIOA,&GPIO_InitStructure);

GPIO_InitStructure.GPIO_Pin=GPIO_Pin_6;//PWM,TIM3_CH1 
GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz; 
GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AF_PP; 
GPIO_Init(GPIOA,&GPIO_InitStructure);

GPIO_InitStructure.GPIO_Pin=GPIO_Pin_1;//TIM2_CH2 
GPIO_InitStructure.GPIO_Mode=GPIO_Mode_IN_FLOATING; 
GPIO_Init(GPIOA,&GPIO_InitStructure); 
}

void TIM2_Configuration(void) 

TIM_TimeBaseInitTypeDef TIM_TimeBaseStruct; 
TIM_ICInitTypeDef TIM_ICInitStructure;

TIM_ICInitStructure.TIM_Channel=TIM_Channel_2;//选择TIM2_CH2,选择输入端 IC2映射到TI2上 
TIM_ICInitStructure.TIM_ICPolarity=TIM_ICPolarity_Rising;//上升沿捕获 
TIM_ICInitStructure.TIM_ICSelection=TIM_ICSelection_DirectTI;//映射到TI2上 
TIM_ICInitStructure.TIM_ICPrescaler=TIM_ICPSC_DIV1;//在捕获输入上每探测到一个边沿执行一次捕获 
TIM_ICInitStructure.TIM_ICFilter=0;//滤波设置,经历几个周期跳变认定波形稳定。(采样高电平,只有连续采集到N个电平是高电平时才认为是有效的,否则低于N个时认为是无效的,N取0x0-0xF) 
TIM_PWMIConfig(TIM2,&TIM_ICInitStructure);//以上是输入捕获配置 
TIM_SelectInputTrigger(TIM2,TIM_TS_TI2FP2);//选择滤波后的TI2FP2输入作为触发源,触发下面程序的复位 
TIM_SelectSlaveMode(TIM2,TIM_SlaveMode_Reset);//从模式控制器被设置为复位模式-选中的触发信号上升沿重新初始化计数器并产生一个更新信号(上升沿一到,TIM2->CNT被清零,每次上升沿来到,CNT都会被清零) 
TIM_SelectMasterSlaveMode(TIM2,TIM_MasterSlaveMode_Enable);//启动定时器的被动触发 
TIM_ITConfig(TIM2,TIM_IT_CC2,ENABLE);//捕获中断打开 
TIM_ClearFlag(TIM2,TIM_IT_CC2);//清除标志位 
TIM_Cmd(TIM2,ENABLE);//使能定时器2 
}

void TIM3_Configuration(void) 

TIM_TimeBaseInitTypeDef TIM_TimeBaseStruct; 
TIM_OCInitTypeDef TIM_OCInitStructure; 
TIM_TimeBaseStruct.TIM_Period=72000;//计数初值 
TIM_TimeBaseStruct.TIM_Prescaler=0;//分频系数 
TIM_TimeBaseStruct.TIM_ClockDivision=0;//时钟分割 
TIM_TimeBaseStruct.TIM_CounterMode=TIM_CounterMode_Up;//向上计数模式

TIM_TimeBaseInit(TIM3,&TIM_TimeBaseStruct);

//TIM3_CH1作为pwm输出 
TIM_OCInitStructure.TIM_OCMode=TIM_OCMode_PWM1; 
TIM_OCInitStructure.TIM_OutputState=TIM_OutputState_Enable; 
TIM_OCInitStructure.TIM_Pulse=36000; 
TIM_OCInitStructure.TIM_OCPolarity=TIM_OCPolarity_High;

TIM_OC1Init(TIM3,&TIM_OCInitStructure);

TIM_OC1PreloadConfig(TIM3,TIM_OCPreload_Enable); 
TIM_ARRPreloadConfig(TIM3,ENABLE); 
TIM_Cmd(TIM3,ENABLE);

}

void NVIC_Configuration(void) 

NVIC_InitTypeDef NVIC_InitStructure;

NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);

NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn; 
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; 
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1; 
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; 
NVIC_Init(&NVIC_InitStructure);

}

void USART_Configuration(void) 

USART_InitTypeDef USART_InitStructure;

USART_InitStructure.USART_BaudRate=115200; 
USART_InitStructure.USART_WordLength=USART_WordLength_8b; 
USART_InitStructure.USART_StopBits=USART_StopBits_1; 
USART_InitStructure.USART_Parity=USART_Parity_No; 
USART_InitStructure.USART_HardwareFlowControl=USART_HardwareFlowControl_None; 
USART_InitStructure.USART_Mode=USART_Mode_Rx|USART_Mode_Tx;

USART_Init(USART1,&USART_InitStructure); 
USART_Cmd(USART1,ENABLE); 
USART_ClearFlag(USART1,USART_FLAG_TC); 
}

//中断程序 
void TIM2_IRQHandler(void) 

if(TIM_GetITStatus(TIM2,TIM_IT_CC2)==Bit_SET) 

float IC2Value=0; 
float DutyCycle=0;

float Frequency=0; 
float pulse=0;

IC2Value=TIM_GetCapture2(TIM2);//获得CCR2的值 
pulse=TIM_GetCapture1(TIM2);//获得CCR1的值 
DutyCycle=pulse/IC2Value; 
Frequency=72000000/IC2Value; 
duty=(u32)(DutyCycle*100); 
freq=(Frequency/1000);

flag=1;

TIM_ClearITPendingBit(TIM2,TIM_IT_CC2); 

}

duty和freq是定义的全局变量 
extern u32 duty; 
extern u16 freq;

u32 duty=0; 
u16 freq=0;

经调试程序可用。频率和占空比都对。频率的设置不要太高,因为printf函数发数所需时间较多,两次捕获的时间间隔短的话可能使printf不能及时地送出数据,造成数据被刷新。更改方法,使用:USART_SendData();函数发数。

其他应用: 
1.测量高电平时间:a,上文中的CCR1就是高电平时间;b,当使用一个通道CH1时,先将触发沿选为为上升沿,产生捕获中断,读取CCR1中的内容,再改变触发沿为下降沿,下降沿到来时捕获,再次读出CCR1的内容,两次相减为高电平时间。 
2.测量脉冲个数:a,开启定时器1的捕获中断,捕获信号边沿(上升沿或下降沿)进中断,count++计数,再开启定时器2的更新中断,定时一定时间进更新中断,读取count值,此为脉冲个数。b,开启外部中断,配置沿触发中断,count++计数,再开启定时器x的更新中断,定时一定时间进更新中断,读取count值,此为脉冲个数。 
3.计算一路信号的频率,可以选择定时器的CH1或CH2(不可同时计算两路频率,否则计算出的频率是后初始化的那个通道代表的信号频率。当然,要同时也可以,每次得到频率后切换通道,将数据通过DMA取走即可),使用PWM输入捕获模式,使用上升沿触发。而CH3和CH4通道则不行,如图2所示,只有红线所指的4个信号连在了从模式控制器上。所以,对于3和4通道,计数器的值不可能在接受到信号上升沿时候,有复位这个动作。 
图2


关键字:stm32  定时器  pwm模式  输入捕获 引用地址:stm32定时器pwm模式输入捕获

上一篇:STM32+MS5611测气压温度例程详解,测试无误
下一篇:STM32 TIM1 做PWM输出问题

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

STM32 外部 SRAM
STM32F103ZET6 自带了 64K 字节的 SRAM,对一般应用来说,已经足够了,不过在一些对内存要求高的场合,STM32 自带的这些内存就不够用了。比如跑算法或者跑 GUI 等,就可能不太够用 IS62WV51216 简介 IS62WV51216 是 ISSI(Integrated Silicon Solution, Inc)公司生产的一颗 16 位宽 512K(512*16,即 1M 字节)容量的 CMOS 静态内存芯片。该芯片具有如下几个特点: l 高速。具有 45ns/55ns 访问速度。 l 低功耗。 l TTL 电平兼容。 l 全静态操作。不需要刷新和时钟电路。 l 三态输出。 l 字节控制功能。支
[单片机]
STM32中使用printf打印串口数据的实现原理及方法
STM32中使用printf打印串口数据的实现原理 在C库中,printf()等输出流函数都是通过fputc()这个函数实现的,所以我们通过重映射的方式,修改这个函数的定义使它输出在STM32的寄存器中,便可以实现使用printf()函数在STM32串口上输出数据的功能。 盘点一下实现printf()函数打印字符串重定义到USART1的方法 方法一 1添加包含printf()函数的头文件:#include “stdio.h” 2.重写 stdio.h 头文件中的 int fputc(int ch, FILE *f) 函数 3.将该函数” int fputc(int ch, FILE *f) “放在main()函数能够调用到的文
[单片机]
STM32定时器时间的计算方法
STM32中的定时器有很多用法: (一)系统时钟(SysTick) 设置非常简单,以下是产生1ms中断的设置,和产生10ms延时的函数: void RCC_Configuration(void) { RCC_ClocksTypeDef RCC_ClockFreq; SystemInit();//源自system_stm32f10x.c文件,只需要调用此函数,则可完成RCC的配置. RCC_GetClocksFreq(&RCC_ClockFreq); //SYSTICK分频--1ms的系统时钟中断 if (SysTick_Config(SystemFrequency / 1000)) { while (1); // Capt
[单片机]
STM32 文件系统 fatfs 移植笔记详解
1、内存和Flash介绍 stm32 的 flash 地址起始于 0x0800 0000,结束地址是 0x0800 0000 加上芯片实际的 flash 大小,不同的芯片 flash 大小不同。 RAM 起始地址是 0x2000 0000,结束地址是 0x2000 0000 加上芯片的 RAM 大小,不同的芯片RAM也不同。 Flash 中的内容一般用来存储代码和一些定义为 const 的数据,断电不丢失,RAM 可以理解为内存,用来存储代码运行时的数据,变量等等,掉电数据丢失。 stm32 将外设等都映射为地址的形式,对地址的操作就是对外设的操作。 stm32 的外设地址从 0x4000 0000 开始,可以
[单片机]
<font color='red'>STM32</font> 文件系统 fatfs 移植笔记详解
一文知道STM32 GUI的应用
整体上讲,很多STM32芯片内置了功能强大的用于加速图形处理的硬件加速器,借助它们一方面可以大大减轻CPU负荷,以节省CPU处理带宽去应对其它任务,另一方面,在节省内存同时还能保障动画或视频播放更为流畅。这些硬件图形加速器分别是STM32 Chrom-ART 加速器,或称DMA2D,是个专门用于二维图形操作处理的DMA;硬件JPEG 编解码器,用于对JPEG图像的编解码;STM32 Chrom-GRC,它是个内存管理单元,用于优化非方形图形显示的存储开销。 到目前为止,由于支持图形显示的STM32系列或料号很多,有时想基于STM32 的GUI应用做选型,可能要费一番功夫。这里有个表格,汇总了目前直接支持各类显示接口的STM32
[单片机]
一文知道<font color='red'>STM32</font> GUI的应用
STM32(Cortex-M3)中NVIC(嵌套向量中断控制)的理解
简介:STM32(Cortex-M3)中有两个优先级的概念:抢占式优先级和响应优先级,也把响应优先级称作“亚优先级”或“副优先级”,每个中断源都需要被指定这两种优先级。 1. 何为占先式优先级(pre-emption priority) 高占先式优先级的中断事件会打断当前的主程序/中断程序运行—抢断式优先响应,俗称中断嵌套。 2. 何为副优先级(subpriority) 在占先式优先级相同的情况下,高副优先级的中断优先被响应; 在占先式优先级相同的情况下,如果有低副优先级中断正在执行, 高副优先级的中断要等待已被响应的低副优先级中断执行结束后才能得到响应—非抢断式响应(不能嵌套)。 3. 判断中断是否会被响
[单片机]
<font color='red'>STM32</font>(Cortex-M3)中NVIC(嵌套向量中断控制)的理解
STM32使用FSMC驱动8080时序CH395的一些问题
CH395L是带并口的版本,支持串口、SPI、并口三种模式,网卡类似于内置TCP协议的W5500,用户只需读取一些参数设置socket就可以完成网络通信。CH395具有并口模式,这是个特色,在对速度要求高的场合,并口比SPI等串行方式快很多,在使用stm32f103以fsmc硬件并口驱动ch395时参考秉火和战舰的驱动LCD的例程,因为都是8080时序的设备,方法相似。 在配置过程中,发现在以杜邦线连接ch395模块的情况下, readWriteTiming.FSMC_AddressSetupTime = 0x03; readWriteTiming.FSMC_DataSetupTime = 0x08; 这两
[单片机]
<font color='red'>STM32</font>使用FSMC驱动8080时序CH395的一些问题
怎么使用C语言控制硬件
C语言的应用编程在单片机的领域占了很大一部分,使用的比较多的51单片机和STM32单片机都可以使用MDK软件编写固件。 单片机烧写了固件后可以点亮LED灯,可以驱动ADC检测电压,也可以驱动蜂鸣器发声,这就是简单地控制硬件。稍微复杂一点的,可以驱动NRF2401进行无线的连接,也可以使用ESP8266这类wifi芯片连接网络。 接下来,简单地讲讲如何使用C语言控制硬件。 1、电路连接 简单的模块可以直接使用高低电平来控制,比如红外线发射模块,当你在驱动引脚上的电压达到3.3v,就能发出红外线;然后将电平设置为0v,红外线发射就停止了。 一般而言,单片机的引脚输出电压能够达到3.3v,也是可以点亮红外线LED,但是可能会导致
[单片机]
小广播
添点儿料...
无论热点新闻、行业分析、技术干货……
设计资源 培训 开发板 精华推荐

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

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

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