加米 发表于 2016-3-22 16:21:58

想实现pulseIn功能,又不想等待,解决方案是millis和micros(测速新方法!)

本帖最后由 加米 于 2016-3-22 17:41 编辑

分析了一下Super169的帖子,结合自己的理解,觉得pulseIn函数还是有一定缺陷的,嗯,没错!
http://www.geek-workshop.com/thread-11138-1-1.html

unsigned long (uint8_t pin, uint8_t state, unsigned long timeout);pulseIn函数返回值类型为无符号长整型(unsigned long),3个参数分别表示脉冲输入的引脚、脉冲响应的状态(高脉冲或低脉冲)和超时时间。这样的缺陷在于,如果状态一开始就是HIGH/LOW,那就会一直触发等待,而且如果状态一直保持,那只能通过Super169的方法通过多次测量取最大值了。

所以总结起来pulseIn有以下缺陷:

1、需要等待时间
         对于程序执行效率而言,等待意味着白白损耗了CPU时间,导致效率低下,而且pulseIn的默认等待时间是1s(如果没记错的话)。
         对于高频信号,如果不想过多等待,得把 timeout 改小一点,改太小又不行;
         对于低频信号(比如10s才电平转换一次),那只能等了,但是,10s可以做很多事情了。

2、需要对齐电平转换的位置,或者多次测量取max。
         具体分析,Super169已经说得很明白了。
         http://www.geek-workshop.com/forum.php?mod=viewthread&tid=11138&extra=page%3D1&page=1


解决方法:
         对于需要等待时间的解决方法是使用中断,或者类中断(定时器中断)。
         对于需要对齐电平转换的解决方法是,使用上升沿/下降沿触发计时/结束。

具体看代码:

unsigned long duration= 0;//duration 就是要测量的IO口电平转换时间了
void setup()
{
    attachInterrupt(0,FLASH,RISING);//0号外部中断.上升沿触发,FLASH为中断服务程序
}

void loop()
{
    duration = 0;//重新幅值
/*你想做的一大堆事^v^*/

/*此处省略一万行代码...*/
}

void FLASH()
{
   static unsigned long OldTime = 0;
   duration = micros() - OldTime;
   OldTime= micros();
}

使用这种方法的不足是,检测引脚只能是外部中断引脚,但好处也是显而易见的,如果还有什么好方法别忘了告诉我哦
如果不需要us的时间精度可以将void FLASH()中的micros换成精度为ms的millis就可以了。
另外,这种方法也可以用来测试哦,不过前提是你只有两个轮子的话(普通arduino只有两个中断引脚)

附上自己的调试图一张:

加米 发表于 2016-3-22 16:28:16

自己顶一下

加米 发表于 2016-3-22 16:31:27

板凳也自己占了:D

xiaozeng 发表于 2016-4-25 00:00:52

超声波的可以用这个吗?
页: [1]
查看完整版本: 想实现pulseIn功能,又不想等待,解决方案是millis和micros(测速新方法!)