stm32f103采用高级定时器1发固定数量PWM脉冲

恩~这是博主的第一次发博客,用来记录博主几个小时之内感到困难的问题,写的不好,还请大家指正!

今天,本来想用TIM1发一个38KHZ的脉冲来驱动红外发射管的(就是简单的发送,无需协议)。可是,必须每次发送之后,必须延迟一段时间,暂定500ms。在这段延时中,是不需要PWM波的。

开始,我想的还挺简单。直接开启关闭定时器就好了。

void IR_contral(void)
{
        TIM1_ENABLE;//开启定时器
	delay_us(3600);//延时,有就好了
	TIM1_DISABLE;//关闭定时器
}
	

可是,用示波器一看,IO口的脉冲电平输出根本就不是恒定的,会有波动。至于为什么,大家想一下就明白了,是由于程序运行的时间问题。

于是我就上网百度 “STM32定时器输出指定脉冲个数”,于是一大堆答案就出来了。可是仔细一看,大部分都是“定时器主从方式输出可控个数的PWM脉冲”。这就很麻烦了,还要用到两个定时器。本人有点不耐烦了,仔细想了想。便有了现在的想法。通过TIM1的更新中断来控制脉冲个数(尽量在几十个以内,几个脉冲就更好了),并达到指定个数之后,关闭定时器。

好,现在上正菜。

TIM1.C

/**
***TIM1 PWM部分初始化 时钟选择为APB2的2倍,而APB2为64M//TIM2k 128MHZ
***PWM输出初始化,
***arr:自动重装值
***psc:时钟预分频数
**/
//用于IR红外的驱动                                   
void TIM1_PWM_Init(u16 arr,u16 psc)			         
{	//PA8--T1_CH2	PA9--T1_CH1
	//此部分需手动修改IO口设置
	RCC->APB2ENR|=1<<11;	//使能TIM1时钟
	RCC->APB2ENR|=1<<2;    	//使能PORTA时钟	    
	
	GPIOA->CRH&=0XFFFFFF00;	//PA8/9输出
	GPIOA->CRH|=0X000000BB;	//复用功能输出 	  	 
//	默认映像管脚,无需配置   
//	RCC->APB2ENR|=1<<0;     //开启辅助时钟	   
//	AFIO->MAPR&=0XFFFFF3FF; //清除MAPR的[11:10]
//	AFIO->MAPR|=1<<11;      //部分重映像,TIM3_CH2->PB5

	TIM1->ARR=arr;			//设定计数器自动重装值 
	TIM1->PSC=psc;			//预分频器不分频
	   
	TIM1->CCMR1|=7<<4;  	//CH1 PWM2模式//	TIM1->CCMR1&=~(7<<4);
	TIM1->CCMR1|=1<<3;
	TIM1->CCER|=1<<0;   	//通道1 输出使能,默认高电平有效
	   
	TIM1->CCMR1|=7<<12;  	//CH2 PWM2模式	//TIM1->CCMR1&=~(7<<12);	 
	TIM1->CCMR1|=1<<11; 	//CH2预2装载使能	
	TIM1->CCER|=1<<4;   	//通道2 输出使能,默认高电平有效
	
	TIM1->DIER|=1<<0;   //允许更新中断	
	TIM1->RCR	= 0;//高级定时器配置输出,必须配置,配置该值为0则每次更新溢出都会中断
	
	TIM1->CR1=0x0080;   	//ARPE使能 自动重装载预装载是使能
	TIM1->CR1|=0x01;    	//使能定时器2	

	TIM1->BDTR |= 1<<15;//高级定时器配置输出,必须配置
	
  	MY_NVIC_Init(1,2,TIM1_UP_IRQn,2);//抢占1,子优先级3,组2

} 
//定时器1中断服务程序	 
void TIM1_UP_IRQHandler(void)
{ 	
	static u8 count = 0;//PWM脉冲个数控制
	if(TIM1->SR&0X0001)//溢出中断
	{
		count++;
		if(count >= 6)//6个脉冲之后,关闭定时器
		{
			count = 0;
			TIM1_DISABLE;
		}
	}				   
	TIM1->SR&=~(1<<0);//清除中断标志位 	    
}

main.c

int main(void)
{	
	Stm32_Clock_Hsi_Init(16);
	delay_init(72);	   	 			//延时初始化  	
	
	IR_init();
	
	contralIR_PWM(500);
 	while(1)
	{  
            IR_contral();//每隔500ms就使能TIM1,TIM1发出6个PWM波脉冲之后就关闭TIM1
            delay_ms(500);
        }
}

IR.c

void IR_init(void)
{
	TIM1_PWM_Init(1000-1,2-1);    //PWM输出,根据自己测量的实际时钟频率,修改,2分频就够
	
	RCC->APB2ENR|=1<<3;    	//使能PORTB时钟	    PB14/15	浮空输入
	GPIOB->CRH&=0X00FFFFFF;
	GPIOB->CRH|=0X44000000;
}  
 void IR_contral(void)
{
        TIM1_ENABLE;//开启定时器
	delay_us(3600);//延时,有就好了
	TIM1_DISABLE;//关闭定时器
}

void contralIR_PWM(u16 value)//
{
	TIM1->CCR1 = value;
	TIM1->CCR2 = value;
}


猜你喜欢

转载自blog.csdn.net/qq_39608070/article/details/80990207