51单片机+红外发射模块(38k+NEC),这代码对不对?有详细...

2020-01-27 11:34发布

哪位大神帮小弟看一下这段代码,是网上载的,我大概修改了一下几个数值,因为我觉得原来的错的,结果红外发射模块发射不了,用原来载下来的数值执行起来也是不行,小弟这里没示波器,这份代码小弟很详细的给它添加了很多注释,只求有心的前辈帮一下小弟,帮忙看一下哪里不对。。。。 38k + NEC协议。。。。作者没有使用循环去发送 用户码 用户反码 键码 键反码,所以代码看起来比较多,其实是很少的。。。
捣鼓了我好几天了一直不知道为什么不行,啊啊啊啊啊啊 拜托前辈了!帮了小弟这个忙,什么都好说
  1. //#include <AT89X51.h>
  2. #include <reg51.h>

  3. static bit OP;                                   //红外发射管的亮灭控制位
  4. static unsigned int count;                //延时计数器
  5. static unsigned int endcount;         //终止延时计数
  6. static unsigned char flag;                //红外发送标志
  7. sbit  P3_4=P3^4;
  8. char iraddr1; //十六位地址的第一个字节
  9. char iraddr2; //十六位地址的第二个字节
  10. void SendIRdata(char p_irdata);//发送子函数
  11. void delay();


  12. void main(void)                                 
  13. {
  14.         count = 0;
  15.         flag = 0;                //无载波
  16.         OP = 0;                        //不亮
  17.         P3_4 = 0;                //在后面会发现用OP赋值的
  18.         EA = 1;                 //允许CPU中断
  19.         TMOD = 0x11;         //设定时器0和1为16位模式1  
  20.         ET0 = 1;                 //定时器0中断允许
  21.         TH0 = 0xFF;  
  22.         TL0 = 0xE6;         //设定时值0为38K 也就是每隔26us中断一次
  23.         TR0 = 1;                //开始计数
  24.         iraddr1=3;                //自定义的一个地址
  25.         iraddr2=252;        //地址反码

  26.         do
  27.         {
  28.                 delay();                 //延时
  29.                 SendIRdata(221); //发送数据

  30.         }while(1);
  31. }

  32. //定时器0中断处理
  33. void timeint(void) interrupt 1
  34. {
  35.         TH0=0xFF;
  36.         TL0=0xE6;                 //设定时值为38K 也就是每隔26us中断一次
  37.         count++;
  38.        
  39.         if (flag==1)         //如果是待发送的有效数据flag=1,就在此产生载波(亮灭交变)
  40.         {
  41.                 OP=~OP;                //产生方波其实就是调制后的高电平哈
  42.         }
  43.         else
  44.         {
  45.                 OP = 0;                 //发送低电平
  46.         }
  47.        
  48.          P3_4 = OP;           //往发射模块的 IO口发送出去哈
  49. }

  50. void SendIRdata(char p_irdata)                //发送数据子函数
  51. {
  52.         int i;
  53.         char irdata=p_irdata;
  54.        
  55.         /***************************************************************/
  56.        
  57.         //发送9ms的起始码       
  58.         //引导码是9ms的高电平,9000us/26us = 346
  59.         endcount = 346;
  60.         flag=1;                                          //载波模式有效
  61.         count=0;
  62.         while(count<endcount);        //等待中断,在中断中发送载波,总时间为9ms


  63.         //发送4.5ms的结果码,并是载波模式无效,也就是发送4.5ms的低电平
  64.         //结果码是 4500us/26us = 173
  65.         endcount = 173;
  66.         flag=0;
  67.         count=0;
  68.         while(count<endcount);

  69.         /***************************************************************/
  70.         //发送十六位地址的前八位,iraddr存的是地址码
  71.         irdata=iraddr1;
  72.         for(i=0;i<8;i++)
  73.         {
  74.                 //一个周期里规定先以高电平开始,在以低电平结束。先发送0.56ms的38KHZ“1”的红外波(即编码中0.56ms的高电平)
  75.                 endcount = 21;                        //560us/26us = 21
  76.                  flag=1;
  77.                 count=0;
  78.                 while(count<endcount); //等待中断


  79.                   if(irdata-(irdata/2)*2)        //判断二进制数个位为1还是0
  80.                   {
  81.                         endcount=64; //如果是 1,修改 endcount = 64, 64*26us = 1680us
  82.                 }
  83.                   else                 
  84.                   {
  85.                         endcount=21;//如果是0,则低电平 21*26us = 560us;
  86.                 }
  87.                 flag=0; //因为发送的 0,所以调制后就是一连串连续的低电平,所以 flag=0,载波模式无效
  88.                 count=0;
  89.                
  90.                 while(count<endcount); //等待中断发送
  91.                
  92.                 irdata=irdata>>1;//依次取位
  93.                        
  94.         }

  95.         //发送十六位地址的后八位

  96.        
  97.         irdata=iraddr2;        //此处已经是地址的反码       
  98.         for(i=0;i<8;i++)
  99.         {
  100.                 endcount = 21;
  101.                 flag=1;
  102.                 count=0;
  103.                
  104.                 while(count<endcount);
  105.                
  106.                 if(irdata-(irdata/2)*2)
  107.                 {
  108.                         endcount = 64;

  109.                 }
  110.                 else
  111.                 {
  112.                         endcount = 21;
  113.                 }

  114.                 flag=0;
  115.                 count=0;
  116.                
  117.                 while(count<endcount);
  118.                
  119.                 irdata=irdata>>1;
  120.         }/***************************************************************/
  121.         //发送八位数据
  122.        
  123.         irdata=p_irdata;
  124.        
  125.         for(i=0;i<8;i++)
  126.         {
  127.                 endcount = 21;
  128.                 flag=1;
  129.                 count=0;
  130.                
  131.                 while(count<endcount);
  132.                
  133.                 if(irdata-(irdata/2)*2)
  134.                 {
  135.                         endcount=64;;
  136.                        
  137.                 }
  138.                 else
  139.                 {
  140.                         endcount = 21;
  141.                 }
  142.                
  143.                 flag=0;
  144.                 count=0;
  145.                
  146.                 while(count<endcount);
  147.                
  148.                 irdata=irdata>>1;               
  149.         }

  150.         //发送八位数据的反码
  151.         irdata=~p_irdata;                //要将数据位取反
  152.        
  153.         for(i=0;i<8;i++)
  154.         {
  155.                 endcount = 21;
  156.                 flag=1;
  157.                 count=0;
  158.                
  159.                 while(count<endcount);
  160.                
  161.                 if(irdata-(irdata/2)*2)
  162.                 {
  163.                         endcount = 64;
  164.                 }
  165.                 else
  166.                 {
  167.                         endcount = 21;
  168.                 }
  169.                
  170.                 flag=0;
  171.                 count=0;
  172.                
  173.                 while(count<endcount);
  174.                
  175.                 irdata=irdata>>1;
  176.         }
  177.        
  178.   //到这边一帧的数据已经按照 38K + NEC发送出去了
  179. }


  180. void delay()
  181. {
  182.         int i,j;
  183.        
  184.         for(i=0;i<400;i++)
  185.         {
  186.                 for(j=0;j<100;j++)
  187.                 {
  188.                 }
  189.         }
  190. }

复制代码
友情提示: 此问题已得到解决,问题已经关闭,关闭后问题禁止继续编辑,回答。
29条回答
gmliwei
2020-01-29 18:30
从百度文库找了一个程序供你参考一下:
/*****************************************************************************************
红外发射接收原理:
                发射波形(38kHZ代替高电平)                                                    接收波形(接受到的电平反向)                                       
                                                                                                                                                   
38kHZ                        38kHZ                                  发射            ____1__________             ______1_________
||||||_____0________||||||___0_______------------->___0__|                         |___0__|
                                                                         ------------->
定时器工作方式
在方式2中把16位的计数器拆分成两个8位计数器,底8位作计数器用以保存计数初值。方式2适合用于比较精确的脉冲信号发生器,和波特率发生器
方式2计算初值X,X=256-tfosc/12(或6)
12和6是分频,一般情况下取12;t为所设计时时间单位为s,fosc为晶振单位为Hz。
计数器每加1耗费一个机器机器周期,一个机器周期等于12个振荡脉冲周期即如果震荡周期为1s计数器加一要花12s ,若晶振为fosc=12MHz计数频率
为fcont=fosc/12为1MHz即计数器加1消耗1us  ,每计1所华的时间为  t=T=1/fcont=1(fosc/12)=12/fosc                           

/**********************************************************/
#include "reg51.h"
#include "keyscan.c"

sbit TR_DATA=P2^7;


/***********************************************
函数名:delay_ms
子函数:无
输  入:n
输  出:无
功  能:延迟nMS子程序24MHz,n MS经滤波器检测非常精确
------------------------------------------------
************************************************/
void delay_ms(unsigned int n)
{
    unsigned int i=218;
    for(;n>0;n--)
        {
            while(i--);
        i=218;
        }
}


/***********************************************
函数名:TransData
子函数:无
输  入:_data
输  出:无                                                                         
功  能:发送数据                                                          9ms38k                                4ms低电平
说明:开始时序:9ms38kHz方波接着4ms低电平 |||||||||||||||||||||||____0___
      信号"1"时序:1ms的38kHZ方波接着1ms低电平
          信号"0"时序:1ms的38kHZ方波接着3ms低电平
          结束时序:5ms的38kHZ
************************************************/

void TransData(unsigned char _data)
{
    unsigned char i;
        TR0=1;               //启动38K发生器
        delay_ms(9);         //9ms的启动38KHz脉冲
        TR0=0;               //关闭38K发生器
        TR_DATA= 0;          //输出0
    delay_ms(5);         //5ms的启动低电平
    for(i=0;i<8;i++)
        {
            TR0=1;            //启动38K发生器
            delay_ms(1);      //产生1ms的38k脉冲供红外发射管发射
                TR0=0;            //关闭38K发生器
                TR_DATA= 0;        //输出0
                if(_data&(1<<i))delay_ms(1);        //1左移i位 ,先发低位
                                               //如果发送1 则高低电平比为1:1
                else delay_ms(3);           //如果发送0 则高低电平比为1:3
        }
        TR0=1;               //启动38K发生器
        delay_ms(5);         //5ms的结束38K方波
        TR0=0;               //关闭38K发生器
        TR_DATA= 0;          //输出0
}

//主函数

void main()
{
    unsigned char key;
   TMOD=0x02;          //定时器T0工作方式2
        TH0=0xE6;
        TL0=0xE6;  //自动重载
        EA=1;
        ET0=1;


    while(1)
          {
              TR_DATA=0;
              while(!key_on());  //等待按下按键
                  key=key_scan();
                  if(key == 20)continue;//如果key=20结束本次循环
          TransData(key);
                  while(key_on());   //等按键松开  
          }         

}


//定时器零产生38K方波       

void T0_interrupt(void) interrupt 1
{
    TR_DATA=~TR_DATA;
        TR0=1;
}          

一周热门 更多>