通用定时器的使用(1) 按键控制LED的亮度 呼吸灯

本文介绍了如何使用STM32的通用定时器TIM3的输出比较功能,如PWM控制LED3的亮度,并提供了两种实现方法,包括基本的亮度控制和呼吸灯效果。同时,作者强调了优化主函数以避免长时间延时对其他功能的影响。
摘要由CSDN通过智能技术生成

什么是通用定时器:

        通用定时器除了有延时和定时中断功能外还有输出比较输入捕获的功能。

        通用定时器有那些:

                TIM2、TIM5:有四个通道可配置  TIM9、TIM12有两个通道可配置

                TIM10、TIM11、TIM13、TIM14有一个通道可配置

今天主要分享的是通用定时器输出比较功能:

eg1:TIM3通道1输出PWM控制LED3

        原理:通用定时器驱动IO口输出PWM波,让LED亮(具体寄存器的配置参考中文手册)

PS:

什么是PWM波:一段有规律的高低电平的波形!!!周期一定通过改变占空比来改变有效电平的持续时间,改变占空比就是改变CCRx寄存器的值(输出比较寄存器)

定时器驱动IO口输出PWM波的总体程序思路:

初始化配置

{

        /*IO控制器配置*/

        /*定时器控制器通道配置*/

}

详细配置思路

{

        /*IO控制器配置*/

        //端口时钟使能

        //输出模式配置

        //输出类型配置

        //输出速度配置

        //复用功能控制器配置

        /*定时器控制器通道配置*/

        //定时器时钟使能(选择内核时钟)

        //CR1

        //SMCR

        //EGR

        //CCMRx

        //CCER

        //PSC

        //ARR

        //CCR1

}

/*****按键控制LED3的亮度(初始化配置)*****/
void Tim3_ch1_pwm(void)
{
	/*IO控制器配置*/
	//端口时钟使能
	RCC->AHB1ENR |= (1<<2);
	//端口模式配置-------复用模式
	GPIOC->MODER &= ~(3<<12);
	GPIOC->MODER |= (2<<12);
	//输出类型
	GPIOC->OTYPER &= ~(1<<6);
	//输出速度
	GPIOC->OSPEEDR &= ~(3<<12);
	//上下拉
	GPIOC->PUPDR &= ~(3<<12);
	//复用功能寄存器
	GPIOC->AFR[0] &= ~(0xf<<24);
	GPIOC->AFR[0] |= (2<<24);
	
	/*通用定时器控制器配置*/
	//定时器时钟使能
	RCC->APB1ENR |= (1<<1);
	//CR1
	TIM3->CR1 |= (1<<7);     //重载影子寄存器
	TIM3->CR1 &= ~(3<<5);    //边沿对齐模式
	TIM3->CR1 &= ~(1<<4);    //递增计数
	TIM3->CR1 &= ~(1<<3);    //循环计数模式
	TIM3->CR1 &= ~(1<<1);
	//SMCR
	TIM3->SMCR &= ~(7<<0);   //选择内部时钟模式
	//CCMRx
	TIM3->CCMR1 &= ~(3<<0);  //通道1定为输出
	TIM3->CCMR1 |= (1<<3);   //比较寄存器的影子寄存器
	TIM3->CCMR1 &= ~(7<<4);
	TIM3->CCMR1 |= (6<<4);   //PWM1
	//CCER
	TIM3->CCER |= (1<<1);    //低电平有效
	//PSC
	TIM3->PSC = 84-1;
	//ARR
	TIM3->ARR = 1000-1;
	//CCRx
	TIM3->CCR1 = 100;
	//EGR
	TIM3->EGR |= (1<<0);    //人为产生更新事件
	
	
	//通道1使能
	TIM3->CCER |= (1<<0);
	//计数器使能
	TIM3->CR1 |= (1<<0); 
	
}


/*****按键控制LED3的亮度(主函数)*****/

int main(void)
{
	u8 key;
	Tim3_ch1_pwm();
	key_init();
	
	
	while(1)
	{
		key = key_scan();
		if(key == 1  &&  TIM3->CCR1<1000)
		{
			TIM3->CCR1 += 100;
		}
		else if(key == 2 && TIM3->CCR1>0)
		{
			TIM3->CCR1 -= 100;
		}	
	}
	
	
	return 0;
}

eg2:TIM3通道1输出PWM控制LED3实现呼吸灯效果

初始化函数和上面一样

/******TIM3通道1输出PWM控制LED3实现呼吸灯效果(主函数)*****/
int main(void)
{
    tim3_ch1_pwm();

	while(1)
	{
		u32 i;
		for(i=0;i<1000;i++)//慢慢变亮
		{
			TIM3->CCR1=i;
			TIM3->CCR2=i;
			delay_ms(1);
		}
	    for(i=0;i<1000;i++)//慢慢变暗
		{
		    TIM3->CCR1=(1000-i);
		    TIM3->CCR2=(1000-i);
			delay_ms(1);
    	}
	}

	
	return 0;
}

这种方法可以实现呼吸灯效果,但是不太友好主程序延时太长,跳出两个for循环,跑一层主函数就至少2s钟了。 如果主程序中后面有类似按键这种功能函数的话,可能会导致按键不好使了,所以要将程序优化 避免主函数有过长的延时!!!!!!!

/******TIM3通道1输出PWM控制LED3实现呼吸灯效果(主函数)*****/
int main(void)
{
	u8 tim3_flag=1;
	tim3_ch1_pwm();
	while(1)
	{
		if(tim3_flag==1)
		{
			TIM3->CCR1++;
			delay_ms(1);
			if(TIM3->CCR1==1000)
			{
				 tim3_flag=0;
			}
		}
		if(tim3_flag==0)
		{
			TIM3->CCR1--;
			delay_ms(1);
			if(TIM3->CCR1==0)
			{
				tim3_flag=1;
			}
		}

利用标志位思想!!!优化后的代码跑一层主程序只需要2ms 可以避免影响后面的功能。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值