作者 主题: arduino生成38KHz问题  (阅读 4939 次)

ArdyPro

  • Newbie
  • *
  • 帖子: 17
arduino生成38KHz问题
« 于: 十月 13, 2011, 11:37:27 下午 »
参照网上ladyada的代码写了一个红外发送的程序,需要用arduino生成38KHz的载波,我已经根据MEGA1280调整了高低电平延时,连续高电平在1000μs之内是,生成的载波误差比较小,但是发现有两个连续高电平7190μs和9130μs的情况时,误差太大到难以理解。下面第一组数据,本来是需要连续9130μs的高电平,按照26μs一个周期,则需要351个周期,实际是用了352个周期,花费816μs,相当于每个周期才2.3μs,远低于单个指令之后的延时6μs!

各位亲们,帮我看看程序到底错在哪里。

//源代码片段

程序代码
// This procedure sends a 38KHz pulse to the IRledPin 
// for a certain # of microseconds. We'll use this whenever we need to send codes

void pulseIR(long microsecs, long Interval)
{
     // we'll count down from the number of microseconds we are told to wait
    Serial.print(microsecs);
 
    long i;   i= micros();
    long c;   c=0;  //
 
    cli();  // this turns off any background interrupts
    while (microsecs > 0)
      {
        // 38 kHz is about 13 microseconds high and 13 microseconds low
       digitalWrite(IRledPin, HIGH);  // this takes about 3 microseconds to happen
       delayMicroseconds(Interval);         // hang out for 10 microseconds
       digitalWrite(IRledPin, LOW);   // this also takes about 3 microseconds
       delayMicroseconds(Interval);         // hang out for 10 microseconds
       // so 26 microseconds altogether
       microsecs -= 26;
       c++;
     }

    sei();  // this turns them back on
    i = micros() -i;
 
    Serial.print("  ");  Serial.print(c );  Serial.print("cycles and takes  ");
    Serial.print(i);  Serial.println(" us");
}

//跟踪信息
9130  352cycles and takes  816 μs   <--误差很大,每个cycle才2.3μs,难以理解
850  33cycles and takes  856 μs
....
560  22cycles and takes  572 μs
7190  277cycles and takes  948 μs   <--误差很大
560  22cycles and takes  572 μs





[/size]

ArdyPro

  • Newbie
  • *
  • 帖子: 17
Re: arduino生成38KHz问题
« 回复 #1 于: 十月 13, 2011, 11:39:35 下午 »
int IRledPin =  13;    // LED connected to digital pin 13
int _38HZ_Space=6;     //38KHz interval

//定义按键的波形特征码
long PowerOnArray[][2]=
{
  1,913,0,412,1,85,0,22,1,87,0,23,1,87,0,25,1,85,0,25,1,85,0,26,1,85,0,
  27,1,83,0,27,1,84,0,27,1,84,0,138,1,83,0,138,1,83,0,138,1,82,0,138,1,
  82,0,139,1,82,0,140,1,80,0,32,1,75,0,144,1,76,0,146,1,74,0,38,1,69,0,
  153,1,66,0,156,1,64,0,46,1,64,0,47,1,63,0,48,1,61,0,50,1,59,0,51,1,59,
  0,163,1,56,0,55,1,56,0,55,1,55,0,166,1,56,0,165,1,56,0,166,1,55,0,165,
  1,56,0,4021,1,719,0,209,1,56,0,0
};

void setup()   {               
  // initialize the IR digital pin as an output:
  pinMode(IRledPin, OUTPUT);     

  Serial.begin(9600);
}

void loop()                     
{
  //Serial.println("Sending IR signal");

  char Recv;

  if (Serial.available()>0)
  {
    //Serial.println("Has incoming chars");
    Recv=Serial.read();
    Serial.println(Recv);

    switch (Recv)
    {
    case '0':
    case '1':
    case '2':
    case '3':
    case '4':
    case '5':
    case '6':
    case '7':
    case '8':
    case '9':
      {
        Serial.println("Power On...");
        _38HZ_Space = Recv - 48;
        Serial.println(_38HZ_Space);
        PowerOn();
        break;
      };
    default:
      { 
      };
    }
  }

  //delay(60*1000);  // wait one minute (60 seconds * 1000 milliseconds)
}

void PowerOn()
{
  long i,c;
  long cmd,value;
  c=sizeof(PowerOnArray)/sizeof(PowerOnArray[0][0]);
  for (i=0; i<=c; i++)
  {
    cmd=PowerOnArray[0];
    value=PowerOnArray[1];
    if (cmd==1)
      pulseIR(value*10,_38HZ_Space);
    else
      delayMicroseconds(value*10);
  }
}

// This procedure sends a 38KHz pulse to the IRledPin
// for a certain # of microseconds. We'll use this whenever we need to send codes

void pulseIR(long microsecs, long Interval) {
  // we'll count down from the number of microseconds we are told to wait
  Serial.print(microsecs);

  long i;   
  i= micros();
  long c;   
  c=0;  //

  cli();  // this turns off any background interrupts
  while (microsecs > 0) {
    // 38 kHz is about 13 microseconds high and 13 microseconds low
    digitalWrite(IRledPin, HIGH);  // this takes about 3 microseconds to happen
    delayMicroseconds(Interval);         // hang out for 10 microseconds
    digitalWrite(IRledPin, LOW);   // this also takes about 3 microseconds
    delayMicroseconds(Interval);         // hang out for 10 microseconds
    // so 26 microseconds altogether
    microsecs -= 26;
    c++;
  }
  sei();  // this turns them back on
  i = micros() -i;

  Serial.print("  "); 
  Serial.print(c ); 
  Serial.print("cycles and takes  ");
  Serial.print(i); 
  Serial.println(" us");
}

后面部分怎么变成斜体了? :(
« 最后编辑时间: 十月 13, 2011, 11:49:50 下午 作者 ArdyPro »

Contra

  • SuperManager
  • Sr. Member
  • *****
  • 帖子: 347
  • AC, game dev, new media art&tech.
    • i'm Contra
Re: arduino生成38KHz问题
« 回复 #2 于: 十月 13, 2011, 11:49:44 下午 »
貌似编辑器最近很脆弱。。。

ArdyPro

  • Newbie
  • *
  • 帖子: 17
Re: arduino生成38KHz问题
« 回复 #3 于: 十月 14, 2011, 04:54:40 下午 »
我在官网咨询了一下,建议注释掉cli()和sei(),结果似乎正常,需要验证一下。至于原来代码中为什么要调用它俩,希望有明白的兄弟给解释一下。

ChocolateUniverse

  • Jr. Member
  • **
  • 帖子: 97
  • BigQ 勤劳勇敢,爱好艺术
Re: arduino生成38KHz问题
« 回复 #4 于: 十一月 17, 2011, 08:50:16 上午 »
我觉得是怕中断影响Timer,因为后面的代码是完全按照既定时间来操作的。
BigQ 勤劳勇敢 爱好艺术

Tags: