打印

红外解码程序!!请高手帮忙看看

[复制链接]
16588|111
手机看帖
扫描二维码
随时随地手机跟帖
沙发
贺信|  楼主 | 2009-10-13 16:05 | 只看该作者
我解码时出现了问题!!我想在单片机解码后把数据发到串口调试助手上看是否解码正确!!但串口上没有任何数据,我试过串口发送函数是正确的,所以问题在于解码函数没有把数据传给串口发送函数
下面是我的程序!!请高手们看看,提携一下刚入门的小弟
#include <reg51.h>
#include"initial.h"
#include"IR Decode.h"
#include"UART.h"
//#include"main.h"

#define uchar unsigned char
#define uint unsigned int

bit SendFlag = 0;

/*****************************主函数*************************/

unsigned char uSendData;

void main(void)
{
        InitialTimer0();        //定时器0初始化
        Uart_initial();                //串口初始化
        while(1)
        {
                uSendData = IR_Decode();        //取解码函数返回值
                if(SendFlag ==1)                        //判断发送标志位
                {
                        Uart_send (uSendData);        //串口发送函数
                        SendFlag=0;                                //清发送标志位
                }
        }
}

使用特权

评论回复
板凳
贺信|  楼主 | 2009-10-13 16:07 | 只看该作者
本帖最后由 贺信 于 2009-10-13 16:22 编辑

这是解码函数
我的解码只需要数据前四位Bit就可以了,后面的就不管了,即每来一字节数据我只关心前四位Bit数据

sbit IR_RE   = P3^2;        //红外接受口  (注:这句在main.h 我这里把3.2口当一般IO口用)

#include <reg51.h>
#include "main.h"


#define uchar unsigned char
#define uint unsigned int

uchar  T0Count;                         //定时器计数器
uchar k = 0;                                //中断后数据处理个数计数
extern bit SendFlag ;                //发送标志
        

//**********************红外解码******************************//

uchar IR_Decode()
{
        unsigned char uData = 0;        //处理数据后返回值
        unsigned char uTemp = 0;        //数据为1或0暂存值

        ET1 = 0;                                //关定时器1
        T0Count = 0;                        //定时器计数值清零
        while(IR_RE == 1);      //初始状态下,红外输出脚一直是高电平,等待
        ET1 = 1;                                //当有低电平到来打开定时器
        while(IR_RE == 0);                //低电平等待,T0计数
        if( T0Count > 17)                //电平为高,判断计数时间0.5* 17 = 8.5ms约为9.0ms
        {
                ET1 = 0;
                T0Count = 0;
                ET1 = 1;
                while(IR_RE == 1);  //等待4.5ms的头高电平过去
                if(T0Count > 5)                //超过0.5*5 = 2.5ms,即视为数据头判断完
                {
                        ET1 = 0;
                        T0Count = 0;
                        for(k=0;k<4;k++)
                        {
                                while(IR_RE == 0);        //等待560ms低电平过去,因为只判断数据高电平
                                ET1 = 0;                        
                                T0Count = 0;                //高电平时清计数值开定时器
                                ET1 = 1;
                                while(IR_RE == 1);        //高电平等待计时
                                if(T0Count > 2)                //根据波形长度判定码值为0或1
                                uTemp = 1;
                                else
                                uTemp = 0;
                                uData |= (uTemp<<k);         //保存键值
                        }
                        return uData;                        //判断四位后返回得到的值
                        SendFlag = 1;                        //置位发送标志
                }
        }
        else
        {
                T0Count = 0;
                return uData = 0;
        }
        
}
/**************************定时器0中断******************

定时500uS,用来解码高低电平

********************************************************/

void timer0() interrupt 1
{


T0Count++;

TH1 = 0xfe;        //定时500uS
TL1 = 0x33;

}

使用特权

评论回复
地板
贺信|  楼主 | 2009-10-13 16:14 | 只看该作者
很困惑中!!前辈们指点一下呀!!

使用特权

评论回复
5
程序匠人| | 2009-10-13 16:21 | 只看该作者
我解码时出现了问题!!我想在单片机解码后把数据发到串口调试助手上看是否解码正确!!但串口上没有任何数据,我试过串口发送函数是正确的,所以问题在于解码函数没有把数据传给串口发送函数
下面是我的程序!!请 ...
贺信 发表于 2009-10-13 16:05


“没有任何数据”是什么意思?你是在什么样条件下向串口传数据?

使用特权

评论回复
6
程序匠人| | 2009-10-13 16:31 | 只看该作者
你的解码程序居然是独占式的?

如果只是测试程序也到算了。如果是正式写项目程序,最好还是用中断来检测,实时性会更好些。

使用特权

评论回复
7
贺信|  楼主 | 2009-10-13 16:35 | 只看该作者
本帖最后由 贺信 于 2009-10-13 16:36 编辑

不好意思,语言不是很清楚
我的意思是我的发射信号(这个信号我一直在示波器扫描,存在如上面截图)经1838的OUT脚输入到P3.2给单片解码,但在串口调试助手上没有任何数据,也就是这句 uSendData = IR_Decode();        //取解码函数返回值  没有得到值!所以没有发射(也有可能SendFlag ==1有错),总之是解码出错。当我把uSendData = IR_Decode(); 改为uSendData = 0x27或其它,并屏蔽SendFlag ==1,再看串口调试助手它就有27这值

使用特权

评论回复
8
贺信|  楼主 | 2009-10-13 16:41 | 只看该作者
6# 程序匠人

我现在只想确认这种解码方法有没有错,实际用时我肯定是用中断,所以才会有sbit IR_RE   = P3^2;    P3.2口就是中断脚
恳切请求指导一下这程序是不是哪里出问题了???我搞了好久不知道问题在那????

使用特权

评论回复
9
贺信|  楼主 | 2009-10-13 16:53 | 只看该作者
殷切期待高手拉小弟一把!!!谢谢啦!!!!!:dizzy:

使用特权

评论回复
10
zhongce09| | 2009-10-13 17:06 | 只看该作者
热切期待高手解出!!偶也不懂这个嚎

使用特权

评论回复
11
zhongce09| | 2009-10-13 17:06 | 只看该作者
热切期待高手解出!!

使用特权

评论回复
12
zhongce09| | 2009-10-13 17:06 | 只看该作者
偶也不懂这个嚎

使用特权

评论回复
13
有风| | 2009-10-13 17:07 | 只看该作者
我解码时出现了问题!!我想在单片机解码后把数据发到串口调试助手上看是否解码正确!!但串口上没有任何数据,我试过串口发送函数是正确的,所以问题在于解码函数没有把数据传给串口发送函数
下面是我的程序!!请 ...
贺信 发表于 2009-10-13 16:05


定时500us直接用个Delay500us()函数来处理吧,
没必要用中断做,这样反而不准确,500us很短,
进出中断要时间的..
检测到数据头后,
高电平时间
>(560us+1680us)/2=1120us为1,
<1120us为0.

使用特权

评论回复
14
有风| | 2009-10-13 17:08 | 只看该作者
哎,写一个太简单了...

使用特权

评论回复
15
贺信|  楼主 | 2009-10-13 17:13 | 只看该作者
定时500us直接用个Delay500us()函数来处理吧,
没必要用中断做,这样反而不准确,500us很短,
进出中断要时间的..
检测到数据头后,
高电平时间
>(560us+1680us)/2=1120us为1,
...
有风 发表于 2009-10-13 17:07

延时我也用过,就是没有正确解码,我才改用定时的!!!
现在的关键是我不知道这程序为什么没有返回值????串口调试助手上没有数据呀!!!!
改为uSendData = 0x01或其它,并屏蔽SendFlag ==1,再看串口调试助手它就有数据呀!!!

使用特权

评论回复
16
程序匠人| | 2009-10-13 17:19 | 只看该作者
说实话,凭肉眼抓错误是很困难的。不过,你可以自己调试、验证、推理。只要方法恰当,没有找不出来的BUG。

1、根据你的描述,“串口调试助手上没有任何数据”,那就是“串口发送函数”没有被执行。也就是说,SendFlag 没有被置位。那么问题就是在IR_Decode函数里。

2、为什么SendFlag 没有被置位?——因为程序没有走到这里。所以,可以在IR_Decode程序里,程序不同节点(必经之处)上设置断点,看程序能否走到。

3、如果你没有仿真环境。那就要另想办法了。

使用特权

评论回复
17
程序匠人| | 2009-10-13 17:21 | 只看该作者
请汇报一下你的开发工具和条件。

使用特权

评论回复
18
贺信|  楼主 | 2009-10-13 17:21 | 只看该作者
16# 程序匠人

要是有仿真就好了!!我是直接在单片机上实验的!!!困惑中!!!!

使用特权

评论回复
19
程序匠人| | 2009-10-13 17:25 | 只看该作者
//**********************红外解码******************************//

uchar IR_Decode()
{
        unsigned char uData = 0;        //处理数据后返回值
        unsigned char uTemp = 0;        //数据为1或0暂存值

        ET1 = 0;                                //关定时器1
        T0Count = 0;                        //定时器计数值清零
        while(IR_RE == 1);      //初始状态下,红外输出脚一直是高电平,等待
        ET1 = 1;                                //当有低电平到来打开定时器
        while(IR_RE == 0);                //低电平等待,T0计数
        if( T0Count > 17)                //电平为高,判断计数时间0.5* 17 = 8.5ms约为9.0ms
        {
                ET1 = 0;
                T0Count = 0;
                ET1 = 1;
                while(IR_RE == 1);  //等待4.5ms的头高电平过去
                if(T0Count > 5)                //超过0.5*5 = 2.5ms,即视为数据头判断完  //在调试时,先把这些无关紧要但是有可能导致程序无法顺利执行的代码去掉                {
                        ET1 = 0;
                        T0Count = 0;
                        for(k=0;k<4;k++)
                        {
                                while(IR_RE == 0);        //等待560ms低电平过去,因为只判断数据高电平
                                ET1 = 0;                        
                                T0Count = 0;                //高电平时清计数值开定时器
                                ET1 = 1;
                                while(IR_RE == 1);        //高电平等待计时
                                if(T0Count > 2)                //根据波形长度判定码值为0或1
                                uTemp = 1;
                                else
                                uTemp = 0;
                                uData |= (uTemp<<k);         //保存键值
                        }
                        return uData;                        //判断四位后返回得到的值
                        SendFlag = 1;                        //置位发送标志
                }
        }
        else
        {
                T0Count = 0;
                return uData = 0;
        }
        
}

使用特权

评论回复
20
有风| | 2009-10-13 17:25 | 只看该作者
本帖最后由 有风 于 2009-10-13 17:26 编辑
延时我也用过,就是没有正确解码,我才改用定时的!!!
现在的关键是我不知道这程序为什么没有返回值????串口调试助手上没有数据呀!!!!
改为uSendData = 0x01或其它,并屏蔽SendFlag ==1,再看串口调试助 ...
贺信 发表于 2009-10-13 17:13


if(T0Count > 2)                //根据波形长度判定码值为0或1
   uTemp = 1;
else
  uTemp = 0;

T0Count > 2 相当于T0Count >=3, 就是说高电平时间要>=500*3=1500us,
不正确的,1的高电平时间是1680us,如果信号有一点偏移,变成1480us,
加上你那500us的延时很有水分,就检测不到1了.
搞个100us的延时函数,以11为分界点,这样子精确一点的.

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

66

主题

305

帖子

0

粉丝