查看: 237|回复: 7

[已解决] 自制分析引脚高低电平持续时间程序误差有点大?

[复制链接]
  • TA的每日心情
    无聊
    2020-7-19 00:16
  • 签到天数: 29 天

    [LV.4]偶尔看看III

    发表于 2020-7-2 02:03 | 显示全部楼层 |阅读模式
    本帖最后由 wanglanshu 于 2020-7-2 22:34 编辑

    如题,我在社区里找到延时0.25微秒的函数
    __asm__("nop\n\t""nop\n\t""nop\n\t""nop\n\t"); // 0.25us
    程序原理是主函数1微秒加一次数,被测信号用外部中断0变化沿记录下主函数里的计时时间,清零计时
    外部中断1低电平时识别按键按下发送保存的高低电平持续时间到串口。
    现在我把红外接收模块接在被测信号线上测量高低电平时间,
    然后对比IRremote红外库的数值发现,时间不但少了一倍,某些时间出现不正常的超大数值
    这是怎么回事
    以下是我的程序代码
    int count = 0;
    int number = 0;
    boolean resultstate[100];
    int resulttime[100];
    boolean state = HIGH;
    void setup() {
      // put your setup code here, to run once:
      pinMode(2, INPUT_PULLUP);
      pinMode(3, INPUT_PULLUP);
      Serial.begin(9600);
      state = HIGH;
      attachInterrupt(0, clc, CHANGE);
      attachInterrupt(1, outprint,LOW);
    }

    void loop()
    {
      // put your main code here, to run repeatedly:
      while (1)
      {
        __asm__("nop\n\t""nop\n\t""nop\n\t""nop\n\t"); // 0.25us
        __asm__("nop\n\t""nop\n\t""nop\n\t""nop\n\t"); // 0.25us
        __asm__("nop\n\t""nop\n\t""nop\n\t""nop\n\t"); // 0.25us
        __asm__("nop\n\t""nop\n\t""nop\n\t"); // 0.25us
        count++;
      }
    }
    void clc()
    {
      state = !state;

      resultstate[number] = state;
      resulttime[number] = count;
      number++;
      count = 0;

    }
    void outprint()
    {
      for (int i = 0; i < 100; i++)
      {
        if (resultstate == HIGH)
        {
          Serial.print("HIGH");
          Serial.print(resulttime);
          Serial.print(",");
        }
        else
        {
          Serial.print("LOW");
          Serial.print(resulttime);
          Serial.print(",");
        }
      }
      number = 0;
      count = 0;
      state=HIGH;
    }

  • TA的每日心情
    慵懒
    2018-11-12 08:58
  • 签到天数: 37 天

    [LV.5]常住居民I

    发表于 2020-7-3 09:24 | 显示全部楼层
    本质就是需要记录电平持续时间吧,arduino提供了系统运行时间函数micros() 单位微秒,利用它记录两次时间差,就能得出电平持续时间了
  • TA的每日心情
    擦汗
    2019-7-29 00:08
  • 签到天数: 47 天

    [LV.5]常住居民I

    发表于 2020-7-2 20:15 | 显示全部楼层
    wanglanshu 发表于 2020-7-2 16:31
    明白了,在count++前noInterrupts();在count++;后interrupts();
    不过这样会不会我频率15微秒的信号过来刚 ...

    nointerrupts 只是会暂停中断,不清空。中断的请求位会被保持,等 interrupts 开启后再执行。

    但是用了这个机制以后,中断的实时性会下降,最差时间就是 nointerrupts 到 interrupts 之间运行时间。
  • TA的每日心情
    无聊
    2020-7-19 00:16
  • 签到天数: 29 天

    [LV.4]偶尔看看III

     楼主| 发表于 2020-7-2 04:52 | 显示全部楼层
    这句话在UNO上跑接近1微秒了不是0.25微秒__asm__("nop\n\t""nop\n\t""nop\n\t""nop\n\t");
    那么请问延时1微妙到底怎么写?
    不要delayMicroseconds(1);试了运行不了
  • TA的每日心情
    擦汗
    2020-8-8 01:43
  • 签到天数: 35 天

    [LV.5]常住居民I

    发表于 2020-7-2 07:34 | 显示全部楼层
    wanglanshu 发表于 2020-7-2 04:52
    这句话在UNO上跑接近1微秒了不是0.25微秒__asm__("nop\n\t""nop\n\t""nop\n\t""nop\n\t");
    那么请问延时1 ...

    這是以前為了避開函式庫衝突上網找到 的 DELAY 方式
    (執行一個組合語言的虛工指令 nop 來達到延遲的作用),
    依 TRY & ERROR 的結果我加了一個校正常數值 1.3,
    音樂聽起來音調還蠻正常,應該不會差很多,提供給您參考:

    //定義 NOP (虛工指令)
    #define NOP do { __asm__ __volatile__ ("nop"); } while (0)

    void delayNANO( unsigned long NANO )
    //撰寫自己的延時函式(以奈秒計),無回傳值,引數 NANO 為延時奈秒值
    {
      for (unsigned long I=0; I< (unsigned int) (NANO*1.3) ; I++)
        NOP;
    }

    這是用在 16MHz 的 MINI PRO 上,可以修改 1.3 的常數值來進行修正 ^^
  • TA的每日心情
    无聊
    2020-7-19 00:16
  • 签到天数: 29 天

    [LV.4]偶尔看看III

     楼主| 发表于 2020-7-2 10:08 | 显示全部楼层
    shouzama 发表于 2020-7-2 07:34
    這是以前為了避開函式庫衝突上網找到 的 DELAY 方式
    (執行一個組合語言的虛工指令 nop 來達到延遲的作用) ...

    这前面一个for执行太多机器周期影响计时,我现在想抓一个15微秒的信号,时间差太多不准
    现在计时我改成了while (1) { __asm__("nop\n\t""nop\n\t""nop\n\t""nop\n\t");count++;}
    9000微秒左右的红外码记成9500左右凑合用
  • TA的每日心情
    擦汗
    2019-7-29 00:08
  • 签到天数: 47 天

    [LV.5]常住居民I

    发表于 2020-7-2 13:08 | 显示全部楼层
    临界区概念了解下?

    先不说代码计时准不准,单一个 int count 被两层代码调用(loop 和 int)就已经触发临界区了。

    最差情况:loop 里的 count++ 运行了一半(只有低8位++了,高8位还没动),
    就发生中断了,还去调用这个 count 读取判断,你猜咋着?
  • TA的每日心情
    无聊
    2020-7-19 00:16
  • 签到天数: 29 天

    [LV.4]偶尔看看III

     楼主| 发表于 2020-7-2 16:31 | 显示全部楼层
    t3486784401 发表于 2020-7-2 13:08
    临界区概念了解下?

    先不说代码计时准不准,单一个 int count 被两层代码调用(loop 和 int)就已经触发临 ...

    明白了,在count++前noInterrupts();在count++;后interrupts();
    不过这样会不会我频率15微秒的信号过来刚好被禁止中断而收不到信号?
    我试了红外模块好像没有遇到这么寸的情况67个中断都好好的发生了
    您需要登录后才可以回帖 登录 | 立即注册

    本版积分规则

    热门推荐

    5分钟带你快速了解新一代开发板:M5STACK
    5分钟带你快速了解新一代
    一、什么是M5Stack M5Stack是一种模块化、可堆叠扩展的开发板,每个模块
    创客火首发无人机编队套装,开启不一样的人工智能教育
    创客火首发无人机编队套装
    2017年国务院发布《新一代人工智能发展规划》,提出要广泛开展人工智能科普活动,在中
    胸卡式儿童红花榜(blinker+三色墨水屏)
    胸卡式儿童红花榜(blinke
    【项目名称】胸卡式儿童红花榜【项目简介】 小朋友有很强的自尊心和荣誉感,也有自
    ADAFRUIT_GFX库 tft屏真彩图怎么取模
    ADAFRUIT_GFX库 tft屏真彩
    请问这种16位的是用什么软件取的,网上找了好久取模软件,取的都是8位的
    温度传感器实验求代码
    温度传感器实验求代码
    求详细代码,急!
    Copyright   ©2015-2016  Arduino中文社区  Powered by©Discuz!   
    快速回复 返回顶部 返回列表