恩~这是博主的第一次发博客,用来记录博主几个小时之内感到困难的问题,写的不好,还请大家指正!
今天,本来想用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;
}