zoukankan      html  css  js  c++  java
  • STM32定时器输出、捕获PWM

    硬件:德飞莱STM32F407
    功能:TIM4_CH1->PB6输出PWM,TIM3_CH1->PC6捕获高电平时间

    #include "timer.h"
    
    void TIM4_PWM_Init(void)
    {
    	RCC->APB1ENR|=1<<2;				//打开定时器4时钟
    	RCC->AHB1ENR|=1<<1;				//打开GPIOB的时钟
    	
    	GPIOB->MODER|=2<<12;			//PB6 复用模式
    	GPIOB->OTYPER&=~(1<<6);		//PB6	推挽输出
    	GPIOB->OSPEEDR|=11<<12;		//PB6 输出速度100M
    	GPIOB->PUPDR|=1<<6;				//PB6	上拉
    	
    	GPIOB->AFR[0]|=2<<24;			//PB6	AF2
    	
    	TIM4->ARR=500-1;
    	TIM4->PSC=84-1;						//频率为2K
    	
    	TIM4->CCR1=250;						//高电平时间为500-250    占空比为(500-250)/500=50%
    	
    	TIM4->CCMR1&=~(3<<0);			//配置为输出
    	TIM4->CCMR1|=1<<2;				//输出比较快速使能
    	TIM4->CCMR1|=1<<3;				//输出比较预装载使能
    	TIM4->CCMR1|=7<<4;				//PWM2模式
    	TIM4->CCER|=1<<0;					//输出使能,在相应输出引脚上输出 OC1 信号
    	TIM4->CCER|=1<<1;					//低电平有效
    	TIM4->CR1|=1<<7;					//自动重装载预装载使能
    	TIM4->CR1|=1<<0;					//打开定时器4
    }
    
    
    void TIM3_Cap_Init(void)//TIM3_CH1定时器获取
    {
    	RCC->APB1ENR|=1<<1;				//打开定时器3时钟
    	RCC->AHB1ENR|=1<<2;				//打开GPIOC的时钟
    	
    	GPIOC->MODER|=(2<<12);		//PC6 输入模式
    	GPIOC->PUPDR|=2<<6;				//PC6	下拉
    	
    	GPIOC->AFR[0]|=2<<24;			//PC6	AF2
    	
    	TIM3->ARR=0xFFFFFFFF;					//计数周期设置为最大,计数周期65536
    	TIM3->PSC=72-1;						//计数频率1M,每隔1us捕获一次
    	
    	TIM3->CCMR1|=1<<0;				//配置为输入,映射到T1上
    	TIM3->CCMR1&=~(3<<2);			//不分频
    	TIM3->CCMR1&=~(15<<4);		//不滤波
    	
    	TIM3->CCER|=1<<0;					//使能捕获
    	TIM3->CCER&=~(3<<1);			//上升沿捕获
    	
    	TIM3->DIER|=1<<0;					//允许更新中断
    	TIM3->DIER|=1<<1;					//使能通道1捕获中断
    	
    	TIM3->CR1|=1<<0;					//使能计数器
    	
    	MY_NVIC_Init(2,1,TIM3_IRQn,2);//抢占2,子优先级1,组2	  
    }
    
    u8 TIM3_IRQ_STA=0;
    u32 TIM3_IRQ_VAL=0;
    void TIM3_IRQHandler(void)
    {
    	u16 sr;
    	sr=TIM3->SR;
    	if(!(TIM3_IRQ_STA&0x80))					//未捕获完成
    	{
    		if(sr&0x01)											//产生更新中断,上升沿时间超过一个计数周期65536us,记录超过了几次
    		{
    			if(TIM3_IRQ_STA&0X40)					//已经捕获到高电平了
    			{
    				if((TIM3_IRQ_STA&0X3F)==0X3F)//高电平太长了
    				{
    					TIM3_IRQ_STA|=0X80;				//高电平时间过长,强制标记成功捕获了一次
    					TIM3_IRQ_VAL=0XFFFFFFFF;
    				}else TIM3_IRQ_STA++;
    			}	 
    		}
    		if(sr&0x02)											//产生捕获中断
    		{
    			if(TIM3_IRQ_STA&0x40)					//此时状态为,已经捕获到上升沿,定时器设置为下降沿捕获,且进入中断,也即是捕获到上升沿之后又捕获到下降沿
    			{
    				//标记捕获完成一次
    				TIM3_IRQ_STA|=0x80;					//标记完成一次捕获
    				TIM3_IRQ_VAL=TIM3->CCR1;
    				TIM3->CCER&=~(1<<1);				//配置为上升沿捕获,开始新的一轮捕获
    			}
    			else													//此时进来肯定是只捕获到上升沿,开始计数上升沿时间
    			{
    				TIM3_IRQ_STA=0;							//清空状态寄存器
    				TIM3_IRQ_VAL=0;							//清空计数
    				TIM3_IRQ_STA|=0x40;					//标记捕获到上升沿
    				TIM3->CR1&=~(1<<0);					//关闭定时器,配置捕获的边缘信号
    				TIM3->CNT=0;								//清空计数器
    				TIM3->CCER|=1<<1;						//配置为下降沿捕获
    				TIM3->CR1|=1<<0;						//开启定时器
    			}
    		}
    	}
    	TIM3->SR=0;												//清除中断标志位 
    }
    
    /*main.c*/
    extern u8  TIM3_IRQ_STA;		//输入捕获状态		    				
    extern u32	TIM3_IRQ_VAL;	//输入捕获值
    
    while(1)
    {
    if(TIM3_IRQ_STA&0X80)//成功捕获到了一次高电平
    		{
    			temp=TIM3_IRQ_STA&0X3F; 
    			temp*=0XFFFFFFFF;		 		//溢出时间总和
    			temp+=TIM3_IRQ_VAL;		//得到总的高电平时间
    			printf("HIGH  >> :%lld us
    ",temp);//打印总的高点平时间
    			TIM3_IRQ_STA=0;			//开启下一次捕获
    		}
    }
    
    
  • 相关阅读:
    字符串匹配——KMP算法(C++)
    数论——Fibonacci数列(C++)
    数据结构——线段树之二(C++)
    数据结构——线段树之一(C++)
    最后的最后
    开始的开始
    10.25模拟 保留道路
    10.25模拟 列车调度
    10.25模拟 三角形
    洛谷 P1093 奖学金
  • 原文地址:https://www.cnblogs.com/hhsxy/p/14018408.html
Copyright © 2011-2022 走看看