二赛君 | Kaspar.s

Studies serve for delight,for ornament,and for ability! ----Francis Bacon

STM32 红外复制程序及思路-完结篇

之前写过一篇文章,STM32 红外复制程序及思路  有些许的不足之处。

在不断修改及完善下,总结及改进如下:

  • 输入捕获中断函数改进。捕获中断脉冲获取函数,使用临时数组。
  • 增加睡眠低功耗模式。
  • 接收数组判断,增加学习发送可靠性。比如接收指令错误,地址错误等问题。
  • 红外发射优化

当然仍有许多需要改进的地方,比如数据压缩处理,增加存储空间;云端红外码库的链接等,现在世面上已有多种红外学习模块,技术已很成熟了,很值得去研究和学习。

1 输入捕获中断函数改进

之前使用两个长度300的数组,占用空间。于是想到用一个长度为2的数组代替,交替获取定时器数值,再根据上升沿还是下降沿判断,处理获得的值存储在长度300的临时数组中,完成红外脉冲信号的学习。具体如下图:

《STM32 红外复制程序及思路-完结篇》

红外接收二极管接收并调制输出至单片机的信号波形为上图中的接收脉冲。

规定下降沿标识flag=0,定时器保存在临时数组temp_count[0]中,上升沿标识flag=1,定时器值保存咋临时数组temp_count[1]中。

之后进行计算,如果temp_count[0]与temp_count[1]均不为0,此时,如果flag=1,说明在下降沿部分,计算temp_count 差值,并将temp_count[1]置0;如果flag=0,说明在上升沿部分,计算temp_count 差值,并将emp_count[0]置1;以此不断轮流置为0,完成数组之间脉冲宽度的学习。实现代码如下:

 if (flag== 0)
{ 
TIM1_ICInitStructure.TIM_Channel = TIM_Channel_1;
TIM1_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_Rising;  
TIM1_ICInitStructure.TIM_ICSelection = TIM_ICSelection_DirectTI;
TIM1_ICInitStructure.TIM_ICPrescaler = TIM_ICPSC_DIV1;
TIM1_ICInitStructure.TIM_ICFilter = 0x0;      
TIM_ICInit(TIM1, &TIM1_ICInitStructure);
temp_count[0] = TIM_GetCounter(TIM1);
flag=1;
}
else
{
TIM1_ICInitStructure.TIM_Channel = TIM_Channel_1;
TIM1_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_Falling;      
TIM1_ICInitStructure.TIM_ICSelection = TIM_ICSelection_DirectTI;
TIM1_ICInitStructure.TIM_ICPrescaler = TIM_ICPSC_DIV1;
TIM1_ICInitStructure.TIM_ICFilter = 0x0;     
TIM_ICInit(TIM1, &TIM1_ICInitStructure);
temp_count[1] = TIM_GetCounter(TIM1);
flag=0;
}
if( temp_count[0] != 0 && temp_count[1] != 0 && flag == 0)
{
if (temp_count[1] > temp_count[0])
{
pluse[num_pluse-1]= temp_count[1] - temp_count[0] ;
}
else
{
pluse[num_pluse-1] = 65535*1 - temp_count[0] + temp_count[1];
}
temp_count[0] = 0 ;
}
if(temp_count[0] != 0 && temp_count[1] != 0 && flag ==1 )
{
if (temp_count[0] > temp_count[1])
{
pluse[num_pluse-1]= temp_count[0] - temp_count[1] ;
}
else
{
pluse[num_pluse-1] = 65535*1 - temp_count[1] + temp_count[0];
}
temp_count[1] = 0 ;
}
if ( num_pluse < 300 )
{
num_pluse++;
}

 

在红外学习指令阶段,一定要加入学习等待时间,否则可能导致脉冲无法完全学习完成。

2 红外发射部分

红外发射部分比较简单,从相应地址读取数组,通过控制载波定时器的开启与关闭发射。载波频率为38KHz,适应大部分红外设备频率。有一点需要注意的是,在结束之后,引脚的高低电平可能时高时低,这在各大贴吧都有解决办法,笔者同样遇到此问题。导致发射管发热,严重有烧坏发射管的危险。

运用函数强制输出低电平,运用库函数重新开启PWM

for ( int i=0 ; i<300 ; i++)
{ if ( send_temp[i] != 0 )
{
if (i % 2 == 0)  
{       TIM_SelectOCxM( TIM2 , TIM_Channel_2 , TIM_OCMode_PWM1);
TIM_CCxCmd(TIM2 , TIM_Channel_2, TIM_CCx_Enable);
TIM_Cmd(TIM2,ENABLE);
delay_us( send_temp[i]*10 );
TIM_Cmd(TIM2,DISABLE);
TIM_ForcedOC2Config(TIM2, TIM_ForcedAction_Active); 
}
else
{
TIM_Cmd(TIM2,DISABLE);
delay_us( send_temp[i]*10 );
TIM_ForcedOC2Config(TIM2, TIM_ForcedAction_Active);  
}
} }

 

主要调用了TIM_ForcedOC2Config()与TIM_SelectOCxM()函数,至于其他功能不做多述。

点赞

Leave a Reply

Your email address will not be published. Required fields are marked *