用示波器“看” ARDUINO (1)

實驗設備是一塊 Arduino Uno 16M (是那種沒有品牌的兼容版),示波器是 Teledyne Lecory Wave Runner 606Zi 600Mhz 20GS/s。

第一個實驗:只使用DigitalWrite 能製造出來的最大頻率是多少?

首先試試最通用的 digitalWrite 的方法不斷在高低之間反轉

<code>const int PinA =  13;      

void setup() {
pinMode(PinA, OUTPUT);
digitalWrite(PinA,LOW);
}

void loop() {
digitalWrite(PinA,HIGH);
digitalWrite(PinA,LOW);
digitalWrite(PinA,HIGH);
digitalWrite(PinA,LOW);
digitalWrite(PinA,HIGH);
digitalWrite(PinA,LOW);
delay(500);
}
/<code>


使用示波器抓圖如下(下面的所有介紹都是具體解說在上,抓取波形在下):我們設置的Delay 是500ms, 然後示波器的水平方向每一格也是500ms,垂直方向是電壓,當前選擇每格2V,因此看起來差不多是5v左右,符合預期。

用示波器“看” ARDUINO (1)

我選擇了了Stop功能,放大波形進行查看。可以看到,最上面波形中黃色豎線實際上是一組波形,就是對應我們的拉高拉低。

用示波器“看” ARDUINO (1)

示波器有測量功能,直接調用該功能進行測試:可以看到幅度是4.946V,示波器還標記出來具體的測試方法,這在測量一些不是那麼“規整”的波形時非常有用。


用示波器“看” ARDUINO (1)


再用示波器自動測量一下頻率:是100kHz。


用示波器“看” ARDUINO (1)


可以在菜單中選擇測試的具體方法(比如,測試頻率通用的方法是波形上升沿50%的位置)

用示波器“看” ARDUINO (1)

再測量週期(其實給出來了頻率,週期是可以直接換算出來的)

用示波器“看” ARDUINO (1)

結論:如果我們用 DigitalWrite拼命上下拉,最高是可以輸出100Khz頻率的。

之後,我們再試試使用PortB賦值直接拉出來的頻率是多少?關於 PortB 指令可以在【參考1】看到。

<code>const int PinA =  13;      
void setup() {
pinMode(PinA, OUTPUT);
digitalWrite(PinA,LOW);

}

void loop() {
PORTB = B100000; //digitalWrite(PinA,HIGH);
PORTB = B000000; //digitalWrite(PinA,LOW);
PORTB = B100000; //digitalWrite(PinA,HIGH);
PORTB = B000000; //digitalWrite(PinA,LOW);
PORTB = B100000; //digitalWrite(PinA,HIGH);
PORTB = B000000; //digitalWrite(PinA,LOW);

delay(500);
}
/<code>


看起來下面波形感覺畸變比較嚴重(這裡:解釋一下,前面圖看起來平滑的原因是採樣時間導致的。比如,我的示波器單位時間可以採樣500個點,如果我採樣1s,放大之後,在1ms範圍內只有5個點。如果我直接採樣1ms,那麼會有500個點來描繪波形,看起來自然“平滑”得多)


用示波器“看” ARDUINO (1)


測試幅度,會達到5.248v


用示波器“看” ARDUINO (1)


同樣,使用自帶功能測試頻率:驚人的 7.99590Mhz


用示波器“看” ARDUINO (1)


因為一個週期裡面實際上是有兩條指令的(拉上拉下),已經非常接近主芯片的16Mhz了。

根據上面的結果引申的問題:如何同時拉高兩個Port?

首先我們嘗試一下 DigitalWrite的方法

<code>const int PinA =  13;      
const int PinB = 8;
void setup() {
pinMode(PinA, OUTPUT);
digitalWrite(PinA,LOW);


pinMode(PinB, OUTPUT);
digitalWrite(PinB,LOW);
}

void loop() {
digitalWrite(PinA,HIGH);
digitalWrite(PinB,HIGH);
digitalWrite(PinA,LOW);
digitalWrite(PinB,LOW);

delay(500);
}
/<code>


下圖可以看到,注意我設置兩個信號起始電壓不同,為了觀測方便,所以會一個上一個下

用示波器“看” ARDUINO (1)

放大之後查看

用示波器“看” ARDUINO (1)

為了方便觀看,我設置他們電壓起點相同,可以看出他們差不多有1個水平格子的差別(5us)。對於這個差異可以在【參考2】初步瞭解一下。

用示波器“看” ARDUINO (1)

再嘗試PortB 直接賦值的方法

<code>const int PinA =  13;      
const int PinB = 8;
void setup() {
pinMode(PinA, OUTPUT);
digitalWrite(PinA,LOW);

pinMode(PinB, OUTPUT);
digitalWrite(PinB,LOW);
}

void loop() {

PORTB = B100001; //digitalWrite(PinA,HIGH); digitalWrite(PinB,HIGH);
PORTB = B000000; //digitalWrite(PinA,LOW); digitalWrite(PinB,LOW);

delay(500);
}
/<code>


結果上可以看作是同時發出的

用示波器“看” ARDUINO (1)

再放大查看,糾纏在一起,,波形上的細微差別可能是外圍電路導致的。

用示波器“看” ARDUINO (1)

補記:為了比對,額外實驗 DFrobot 的 RomeoBLEV1.0 的板子為了看得清楚,修改程序如下,去掉了 delay

<code>const int PinA =  13;      
void setup() {
pinMode(PinA, OUTPUT);
digitalWrite(PinA,LOW);
}

void loop() {
PORTB = B100000; //digitalWrite(PinA,HIGH);

PORTB = B000000; //digitalWrite(PinA,LOW);
PORTB = B100000; //digitalWrite(PinA,HIGH);
PORTB = B000000; //digitalWrite(PinA,LOW);
PORTB = B100000; //digitalWrite(PinA,HIGH);
PORTB = B000000; //digitalWrite(PinA,LOW);
}
/<code>


先看大範圍的,每組3次上升,每組之間的間隔是void loop() { } 中的代碼導致的


振幅上和之前的板子差不多 5.13v左右,實際多測試幾次也會出現 5.2v。看起來由品牌的板子和無品牌的板子在這方便沒有差別。

參考:

1.關於Port x的說明https://www.arduino.cc/en/Reference/PortManipulation

PORTD maps to Arduino digital pins 0 to 7

DDRD - The Port D Data Direction Register - read/writePORTD - The Port D Data Register - read/writePIND - The Port D Input Pins Register - read onlyPORTB maps to Arduino digital pins 8 to 13 The two high bits (6 & 7) map to the crystal pins and are not usable

DDRB - The Port B Data Direction Register - read/writePORTB - The Port B Data Register - read/writePINB - The Port B Input Pins Register - read onlyPORTC maps to Arduino analog pins 0 to 5. Pins 6 & 7 are only accessible on the Arduino Mini

DDRC - The Port C Data Direction Register - read/writePORTC - The Port C Data Register - read/writePINC - The Port C Input Pins Register - read only

同樣,這篇文章中提到了如何同時拉Pin 的方法

Sometimes you might need to set multiple output pins at exactly the same time. Calling digitalWrite(10,HIGH); followed by digitalWrite(11,HIGH); will cause pin 10 to go HIGH several microseconds before pin 11, which may confuse certain time-sensitive external digital circuits you have hooked up. Alternatively, you could set both pins high at exactly the same moment in time using PORTB |= B1100;

2. Arduino 代碼機制 http://blog.csdn.net/pinbodexiaozhu/article/details/42641273


分享到:


相關文章: