用示波器“看” arduino (1)

实验设备是一块 Arduino Uno 16M (是那种没有品牌的兼容版),示波器是 Teledyne Lecory Wave Runner 606Zi 600Mhz 20GS/s。

第一个实验:只使用DigitalWrite 能制造出来的最大频率是多少?

首先试试最通用的 digitalWrite 的方法不断在高低之间反转

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);
}

 

使用示波器抓图如下(下面的所有介绍都是具体解说在上,抓取波形在下):
我们设置的Delay 是500ms, 然后示波器的水平方向每一格也是500ms,垂直方向是电压,当前选择每格2V,因此看起来差不多是5v左右,符合预期。

image001

我选择了了Stop功能,放大波形进行查看。可以看到,最上面波形中黄色竖线实际上是一组波形,就是对应我们的拉高拉低。

image003

示波器有测量功能,直接调用该功能进行测试:可以看到幅度是4.946V,示波器还标记出来具体的测试方法,这在测量一些不是那么“规整”的波形时非常有用。

image005

再用示波器自动测量一下频率:是100kHz。

image007

可以在菜单中选择测试的具体方法(比如,测试频率通用的方法是波形上升沿50%的位置)

image009

再测量周期(其实给出来了频率,周期是可以直接换算出来的)

image011

结论:如果我们用 DigitalWrite拼命上下拉,最高是可以输出100Khz频率的。

之后,我们再试试使用PortB赋值直接拉出来的频率是多少?关于 PortB 指令可以在【参考1】看到。

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);
}

 

看起来下面波形感觉畸变比较严重(这里:解释一下,前面图看起来平滑的原因是采样时间导致的。比如,我的示波器单位时间可以采样500个点,如果我采样1s,放大之后,在1ms范围内只有5个点。如果我直接采样1ms,那么会有500个点来描绘波形,看起来自然“平滑”得多)

image013

测试幅度,会达到5.248v

image015

同样,使用自带功能测试频率:惊人的 7.99590Mhz

image017

因为一个周期里面实际上是有两条指令的(拉上拉下),已经非常接近主芯片的16Mhz了。

根据上面的结果引申的问题:如何同时拉高两个Port?

首先我们尝试一下 DigitalWrite的方法

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);
}

 

下图可以看到,注意我设置两个信号起始电压不同,为了观测方便,所以会一个上一个下
image019

放大之后查看

image021

为了方便观看,我设置他们电压起点相同,可以看出他们差不多有1个水平格子的差别(5us)。对于这个差异可以在【参考2】初步了解一下。

image023

再尝试PortB 直接赋值的方法

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);
}

 

结果上可以看作是同时发出的
image025

再放大查看,纠缠在一起,,波形上的细微差别可能是外围电路导致的。

image027

补记:为了比对,额外实验 DFrobot 的 RomeoBLEV1.0 的板子为了看得清楚,修改程序如下,去掉了 delay

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);  
}

 

先看大范围的,每组3次上升,每组之间的间隔是void loop() { } 中的代码导致的

image029

振幅上和之前的板子差不多 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/write
PORTD - The Port D Data Register - read/write
PIND - The Port D Input Pins Register - read only
PORTB 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/write
PORTB - The Port B Data Register - read/write
PINB - The Port B Input Pins Register - read only
PORTC 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/write
PORTC - The Port C Data Register - read/write
PINC - 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

发表评论

电子邮件地址不会被公开。 必填项已用*标注