lanxix 发表于 2013-7-28 13:59:07

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

byte Flag=0;

void setup() {
Serial.begin(9600);
pinMode(13,OUTPUT);
}

void loop()
{
int X,Y;
uint32_t Time=millis() ;
uint32_t Count=0;
Pio *pPio=PIOB;


for(Y=0;Y<480;Y++)
{
for(X=0;X<800;X++)
{
    Count++;
    digitalWrite(13,1) ;
    //pPio->PIO_SODR=PIO_PB27;
}
}
Serial.print("Time:");
Serial.println(millis()-Time);
delay(1000);

/*

if(Flag==0)
{
    Flag=1;
    pPio=PIOB;
    pPio->PIO_SODR=PIO_PB27;
    //PIO_SetOutput( PIOB, PIO_PB27, 1, 0, PIO_PULLUP ) ;

    Serial.println("1");
}
else
{
    Flag=0;
    pPio= PIOB;
    pPio->PIO_CODR=PIO_PB27;
    //PIO_SetOutput( PIOB, PIO_PB27, 0, 0, PIO_PULLUP ) ;
    Serial.println("0");
}
delay(1000);
*/

}

输出:
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的资源.....

alien 发表于 2013-12-4 09:33:06

OK!!!!! 很好,正希望多看点这种好贴

Simon 发表于 2013-12-4 09:56:34

这个……跟ARM的运算能力无关吧

dan59314 发表于 2013-12-4 14:01:39

不懂pPio->PIO_SODR=PIO_PB27; 的用法

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


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

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

By Daniel Lu2013'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
      ---------------------------------------------------------------      
      CS02CS01 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
}
页: [1]
查看完整版本: 好吧,Due,即使你上ARM,84M,但在IO读写方面,却没有任何进步