极客工坊

 找回密码
 注册

QQ登录

只需一步,快速开始

查看: 10807|回复: 4

好吧,Due,即使你上ARM,84M,但在IO读写方面,却没有任何进步

[复制链接]
发表于 2013-7-28 13:59:07 | 显示全部楼层 |阅读模式
  1. byte Flag=0;

  2. void setup() {
  3.   Serial.begin(9600);
  4.   pinMode(13,OUTPUT);
  5. }

  6. void loop()
  7. {
  8. int X,Y;
  9. uint32_t Time=millis() ;
  10. uint32_t Count=0;
  11. Pio *pPio=PIOB;


  12. for(Y=0;Y<480;Y++)
  13. {
  14.   for(X=0;X<800;X++)
  15.   {
  16.     Count++;
  17.     digitalWrite(13,1) ;
  18.     //pPio->PIO_SODR=PIO_PB27;
  19.   }
  20. }
  21. Serial.print("Time:");
  22. Serial.println(millis()-Time);
  23. delay(1000);

  24. /*
  25.   
  26.   if(Flag==0)
  27.   {
  28.     Flag=1;
  29.     pPio=PIOB;
  30.     pPio->PIO_SODR=PIO_PB27;
  31.     //PIO_SetOutput( PIOB, PIO_PB27, 1, 0, PIO_PULLUP ) ;
  32.   
  33.     Serial.println("1");
  34.   }
  35.   else
  36.   {
  37.     Flag=0;
  38.     pPio= PIOB;
  39.     pPio->PIO_CODR=PIO_PB27;
  40.     //PIO_SetOutput( PIOB, PIO_PB27, 0, 0, PIO_PULLUP ) ;
  41.     Serial.println("0");
  42.   }
  43.   delay(1000);
  44. */
  45.   
  46. }
复制代码


输出:
Time:982
Time:982
Time:982
Time:982



这段测试代码希望你们能看得懂,很简单,480*800=384000次循环,也就是说进行384000次13端口的IO操作时间。如果使用digitalWrite的话,那么需要 982ms,如果把digitalWrite(13,1) ;注释掉,换成 pPio->PIO_SODR=PIO_PB27,直接13对应的物理端口PB27操作,那么是什么结果?39ms,25倍的差异


大家也不要问我AVR32的那些寄存器操作了,因为我也不知道了,我是查看了arduino 1.5.2自带的源代码,跟踪了digitalWrite操作的源代码才知道是怎么调用寄存器操作的,后半段是调用寄存器,让LED一秒闪一次的代码


回复

使用道具 举报

发表于 2013-7-28 16:10:37 | 显示全部楼层
只能说明digitalWrite执行效率实在太低了!

也说明arduino 1.5.2不适用于DUE,用它是浪费ARM的资源.....
回复 支持 反对

使用道具 举报

发表于 2013-12-4 09:33:06 | 显示全部楼层
OK!!!!! 很好,正希望多看点这种好贴
回复 支持 反对

使用道具 举报

发表于 2013-12-4 09:56:34 | 显示全部楼层
这个……跟ARM的运算能力无关吧
回复 支持 反对

使用道具 举报

发表于 2013-12-4 14:01:39 | 显示全部楼层
不懂  pPio->PIO_SODR=PIO_PB27; 的用法

digitalWrite() 使用 Timer0 的 震盪頻率, 是不是因此比較起來慢了些? 請先進們解惑一下。


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

Digital pins:
  &#61565; Pins 0 – 7: PORT D [0:7]
  &#61565; Pins 8 – 13: PORT B [0:5]
  &#61565; Pins 14 – 19: PORT C [0:5] (Arduino analog pins 0 – 5)
  &#61565; digital pins 0 and 1 are RX and TX for serial communication
  &#61565; digital pin 13 connected to the base board LED

  By Daniel Lu  2013'11'30
  https://www.youtube.com/user/dan59314?feature=watch
  http://dan59314.myweb.hinet.net
  http://www.facebook.com/rasvector/
  
 ATMEGA 328 晶片,振盪頻率為 16M Hz,   每秒 16*10^6,  每一次 ~ 63 ns(微秒)
  
  1. 有3個Timer
    Timer 0: millis() and delay().. 所使用的參考Timer
      8 bit 計數暫存器(0~255)
    Timer 1: Servo library 所使用
      16 bit 計數暫存器(0~65535)
    Timer 2:
      8 bit 計數暫存器(0~255)
      
    EX:若要讓 Timer2 每一秒中斷一次,則
       Timer2有16bit,可以計數 0 ~ 65535, 計數器滿了則中斷一次, 因此
        每次中斷間隔時間為   1秒 / 16*10^6次 x 65535 ~= 4 ms
        因為 16MHz 太快,如果要每一秒中斷一次,則必須調降16M Hz,因此有 preScaler
        ---------------------------------------------------------------        
        CS02  CS01 CS00  功能
          0    0    0    無計數功能
          0    0    1    無 PreScale
          0    1    0    PreScale=8 (Clock / 8)
          0    1    1    PreScale=64
          1    0    0    PreScale=256
          1    0    1    PreScale=1024
          1    1    0    在 T0 pin 使用外部 振盪源,下緣觸發 (falling edge)
          1    1    1    在 T0 pin 使用外部 振盪源,上緣觸發 (rising edge)
        ---------------------------------------------------------------      
        所以如果要每秒一次中斷(暫存器計數 65536), 則每秒必須震盪 65536 次
          65535 Hz = 16M Hz / scale  ---> scale ~= 244.1406,  PreScale 必須至少 >= 256 ,在此我們選 1024
          -> (CS02=1, CS01=0, CS00=1)   #設定一
       因此,公式如下:
          interrupt frequency (Hz) = (Arduino clock speed 16,000,000Hz) / (prescaler * (compare match register + 1))
          每秒中斷一次
          1 Hz = (16M Hz) / (1024 * OCRx)  -> OCRx = 16x10^6 / 1024 -1 = 15624
          -> #設定二 : Timer1 的中斷計數值 OCR1A = 15624   
        由 設定一,設定二可設定 Timer1  如下:
          TCCR1A = 0;      // set entire TCCR1A register to 0
          TCCR1B = 0;      // same for TCCR1B
          TCNT1  = 0;      // initialize counter value to 0, 初始化 Timer0 Count (0~65535, 暫存器16bit)
          OCR1A = 15624;   // 中斷計數值 設定二  (16*10^6) / (1*1024) - 1 (must be <65536)
          TCCR1B |= (1 << WGM12);                // 啟動 CTC 模式
          TCCR1B |= (1 << CS12) | (1 << CS10);   // 設定 PreScale = 1024,設定一
          TIMSK1 |= (1 << OCIE1A);               // 啟動 計數值中斷
     
         完成以上設定後, 就可以讓 Timer1 每秒 (計數值 15624 振盪次數) 產生一次中斷      
***********************************************************
*/

//storage variables
boolean toggle0 = 0;  // 紀錄 Timer0 的狀態
boolean toggle1 = 0;  // 紀錄 Timer1 的狀態
boolean toggle2 = 0;

void setup_Timer()
{//Timer0 設定 -------------------------------------------------------------
  TCCR0A = 0;// set entire TCCR0A register to 0,  TCCRxA x代表 Timer 編號 0~2
  TCCR0B = 0;// same for TCCR0B
  TCNT0  = 0;//initialize counter value to 0 ,   初始化 Timer0 Count (0~255, 暫存器8bit)
  // set compare match register for 2khz increments
  OCR0A = 124;// = (16*10^6) / (2000*64) - 1 (must be <256), 中斷計數值,一但到達此值,則產生中斷
  TCCR0A |= (1 << WGM01);// turn on CTC mode  
  TCCR0B |= (1 << CS01) | (1 << CS00);// Set CS01 and CS00 bits for 64 prescaler     
  TIMSK0 |= (1 << OCIE0A);// enable timer compare interrupt  

  //Timer1 設定 -------------------------------------------------------------  
  TCCR1A = 0;  // set entire TCCR1A register to 0
  TCCR1B = 0;  // same for TCCR1B
  TCNT1  = 0;  //initialize counter value to 0, 初始化 Timer0 Count (0~65535, 暫存器16bit)
  // set compare match register for 1hz increments
  OCR1A = 15624;  // = (16*10^6) / (1*1024) - 1 (must be <65536)  
  TCCR1B |= (1 << WGM12);// turn on CTC mode,  注意:不是 TCRR1A
  TCCR1B |= (1 << CS12) | (1 << CS10);// Set CS12 and CS10 bits for 1024 prescaler  
  TIMSK1 |= (1 << OCIE1A);// enable timer compare interrupt

  //Timer2 設定 -------------------------------------------------------------  
  TCCR2A = 0;// set entire TCCR2A register to 0
  TCCR2B = 0;// same for TCCR2B
  TCNT2  = 0;//initialize counter value to 0, 初始化 Timer0 Count (0~255, 暫存器8bit)
  // set compare match register for 8khz increments
  OCR2A = 249;// = (16*10^6) / (8000*8) - 1 (must be <256)
  TCCR2A |= (1 << WGM21);// turn on CTC mode  
  TCCR2B |= (1 << CS21);   // Set CS21 bit for 8 prescaler  
  TIMSK2 |= (1 << OCIE2A);// enable timer compare interrupt  
}

void setup(){  
  //set pins as outputs
  pinMode(8, OUTPUT);  //Timer0
  pinMode(13, OUTPUT);
  pinMode(9, OUTPUT);

  cli();  //關閉 Interrupts 可用 cli(), sei()  在 loop 中, 暫時停用或啟用 interrupt

  setup_Timer();
  
  sei();  //啟動 Interrupts
}//end setup

ISR(TIMER0_COMPA_vect){//timer0 interrupt 2kHz toggles pin 8
//generates pulse wave of frequency 2kHz/2 = 1kHz (takes two cycles for full wave- toggle high then toggle low)
  if (toggle0){
    digitalWrite(8,HIGH);
    toggle0 = 0;
  }
  else{
    digitalWrite(8,LOW);
    toggle0 = 1;
  }
}

ISR(TIMER1_COMPA_vect){//timer1 interrupt 1Hz toggles pin 13 (LED)
//generates pulse wave of frequency 1Hz/2 = 0.5kHz (takes two cycles for full wave- toggle high then toggle low)
  if (toggle1){
    digitalWrite(13,HIGH);
    toggle1 = 0;
  }
  else{
    digitalWrite(13,LOW);
    toggle1 = 1;
  }
}
  
ISR(TIMER2_COMPA_vect){//timer1 interrupt 8kHz toggles pin 9
//generates pulse wave of frequency 8kHz/2 = 4kHz (takes two cycles for full wave- toggle high then toggle low)
  if (toggle2){
    digitalWrite(9,HIGH);
    toggle2 = 0;
  }
  else{
    digitalWrite(9,LOW);
    toggle2 = 1;
  }
}


void loop(){
  //do other things here
}
回复 支持 反对

使用道具 举报

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

本版积分规则

Archiver|联系我们|极客工坊

GMT+8, 2026-6-9 06:26 , Processed in 0.035462 second(s), 23 queries .

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

快速回复 返回顶部 返回列表