• 已解决 73482 个问题
  • 已帮助 5993 位优秀工程师

红外遥控发射NEC编码,代码有问题,LEAD的持续时间无法按要求调整,求助!!

xtacel 2015-10-24 浏览量:724

大家好,
     从网上DOWN了程序,优化了一下,主要想调整NEC编码的占空比(不是38K载波的占空比),但是实际测试输出LEAD波形时并不按设计的走(地址码与数据码都未发现有问题),如,695次调用TIMER0中断,输出延时是对的,但是900次调用中断后就不对了,感觉哪里有东西打断了进程?也尝试在不同的地方加中断、计数使能,但是总有问题。
     我用的是STC12C5202AD单片机,用KEIL 5编译,已经将芯片导入到KEIL里,使用外部12M晶振。
     代码如下:

------------------------自定义头文件----------------------------
#ifndef _C51_ZY_H_
#define _C51_ZY_H_

void UartInit();
void delay_us(int i);
void IR_transfer(char iraddr1,char iraddr2,char p_irdat);
void timer0_int_13us(void);
void delay_100ms(int k) ;
#endif

---------------主程序-----------------------------------------
     #include
#include
sbit P1_1=P1^1;     //  LED
char  iraddr1=0x44;    //the first byte of the hex address
char  iraddr2=0x9b;     //the second byte of the hex address
char  p_irdata=0x12;    //IR DATA
void main(void)  
{
  P1_1=0;
        AUXR |= 0x80;         //SET TIMER0 1T MODE
  P1M1 &= 0xF7;
  P1M0 |= 0x08;        //SET P1_3 PUSH-PULL MODE
        //UartInit();
        
        IR_transfer(iraddr1,iraddr2,p_irdata);

        //delay_us(10);        
        
}   


----------------------TIMER0初始化-----------------------------
#include
#include                                            
void  timer0_int_13us(void)
{                    


        AUXR |= 0x80;                //定时器时钟1T模式
        TMOD &= 0xF0;                //设置定时器模式
        TMOD |= 0x01;                //设置定时器模式
        ET0 = 1;
        TL0 = 0x64;                //设置定时初值
        TH0 = 0xFF;                //设置定时初值
        TF0 = 0;                //清除TF0标志
        TR0 = 1;                //定时器0开始计时

}

-----------------------延时子程序--------------------------
void delay_100ms(int k) 
{     
  int i,j;   
  for(k;k>0;k--)
{  
  for(i=0;i<150;i++)    
     { 
                        for(j=0;j<400;j++);
     } 
        }                 
                 
}

--------------------发射程序---------------------------
#define uchar unsigned char     //just for convenience
#define uint  unsigned int 
#define ulong unsigned long  
#include              //the standard head file  
#include
static bit OP;                 //the turn on or off of the IR led
int count;     //delay count 
int endcount;   //terminate count 
unsigned char flag;     //the flag of IR emission 
sbit P1_3=P1^3;      // IR pin

extern char  iraddr1;    //the first byte of the hex address
extern char  iraddr2;     //the second byte of the hex address
extern char  p_irdata;    //IR DATA
int test_mode;//0 mean constant period,1 mean constant duty cycle    
int logic_high;
int logic0_low;
int logic1_low;
int lead_high;
int lead_low;
void   SendIRdata(); 
void IR_transfer(char iraddr1,char iraddr2,char p_irdata);
//void   delay_us(int i); 
//void timer0_int_13us(void);
void IR_transfer(char iraddr1,char iraddr2,char p_irdata)
{
                 
            count=0;   
                        flag=0;   
                        OP=0;   
                        P1_3=0;     
                  EA = 1;      // permit cpu interrupt           
          
            timer0_int_13us();
          
                        //TMOD = 0x11; //set timer0&1 to the HEX mode of 1   
                        //ET0 = 1;     //permit timer0 interrupt     
                        //TH0 = 0xFF;     
                        //TL0 = 0x7d;  //set timer0 have a interrup per 13us(38k/2)   
      //TR0 = 1;     //start count     
            
        
        test_mode=0;     //0 mean constant period,1 mean constant duty cycle
        logic_high=43;   //43=0%;34=-20%,52=+20%;21=-50%,65=+50%
        lead_high=903;   //625(-10%),556(-20%),486(-30%),417(-40%),347(-50%)
                         //695(0%)
                         //764(+10%),834(+20%),903(+30%),973(+40%),1000(+45%)
        if(test_mode==0)
        {
                lead_low=350;//1045 is standard,
                logic1_low=173-logic_high; //173 is standard,
                logic0_low=87-logic_high;        //87 is standard,
        }
        else
        { 
                lead_low=lead_high/2+1;    //+1 为了补偿中断子程序中取反操作与赋值操作的时间差
                logic0_low=logic_high+1; 
                logic1_low=logic_high*3+1;
        }
        
do{   
         //ET0=0;
         //TR0=1;
         //EA=1;
   SendIRdata();
         //TR0=0;
         //ET0=0;
         //EA=0; 
         delay_100ms(5);
  }   
while(1);
}
void SendIRdata() 
{  
        
        int i;   
        char irdata;
                       //---------------send the starting code of 9ms---------------------
        endcount=lead_high;  //690 is standard,
  flag=1;  
  count=0;   
  //ET0=1;TR0=1;
  do{}while(count                       //---------------send the ending code of 4.5ms--------------------
        //ET0=0;TR0=0;
        endcount=lead_low;  //
  flag=0;  
  count=0;   
        //ET0=1;TR0=1;
  do{}while(count 
  //ET0=0;TR0=0;
               //-----------------send the first 8 bit of the address----------------
        irdata=iraddr1;  
        for(i=0;i<8;i++) 
        {                            
               //---------------first,send 0.56ms ir wave(38k),voltage high-----------
                //ET0=1;TR0=1;
                endcount=logic_high;    
                flag=1;  
    count=0;   
                
    do{}while(count 
                          //----------------stop send ir wave,voltage low-----------------   
          if(irdata-(irdata/2)*2)  //judge the last binary bit is 1 or 0 
                { 
                        endcount=logic1_low;          //1 mean wide low level  
                }  
                else   
                { 
                        endcount=logic0_low;          //0 mean narrow low level
                }   
    flag=0;  
    count=0;  
    do{}while(count     irdata=irdata>>1; 
  }  
              //-------------send the last 8 bit of the HEX address-----------------  
    irdata=iraddr2;  
    for(i=0;i<8;i++) 
    {   
      endcount=logic_high;  
      flag=1;  
      count=0;   
      do{}while(count                   if(irdata-(irdata/2)*2)
                          {endcount=logic1_low;}  
      else   
        {endcount=logic0_low;}    
      flag=0;  
      count=0;   
      do{}while(count       irdata=irdata>>1;
    }  
             //------------------send 8 bit data---------------------  
    irdata=p_irdata;  
    for(i=0;i<8;i++) 
    {  
      endcount=logic_high;  
      flag=1;  
      count=0;   
      do{}while(count 
      if(irdata-(irdata/2)*2)  
        {endcount=logic1_low;}  
      else   
        {endcount=logic0_low;}  
      flag=0;  
      count=0;   
      do{}while(count       irdata=irdata>>1;
     }  
             //---------------------send the 8 bit complement data----------------------   
     irdata=~p_irdata;  
     for(i=0;i<8;i++)   
      {  
        endcount=logic_high;  
        flag=1;  
        count=0;  
        do{}while(count         if(irdata-(irdata/2)*2) 
          {endcount=logic1_low;} 
        else   
          {endcount=logic0_low;} 
        flag=0; 
        count=0;  
        do{}while(count         irdata=irdata>>1;  
      }  
     endcount=logic_high; 
     flag=1;  
     count=0;    
     do{}while(count 
     flag=0; 
                P1_3=0;
                 //ET0 = 0;        
}  



//***********************************************************************************                                           
         //timer0 execute interrupt 
void timeint(void) interrupt 1  using 1
{    
        //ET0=0;
        
        TH0=0xFF;    
        TL0=0x7E;  
        TR0=0;
        count++;   
        
        if (flag==1)  
         {
                 OP=~OP;  
         } 
        else   
         {OP = 0;} 
          P1_3 = OP;
         //ET0=1;
         TR0=1;
}   


-------------------------------

0 0 收起

我来回答

上传资料:
选择文件 文件大小不超过15M(格式支持:doc、ppt、xls、pdf、zip、rar、txt)
最佳答案
  • stm32的程序,注释详细,你好好对比下,计时的值,根据你的时钟周期好好计算下。
    //定时器3中断
    void TIM3_IRQHandler(void)   //TIM3中断
    {
    if (TIM_GetITStatus(TIM3, TIM_IT_Update) != RESET)  
    {
    TIM_ClearITPendingBit(TIM3, TIM_IT_Update  ); 
    count++;
    PCout(1)=~flag1;
    if (flag==1)     //如果是待发送的有效数据flag=1,就在此产生载波(亮灭交变)
             {
    if(flag1==1)
    {
    GPIO_SetBits(GPIOA,GPIO_Pin_8) ;
    flag1=0;
    }
    else
    {
    GPIO_ResetBits(GPIOA,GPIO_Pin_8) ;
    flag1=1;
    }
     
             }
             else
             {
                GPIO_ResetBits(GPIOA,GPIO_Pin_8) ;
             }
         
             if(count==50000)
    count=0;
    }
    }
    void SendIRdata(char p_irdata)        //发送数据子函数

        int i;
        char irdata=p_irdata; 
         
        /***************************************************************/
         
        //发送9ms的起始码   
        //引导码是9ms的高电平,9000us/26us = 346
        endcount = 346;
        flag=1;                      //载波模式有效
        count=0;
        while(count  
     
        //发送4.5ms的结果码,并是载波模式无效,也就是发送4.5ms的低电平
        //结果码是 4500us/26us = 173
        endcount = 173;
        flag=0;
        count=0;
        while(count  
        /***************************************************************/
        //发送十六位地址的前八位,iraddr存的是地址码
        irdata=iraddr1;
        for(i=0;i<8;i++)
        {
            //一个周期里规定先以高电平开始,在以低电平结束。先发送0.56ms的38KHZ“1”的红外波(即编码中0.56ms的高电平)
            endcount = 21;            //560us/26us = 21
             flag=1;
            count=0;
            while(count  
     
              if(irdata-(irdata/2)*2)    //判断二进制数个位为1还是0
              {
                endcount=64; //如果是 1,修改 endcount = 64, 64*26us = 1680us
            }
              else         
              {
                endcount=21;//如果是0,则低电平 21*26us = 560us;
            }
            flag=0; //因为发送的 0,所以调制后就是一连串连续的低电平,所以 flag=0,载波模式无效
            count=0;
             
            while(count          
            irdata=irdata>>1;//依次取位
                 
        }
     
        //发送十六位地址的后八位
     
         
        irdata=iraddr2;    //此处已经是地址的反码   
        for(i=0;i<8;i++)
        {
            endcount = 21;
            flag=1;
            count=0;
             
            while(count          
            if(irdata-(irdata/2)*2)
            {
                endcount = 64;
     
            }
            else
            {
                endcount = 21;
            }
     
            flag=0;
            count=0;
             
            while(count          
            irdata=irdata>>1;
        }/***************************************************************/
        //发送八位数据
         
        irdata=p_irdata;
         
        for(i=0;i<8;i++)
        {
            endcount = 21;
            flag=1;
            count=0;
             
            while(count          
            if(irdata-(irdata/2)*2)
            { 
                endcount=64;; 
                 
            }
            else
            {
                endcount = 21; 
            }
             
            flag=0;
            count=0;
             
            while(count          
            irdata=irdata>>1;       
        }
     
        //发送八位数据的反码
        irdata=~p_irdata;        //要将数据位取反
         
        for(i=0;i<8;i++)
        {
            endcount = 21;
            flag=1;
            count=0;
             
            while(count          
            if(irdata-(irdata/2)*2)
            {
                endcount = 64;
            }
            else
            {
                endcount = 21;
            }
             
            flag=0;
            count=0;
             
            while(count          
            irdata=irdata>>1;
        }
         
      //到这边一帧的数据已经按照 38K + NEC发送出去了
    }
    • 发布于 2015-10-24
    • 举报
    • 评论 0
    • 0
    • 0

其他答案 数量:1
  • 不懂,帮顶一下……代码太长了……
    • 发布于2015-10-28
    • 举报
    • 评论 0
    • 0
    • 0

相关问题

问题达人换一批

红外遥控发射NEC编码,代码有问题,LEAD的持续时间无法按要求调整,求助!!