2719|2

3

帖子

0

TA的资源

一粒金砂(中级)

楼主
 

51代码求助,关于中断的。 [复制链接]

//=====================================================================//
//                      红外遥控器解码程序演示                         //
//  本程序主要将现在比较常用PC9012遥控器进行解码,将解码后的数据通过P2端//
//口的数码管显示出来,为了更好的看到运行过程,特加了三个指示灯用来指示当 //
//前运行状态.P10主要用来闪亮,表示程序正在运行,P11则用来表示接收到数据, //
//P12表示触发内部的定时器操作.P13的闪亮表示正确接收完一个数据.         //
//  程序运行效果: 打开本机电源开关,可以看到P10不停的闪动,按下遥控器的数//
//字键,数码管则显示相应的数字键(1-9).可以看到P11,P12在显示后呈亮状态.则//
//可以接收下一个数据,在上面过程中可以看到P13闪亮了一下.表明上次正确接收//
//到数据.                                                              //
//---------------------------------------------------------------------//
//  开发日期: 2009/01/27   编写红外遥控器解码程序演示的最初代码        //
//  修改日期:                                                          //
//  程序作者: guojun     邮箱:Guojun2008a@126.com                      //
//  程序备注: 此程序仅为表现本机功能而演示用,当用作实际工程时请慎用.   //
//=====================================================================//
#include <AT89x51.h>                      //包含51单片机相关的头文件

unsigned char  code LedShowData[]=        //定义数码管显示数据
         {0x9F,0x25,0x0D,0x99,0x49,       //1,2,3,4,5,
         0x41,0x1F,0x01,0x19,0x03};       //6,7,8,9,0,
static unsigned char RecvData;            //定义接收红外数据变量
static unsigned char CountData;           //定义红外个数计数变量
static unsigned int  AddData;             //定义自增变量
static unsigned int LedFlash;             //定义闪动频率计数变量
#define uint    unsigned int                          //重定义无符号整数类型
#define uchar   unsigned char                         //重定义无符号字符类型

unsigned char LeadCode;                   //定义红外脉冲引导码标志
unsigned char ReceiveBit;                 //定义接收位记数器
unsigned char DataBuffer[4];              //定义接收数据缓存变量
unsigned char RecvSuccess=0;              //定义接收数据成功标志位
uchar temp;
sbit M1A=P0^0;                                        //定义电机1正向端口
sbit M1B=P0^1;                                        //定义电机1反向端口
sbit M2A=P0^2;                                        //定义电机2正向端口
sbit M2B=P0^3;  
sbit led=P1^6;
sbit LeftLed=P2^0;                                    //定义前方左侧指示灯端口
sbit RightLed=P0^7;                                      //定义电机2反向端口
sbit RunLed=P1^0;                         //定义运行指示灯变量位
sbit RecvLed=P1^1;                        //定义接收指示灯变量位
sbit InTimeLed=P1^2;                      //定义定时器开始指示灯变量位
sbit ReadyLed=P1^3;                       //定义就绪指示灯变量
sbit IR1=P3^3;                            //定义红外接收端口
#define ShowPort P2                       //定义数码管显示端口
void Delay()                                          //定义延时子程序
{ uint DelayTime=30000;                               //定义延时时间变量
  while(DelayTime--);                                 //开始进行延时循环
                                             //子程序返回
}
void ControlCar(uchar CarType)                        //定义小车控制子程序
{
 M1A=0;                                               //将电机1正向电平置低
 M1B=0;                                               //将电机1反向电平置低
 M2A=0;                                               //将电机2正向电平置低
 M2B=0;                                               //将电机2反向电平置低
 LeftLed=1;                                           //关闭前方左侧指示灯
 RightLed=1;                                          //关闭前方右侧指示灯                    
                      //将此状态延时一段时间
 switch(CarType)                                      //判断小车控制指令类型
 {  case 1: //前进                                    //判断是否是前进
    { M1A=1;                                          //将电机1正向端口置高
      M2A=1;                                          //将电机2正向端口置高
      
      break;                                          //退出判断
    }
    case 2: //后退                                    //判断是否是后退
    { M1B=1;                                          //将电机1反向端口置高
      M2B=1;                                          //将电机2反向端口置高                                 
     
      break;                                          //退出判断
    }
    case 3: //左转                                    //判断是否是左转
    { M1B=1;                                          //将电机1反向端口置高
      M2A=1;                                          //将电机2正向端口置高
     
      break;                                          //退出判断
    }
    case 4: //右转                                    //判断是否是右转
    { M1A=1;                                          //将电机1正向端口置高
      M2B=1;                                          //将电机2反向端口置高
     
      break;                                          //退出判断
    }
    default:                                          //默认情况下的判断
    {
     break;                                           //直接退出判断
    }
 } 
}

void Timer0_IR1() interrupt 1 using 3     //定义红外定时器子程序
 TH0=0xFF;                                //向定时器定时间寄存器填入高八位值
 TL0=0x49;                                //向定时器定时间寄存器填入低八位值
 InTimeLed=!InTimeLed;                    //将定时器指示灯进行取反
 AddData++;                               //自增变量加1
 if(AddData>400)
 {
    ReceiveBit =0;                        //红外接收记数器清零
    AddData =0;                           //计数器清零
    LeadCode =0;                          //引导码记录器请零
    TR0 =0;                               //关定时器0 
    ET0 =0;                               //关闭定时器0中断
 }
}


此帖出自51单片机论坛
点赞 关注
 

回复
举报

3

帖子

0

TA的资源

一粒金砂(中级)

沙发
 

回复 楼主 rfw8797 的帖子

void Int1_IR1() interrupt 2               //定义红外接收中断子程序
{
  if(LeadCode ==0)                        //第一次处理红外脉冲引导码
   {   
            if( (AddData > 35) && (AddData < 50) )  
             {                                //判断红外计数器是否已到达最大值
               LeadCode =0xff;                //引导码记录器标志位定义
               AddData =0;                    //计数器清零
               return;                        //接收引导码成功
             }
            else                              //正常接收情况下开启定时器开时计数   
             {
               TR0=1;                         //开启定时器0
               ET0=1;                         //开定时器0
               return;                        //接收引导码失败
             }
   }
  else                                    //在正常接收情况
   {
            RecvData >>=1;                    //接收到的数据右移1位
            
            if((AddData > 3)&&(AddData < 7))  //判断计数时间
            {
              RecvData &= 0x7f;               //对数据0置数
            }
            else                              //判断数据计数时间
            {
                      if(AddData < 15)            //对数据1置数
                      {
                        RecvData |= 0x80;         //对数据1置数
                      }
            }         
             ReceiveBit++;                    //数据位计数器加1
             AddData =0;                      //时间计数清零
   }
         
  switch(ReceiveBit)                      //根据位计数器进行判断
  {
    case 8:                               //8位时用户编码
               {
                           DataBuffer[0] = RecvData;  //将用户编码放入数据缓存0
                       break;
           }
    case 16:                              //16位时用户编码
           {
                   DataBuffer[1] = RecvData;  //将用户编码放入数据缓存1
                   break;
           }         
    case 24:                              //24位时按键编码
               {      
                   DataBuffer[2] = RecvData;  //将按键编码放入数据缓存2
               break;
           }
    case 32: {                            //32位时按键编码反码
               DataBuffer[3] = RecvData;  //将按键编码放入数据缓存3
               ReceiveBit =0;             //清零位标志计数器
               AddData =0;                //时间记录器清零
               LeadCode =0;               //引导标志位清零
                           RecvSuccess=0xff;          //成功标志位置位
                           TR0 =0;                    //关定时器0
               ET0 =0;                    //关闭定时器0
              break;            
             }                                                               
    default: break;
  }
  
  if(RecvSuccess==0xff)                   //判断接收数据成功标志位
  {
       RecvSuccess=0x00;                  //成功标志位清零
       if(DataBuffer[0]!=DataBuffer[1])   //判断用户码是否相同  
           {return;}
           if(DataBuffer[2]!=~DataBuffer[3])  //判断按键码是否正确
           {return;}
      
           P2=LedShowData[DataBuffer[2]];     //P2端口开始显示数据
                //ControlCar(1);
           led=!led;
           DataBuffer[0]=0;                   //清零数据缓存0
           DataBuffer[1]=0;                   //清零数据缓存0
           DataBuffer[2]=0;                   //清零数据缓存0
           DataBuffer[3]=0;                   //清零数据缓存0
  }
}
void main()                       //主程序入口
{
bit ExeFlag=0;                       //定义可执行位变量
RecvData=0;                          //将接收变量数值初始化
CountData=0;                         //将计数器变量数值初始化
AddData=0;                           //将定时器计数器初始化

LedFlash=3000;                       //对闪灯数据进行初始化
ReceiveBit =0;                       //红外接收记数器清零
AddData =0;                          //计数器清零
LeadCode =0;                         //引导码记录器请零
RecvSuccess=0x00;

TMOD=0x01;                           //选择定时器0为两个16位定时器
TH0=0xFF;                            //对定时器进行计数值进行初始化
TL0=0x49;                            //同上,时间大约为25uS

TR0=1;                               //同意开始定时器0
EX1=1;                               //同意开启外部中断1
IT1=1;                               //设定外部中断1为低边缘触发类型
EA=1;                                //总中断开启
while(1)                             //程序主循环
{
   while(LedFlash--)                  //闪灯总延时
    {
     if(IR1==0)                       //判断延时期间是否有红外信号输入
       {ExeFlag=1;                    //将可执行标志位置1
       }
    }
  RunLed=!RunLed;                     //运行指示灯取反
  LedFlash=3000;                      //运行闪动时间重设定
  if(ExeFlag==0)                      //判断可执行标志位
  {
    EX1=1;                            //开启外部中断1
  }
  ExeFlag=0;                          //可执行标志位置0
}
}
此帖出自51单片机论坛
 
 
 

回复

3

帖子

0

TA的资源

一粒金砂(中级)

板凳
 

回复 沙发 rfw8797 的帖子

问题是:
在外部中断中,只要在这个地方
      
           P2=LedShowData[DataBuffer[2]];     //P2端口开始显示数据
                //ControlCar(1);
           led=!led;
           DataBuffer[0]=0;                   //清零数据缓存0
           DataBuffer[1]=0;                   //清零数据缓存0
           DataBuffer[2]=0;                   //清零数据缓存0
           DataBuffer[3]=0;                   //清零数据缓存0
不加ControlCar(1);程序就能正常运行,加了ControlCar(1); 程序进一次中断就不会再进第二次,请问这是什么问题呢?
此帖出自51单片机论坛
 
 
 

回复
您需要登录后才可以回帖 登录 | 注册

随便看看
查找数据手册?

EEWorld Datasheet 技术支持

相关文章 更多>>
关闭
站长推荐上一条 1/10 下一条

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

About Us 关于我们 客户服务 联系方式 器件索引 网站地图 最新更新 手机版

站点相关: 国产芯 安防电子 汽车电子 手机便携 工业控制 家用电子 医疗电子 测试测量 网络通信 物联网

北京市海淀区中关村大街18号B座15层1530室 电话:(010)82350740 邮编:100190

电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved
快速回复 返回顶部 返回列表