什么是通用定时器:
通用定时器除了有延时和定时中断功能外还有输出比较输入捕获的功能。
通用定时器有那些:
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 可以避免影响后面的功能。