Nick Chung gửi vào
- 24603 lượt xem
Arduino dùng chip AVR, nếu điều khiển arduino bằng ngôn ngữ tiêu chuẩn của chip AVR thì tốc độ có thể nhanh hơn 12 lần so với cách dùng lệnh digitalWrite, nhanh hơn 4 lần so với lệnh digitalRead, nhanh 14 hơn lần so với analogRead, nhanh 10 hơn lần so với pinMode… thậm chí cách biệt còn xa hơn nữa. Điều này rất rất quan trọng. Cùng khám phá nào..
Bắt đầu nào...
Ở bài trước, ta đã biết cách điều khiển các chân port . Bây giờ hãy cùng mình so sánh tốc độ của 2 phương pháp.
Tiêu chí đánh giá:
- Bài viết sử dụng arduino uno r3 , tần số hệ thống 16mhz.
- Mình dùng hàm micros() của hệ thống làm đồng hồ. Hàm này sẽ được đặt về 0 khi reset hoặc nạp code lần đầu. Qúa trình khảo sát diến ra rất nhanh ( < 500 micro giây) nên không lo hàm sẽ bị tràn số.
- Công việc cần khảo sát:(đoạn code trong dấu ///) là đoạn code nằm giữa lúc bắt đầu tính thời gian và kết thúc tính thời gian (sát nhất). Các đoạn code khác (nằm trước và sau ) chỉ mang tính chất điều kiện cần, và không liên quan đến khoảng thời gian khảo sát.
- Khoảng thời gian khảo sát: chỉ được bắt đầu tính từ khi đặt start lần đầu tiên, khi "công việc cần khảo sát" kết thúc, mình sẽ lấy hiệu của micros() với start. Hiệu đó sẽ mãi được giữ nguyên,đó chính là khoảng thời gian khảo sát. Cuối cùng nó được in ra bằng Print.
- Thống kê: mình sẽ nhấn nút reset (giữ nguyên code), rồi lại xem kết quả để xem kết quả có bị lệch hay không giữa các lần .
- Độ chính xác: Kết quả tìm HIỆU có thể không chính xác tuyệt đối (không có máy đo chính xác hơn), nhưng chúng ta KHÔNG thật sự cần đến nó, cái quan trọng là chúng ta sẽ so sánh mức độ nhanh chậm gấp bao nhiêu lần của 2 loại code mà thôi(so sánh tương đối). Khi đó ở cùng một điều kiện phần cứng (không thay đổi) thì kết quả được cho là đáng tin cậy.(Đây cũng là cách nhanh nhất và tiết kiệm nhất mà chúng ta có thể thực hiện.)
- Điều kiện cuối: Nếu bạn chấp nhận các tiêu chí trên thì chúng ta sẽ tiếp tục hehe
Pin mode
Đặt pin digital 0 là output
unsigned long start; void setup(){ Serial.begin(9600); start=micros(); /// pinMode(0,OUTPUT); /// start=micros()-start; Serial.println(start); } void loop(){ } |
unsigned long start; void setup(){ Serial.begin(9600); start=micros(); /// DDRD=B00000001; /// start=micros()-start; Serial.println(start); } void loop(){ } |
Thời gian: 4 micro giây
|
4 micro giây
|
Đặt 14 pin digital là OUTPUT
unsigned long start; void setup(){ Serial.begin(9600); start=micros(); /// for(byte pin=0; pin<14; pin++){ pinMode(pin, OUTPUT);} /// start=micros()-start; Serial.println(start); } void loop(){ } |
unsigned long start; void setup(){ Serial.begin(9600); start=micros(); /// DDRB=B11111111; DDRD=B11111111; /// start=micros()-start; Serial.println(start); } void loop(){ } |
Thời gian: 44 micro giây
|
4 micro giây
|
unsigned long start; void setup(){ Serial.begin(9600); start=micros(); /// pinMode(0, OUTPUT); pinMode(1, OUTPUT); pinMode(2, OUTPUT); pinMode(3, OUTPUT); pinMode(4, OUTPUT); pinMode(5, OUTPUT); pinMode(6, OUTPUT); pinMode(7, OUTPUT); pinMode(8, OUTPUT); pinMode(9, OUTPUT); pinMode(10, OUTPUT); pinMode(11, OUTPUT); pinMode(12, OUTPUT); pinMode(13, OUTPUT); /// start=micros()-start; Serial.println(start); } void loop(){ } |
|
Không dùng for,Thời gian: 48 micro giây |
digitalWrite();
Đặt 1 pin là HIGH
unsigned long start; void setup(){ Serial.begin(9600); pinMode(0,OUTPUT); start=micros(); /// digitalWrite(0,HIGH); /// start=micros()-start; Serial.println(start); } void loop(){ } |
unsigned long start; void setup(){ Serial.begin(9600); pinMode(0,OUTPUT); start=micros(); /// PORTD=B00000001; /// start=micros()-start; Serial.println(start); } void loop(){ } |
Thời gian: 8 micro giây
|
4 micro giây
|
Đặt 14 pin là HIGH
unsigned long start; void setup(){ Serial.begin(9600); for(byte pin=0; pin<14; pin++){ pinMode(pin, OUTPUT); } start=micros(); /// for(byte pin=0; pin<14; pin++){ digitalWrite(pin,HIGH);} /// start=micros()-start; Serial.println(start); } void loop(){ } |
unsigned long start; void setup(){ Serial.begin(9600); DDRB=B11111111; DDRD=B11111111; start=micros(); /// PORTB=B11111111; PORTD=B11111111; /// start=micros()-start; Serial.println(start); } void loop(){ } |
Thời gian: 52 micro giây |
4 micro giây |
unsigned long start; void setup(){ Serial.begin(9600); for(byte pin=0; pin<14; pin++){ pinMode(pin, OUTPUT); } start=micros(); /// digitalWrite(0,HIGH); digitalWrite(1,HIGH); digitalWrite(2,HIGH); digitalWrite(3,HIGH); digitalWrite(4,HIGH); digitalWrite(5,HIGH); digitalWrite(6,HIGH); digitalWrite(7,HIGH); digitalWrite(8,HIGH); digitalWrite(9,HIGH); digitalWrite(10,HIGH); digitalWrite(11,HIGH); digitalWrite(12,HIGH); digitalWrite(13,HIGH); /// start=micros()-start; Serial.println(start); } void loop(){ }
|
|
Không dùng for,Thời gian: 56 micro giây |
Khả năng điều khiển đồng bộ
pinMode/ digitalWrite
|
DDR/PORT
|
Lần lượt từng Pin (có thời gian trễ).
|
Điều khiển cùng lúc 8 pin (tức thì)
|
digitalRead()
Đọc giá trị ở trạng thái digital của pin 7
unsigned long start; void setup(){ Serial.begin(9600); bool val; pinMode(7,INPUT); start=micros(); /// val=digitalRead(7); /// start=micros()-start; Serial.println(start); } void loop(){ } |
unsigned long start; void setup(){ Serial.begin(9600); bool val; pinMode(7,INPUT); start=micros(); /// val=PIND&(1<<7); /// start=micros()-start; Serial.println(start); } void loop(){ } |
Thời gian: 8 micro giây |
4 micro giây |
Đọc giá trị 4 nút ấn Game
unsigned long start; void setup(){ Serial.begin(9600); bool b[4]; DDRB=B00000000; start=micros(); /// for(byte i=0; i<4; i++){ b[i]=digitalRead(8+i); } /// start=micros()-start; Serial.println(start); } void loop(){ } |
unsigned long start; void setup(){ Serial.begin(9600); bool b[4]; DDRB=B00000000; start=micros(); /// for( byte i=0; i<4; i++){ b[i]=PINB&( 1<<i); } /// start=micros()-start; Serial.println(start); } void loop(){ } |
Thời gian: 16 micro giây |
4 micro giây |
unsigned long start; void setup(){ Serial.begin(9600); bool b[4]; DDRB=B00000000; start=micros(); /// b[0]=digitalRead(8); b[1]=digitalRead(9); b[2]=digitalRead(10); b[3]=digitalRead(11); /// start=micros()-start; Serial.println(start); } void loop(){ }
|
unsigned long start; void setup(){ Serial.begin(9600); bool b[4]; DDRB=B00000000; start=micros(); /// b[0]=PINB&B00000001; b[1]=PINB&B00000010; b[2]=PINB&B00000100; b[3]=PINB&B00001000; /// start=micros()-start; Serial.println(start); } void loop(){ }
|
Không dùng for,Thời gian: 16 micro s | Không dùng for,4 micro s |
Đọc giá trị digital trên 16 pin.
unsigned long start; void setup(){ Serial.begin(9600); DDRD=255;// = B11111111 PORTD=255;//INTPUT PULLUP DDRC=255;// PORTC=255;//INTPUT PULLUP byte R1,R2; start=micros(); /// R1=PIND; R2=PINC; /// start=micros()-start; Serial.println(start); } void loop(){ }
|
4 micro giây |
analogRead();
Sử dụng 2 điện trở mắc nối tiếp làm cầu phân áp, đọc giá trị điện áp bằng chân A0
void setup(){ pinMode(A0,INPUT); Serial.begin(9600); } unsigned long start; unsigned int ana; void loop(){ start=micros(); /// ana=analogRead(0); /// start=micros()-start; Serial.println(start); Serial.println(ana); delay(2000); } |
void setup(){ pinMode(A0,INPUT); Serial.begin(9600); ADCSRA = ((ADCSRA&(B11111000)) | B00000010); // Cài tần số quét 4mhz } unsigned long start; unsigned int ana; void loop(){ start=micros(); /// ana=analogRead(0); /// start=micros()-start; Serial.println(start); Serial.println(ana); delay(2000); } |
Tần số của bộ đếm ADC mặc định: 125khz Ana=506; Thời gian: 116 micro giây |
Tần số của bộ đếm ADC: 4mhz
Tần số 1mhz:
|
Tốc độ lấy mẫu rất nhanh, rất thích hợp với các dự án liên quan đến analogRead().
Sử dụng 2 điện trở khác, mình dùng cả 4 chân analog A->A3 để đo.
unsigned long start; uint16_t val[4]; void setup(){ DDRC=B00000000;//cho tiện ha Serial.begin(9600); //// ADCSRA = ((ADCSRA&(B11111000)) | B00000010); } void loop(){ start=micros(); /// for(byte i=0; i<4; i++){ val[i]=analogRead(i); } /// start=micros()-start; Serial.println(start); for(byte i=0; i<4; i++){ Serial.print(val[i]); Serial.print("|"); } delay(2000); }
|
unsigned long start; uint16_t val[4]; void setup(){ DDRC=B00000000;//cho tiện ha Serial.begin(9600); ADCSRA = ((ADCSRA&(B11111000)) | B00000010); // Cài tần số quét 4mhz } void loop(){ start=micros(); /// for(byte i=0; i<4; i++){ val[i]=analogRead(i); } /// start=micros()-start; Serial.println(start); for(byte i=0; i<4; i++){ Serial.print(val[i]); Serial.print("|"); } delay(2000); }
|
Tần số của bộ đếm ADC mặc định: 125khz
Thời gian: 448 us. val[0]=val[1]=val[2]=val[3]=178. |
Tần số của bộ đếm ADC: 4mhz
Thời gian: 24 us. (nhanh hơn 18 lần) val[0]=val[1]=val[2]=val[3]=177. |
Tạm kết.
Dưới đây là test của anh John Boxall về tốc độ điều khiển chân port.
http://tronixstuff.com/2011/10/22/tutorial-arduino-port-manipulation/
Hẳn là có bạn vẫn còn nghi ngờ kết quả. Hihi.Các bạn hãy test lại nhé.
Hãy tìm mọi cách để đảo ngược tình thế nhé, có thể đấy.
Các code trên còn là các ví dụ mẫu cho các bạn tham khảo.
Việc điều khiển các chân port là không khó. Nó đem lại cho ta nhiều lợi ích tuyệt vời, không những Full Speed mà còn tiết kiệm dung lượng code . Bạn hãy tìm hiểu cách điều khiển port tại đây:
link: Điều khiển pin bằng ngôn ngữ chính thống .
Tác giả: Thái Sơn.