arduino nano 的引脚输出脉冲,到底有多快?
在loop里只写
digitalWrite(LED_BUILTIN, HIGH);
digitalWrite(LED_BUILTIN, LOW);
试试效果
测试结果出乎意料16M的晶振啊,什么都不干,
只有145.7kHz?
看来digitalWrite不单纯啊,耗能忒大!
查到有玩家用端口控制的方式比较快。
PORTB = B100000;
PORTB = B000000;
一下上到2.672MHz
看图说明 loop本身也有一定的内耗
写个goto 死循环
_s: PORTB = B100000; PORTB = B000000;
goto _s;
4.009MHz效率提升近一倍
while死循环跟这个是一样的
循环本身也有耗能
如果不用循环,直接代码控制会怎么样呢
PORTB = B100000;
PORTB = B000000;
PORTB = B100000;
PORTB = B000000;
PORTB = B100000;
PORTB = B000000;
PORTB = B100000;
PORTB = B000000;
PORTB = B100000;
PORTB = B000000;
...
运行直接上8M
到达1/2晶振频率,这应该是极限了
蚂蚁指挥大象arduino控制伺服电机
测试一下脉冲控制伺服电机
发送脉冲需要
控制延时
//参考 https://www.arduino.cn/thread-12468-1-5.html
//關於delay(), millis(), micros(),delayMicroseconds與定时器(教程)計時
硬件上单片机接伺服要隔离
手工做了个隔离板,没有高速光耦器件,pc817一堆,频率不能太高,做个测试也足够了,下面效果图示波器上部一个通道是单片机的输出信号,下面是隔离输出给伺服驱动的信号
先上效果,这里有视频
图片
上代码
虽然没有细致打磨误差,基本做到辞能达意了
//参考 https://www.arduino.cn/thread-12468-1-5.html
#define ddtick __asm__("nop\n\t");
#define dd2tick __asm__("nop\n\t""nop\n\t");
#define dd4tick __asm__("nop\n\t""nop\n\t""nop\n\t""nop\n\t");
// the Macro dd4tick will delay 0.25us exactly on 16MHz Arduino
#define delayOneUs() { dd4tick; dd4tick; dd4tick; dd4tick; }
//16M
//ddtick 执行一个nop 是一个周期0.0625us (62.5ns)
//dd4tick 执行4个nop 是0.25us (250ns)
//delayOneUs 4个dd4tick 0.25*4=1us
void setup() {
// initialize digital pin LED_BUILTIN as an output.13号针
pinMode(LED_BUILTIN, OUTPUT);
digitalWrite(LED_BUILTIN,LOW);
//初始化串口连接波特率
Serial.begin(115200);
while (!Serial) {
; // wait for serial port to connect. Needed for native USB, on LEONARDO, MICRO, YUN, and other 32u4 based boards.
//等待串口连接。需要LEONARDO, MICRO, YUN, 或其他 32u4板子上的usb接口
}
Serial.println("pwm ok");
}
unsigned int i=1;
void maichong500ns(){
PORTB = B100000;
dd4tick;
dd2tick;
ddtick;
PORTB = B000000;//2tick
//约500ns高电平9tick=562.5ns
}
void maichong1000ns(){
PORTB = B100000;
dd4tick;
dd4tick;
dd4tick;
dd2tick;
ddtick;
PORTB = B000000;//2tick
//约1000ns高电平17tick=1062.5
}
void maichong2000ns(){
PORTB = B100000;
delayOneUs();//16ticks
dd4tick;
dd4tick;
dd4tick;
dd2tick;
//ddtick;
PORTB = B000000;//2tick
//约2000ns高电平33tick=2062.5
}
//
void F250kHz(unsigned long i){
while(i>0){
maichong2000ns();
i--;
delayOneUs();
dd4tick;
//dd4tick;
dd2tick;
ddtick;
}
}
void F200kHz(unsigned long i){
while(i>0){
i--;
PORTB = B100000;
delayOneUs();
delayOneUs();
dd2tick;
dd2tick;
ddtick;
PORTB = B000000;//2tick
delayOneUs();
delayOneUs();
dd2tick;
}
}
//误差
void F100kHz(unsigned long i){
while(i>0){
i--;
PORTB = B100000;
delayOneUs();
delayOneUs();
delayOneUs();
delayOneUs();
delayOneUs();
ddtick;
//delayOneUs();
PORTB = B000000;//2tick
delayOneUs();
delayOneUs();
delayOneUs();
delayOneUs();
dd2tick;
dd2tick;
dd2tick;
ddtick;
//delayOneUs();
}
}
//精度不高10.21
void F10kHz(unsigned long i){
while(i>0){
i--;
PORTB = B100000;
delayMicroseconds(50);
PORTB = B000000;//2tick
delayMicroseconds(50);
}
}
void F5kHz(unsigned long i){
while(i>0){
i--;
PORTB = B100000;
delayMicroseconds(100);
PORTB = B000000;//2tick
delayMicroseconds(100);
}
}
void F1kHz(unsigned long i){
while(i>0){
i--;
PORTB = B100000;
delayMicroseconds(500);
PORTB = B000000;//2tick
delayMicroseconds(500);
}
}
void F500Hz(unsigned long i){
while(i>0){
i--;
PORTB = B100000;
delay(1);
PORTB = B000000;//2tick
delay(2);
}
}
void loop() {
//unsigned long i=4294967295;
//F250kHz(1000000);
//F200kHz(100000);
//F100kHz(10000);
//F10kHz(10000);
F500Hz(2000);
Serial.println("F500Hz over");
F1kHz(5000);
Serial.println("F1kHz over");
F5kHz(50000);
Serial.println("F5kHz over");
F10kHz(50000);
Serial.println("F10kHz over");
/*while(i>0){
if(1){
maichong2000ns();
i--;
dd4tick;
dd4tick;
dd4tick;
ddtick;
//delayOneUs();
}else{
//delay(10);
//i=1024;
}
}*/
//i=1024;
//145.7kHz
//digitalWrite(LED_BUILTIN, HIGH);
//digitalWrite(LED_BUILTIN, LOW);
//看来执行digitalWrite本身就浪费很多时间
//2.672MHz
//PORTB = B100000;
//PORTB = B000000;
//用这种方式要快近十几倍,loop循环是瓶颈
//4.009MHz
//_s: PORTB = B100000; PORTB = B000000;
//goto _s;
//跳转死循比上面再快一倍
//4.009MHz
//while(true){
//PORTB = B100000;
//PORTB = B000000;
//}
//循环与跳转测量结果一样
//8.009MHz
/*while(true){
PORTB = B100000;
PORTB = B000000;
PORTB = B100000;
PORTB = B000000;
PORTB = B100000;
PORTB = B000000;
PORTB = B100000;
PORTB = B000000;
PORTB = B100000;
PORTB = B000000;
PORTB = B100000;
PORTB = B000000;
PORTB = B100000;
PORTB = B000000;
PORTB = B100000;
PORTB = B000000;
PORTB = B100000;
PORTB = B000000;
PORTB = B100000;
PORTB = B000000;
}*/
//直接操作端口高达8M,16M的晶振的一半?
}