高级会员

- 积分
- 777
- 金钱
- 777
- 注册时间
- 2015-3-14
- 在线时间
- 74 小时
|
由于最近案子的缘故,需要一个红外解码的程序。在网上也看到了其他人写的程序,当然也看到了原子哥的STM32F103的例程。感觉他们的解码要么复杂,要么采用了高大上的输入捕获功能,这样的解码方式感觉不太友好。于是自己思索一番,编写了一个基于定时循环执行的解码程序,就是只要定期执行就能解码的程序。这样的解码程序最大的优点就是不占用CPU资源,不需要延时函数,另外移植起来也是so easy! 解码程序主要使用了两个外部变量,一个是ir_decode_ok_flag 解码成功标志位,一个是ir_code[4]码值保存变量。
使用方法,就是定时100us执行一次就可以了。当然其他定时时间间隔也是可以的,需要修改一下同步码、位码的时间上下限值。
解码函数主体部分:
本代码,引导码 4.5ms低电平 + 4.5ms高电平
位码0: 560us低电平 + 560us高电平
位码1 :560us低电平 + 1680us高电平
#define IR_IN PAin(2) // IR引脚
// 红外解码程序,100us定期执行就可以了
void Ir_Decode(void)
{
static unsigned char l_cnt = 0; // 低电平时间计数
static unsigned char h_cnt = 0; // 高电平时间计数
static unsigned char l_cnt_save = 0; // 保存低电平时长
static unsigned char h_cnt_save = 0; // 保存高电平时长
static unsigned char falling_edge_valid_flag = RESET; // IR电平由高变低标志位
static unsigned char rcv_sync_ok_flag = RESET; // 同步码接收成功标志位
static unsigned char bit_value = 0; // 位解码值
static unsigned char bit_rcv_cnt = 0; // 位接收个数变量
if( RESET == IR_IN )
{
if( 0 == l_cnt ) // IR由高变低后立马记录上次测得的高电平时长
{
h_cnt_save = h_cnt;
falling_edge_valid_flag = SET;
}
l_cnt ++;
if( l_cnt > 250 ) // 防止计数溢出
{
l_cnt = 250;
}
h_cnt = 0; // 计数清零
}
else
{
if( 0 == h_cnt ) // IR由低变高后立马记录上次测得的低电平时长
{
l_cnt_save = l_cnt;
}
h_cnt ++;
if( h_cnt > 250 ) // 防止计数溢出
{
h_cnt = 250;
}
l_cnt = 0; // 计数清零
}
if( SET == falling_edge_valid_flag )
{
falling_edge_valid_flag = RESET;
/* 位解码 */
if( ((l_cnt_save >= 3)&&(l_cnt_save <= 7)) && // 560us低电平, 560us高电平
((h_cnt_save >= 3)&&(h_cnt_save <= 7)) )
{
bit_value = 0;
}
else if( ((l_cnt_save >= 3)&&(l_cnt_save <= 7)) && // 560us低电平,1680us高电平
((h_cnt_save >= 15)&&(h_cnt_save <= 18)) )
{
bit_value = 1;
}
else
{
bit_value = 2;
}
if( SET == rcv_sync_ok_flag )
{
if((1 == bit_value) || (0 == bit_value) )
{
if( bit_rcv_cnt < 8 )
{
ir_code[0] |= (bit_value<< (bit_rcv_cnt%8));
}
else if( bit_rcv_cnt < 16 )
{
ir_code[1] |= (bit_value<< (bit_rcv_cnt%8));
}
else if( bit_rcv_cnt < 24 )
{
ir_code[2] |= (bit_value<< (bit_rcv_cnt%8));
}
else if( bit_rcv_cnt < 32 )
{
ir_code[3] |= (bit_value<< (bit_rcv_cnt%8));
}
if( bit_rcv_cnt >= 31 )
{
ir_decode_ok_flag = SET;
rcv_sync_ok_flag = RESET;
}
bit_rcv_cnt ++;
}
else
{
rcv_sync_ok_flag = RESET; // 位接收错误,重新解码
}
}
if( ((l_cnt_save >= 42)&&(l_cnt_save <= 46)) &&
((h_cnt_save >= 42)&&(h_cnt_save <= 46)) ) // 同步码,4.5ms低电平,4.5ms高电平
{
rcv_sync_ok_flag = SET;
bit_rcv_cnt = 0;
ir_code[0] = 0;
ir_code[1] = 0;
ir_code[2] = 0;
ir_code[3] = 0;
}
}
}
解码串口打印结果:
Ir_Decode红外解码程序.zip
(7.07 MB, 下载次数: 180)
|
|