日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

【待续】Arduino踩坑手册-《中断故障排查指南》-中断、串口、定时器等片内硬件资源之间的冲突

發布時間:2024/3/12 编程问答 94 豆豆
生活随笔 收集整理的這篇文章主要介紹了 【待续】Arduino踩坑手册-《中断故障排查指南》-中断、串口、定时器等片内硬件资源之间的冲突 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

有個老師說:Arduino這玩意 更多的時候是兒童玩具 這話說的不錯
我還挺愿意把這話推廣一下 :過度封裝(而不讀文檔)是萬坑之源
各位可以發現:很多稍微高級一些的操作與arduino庫函數共用就會出現奇怪的問題
編者本著刨根問底的精神 看了些官方庫源碼 現將這幾天的研究結果總結如下
時間所限,如有疏漏之處還請各位看官指正


一、定時器相關

arduino uno(atmega328p)帶有三個定時器T0,T1,T2。T0和T2是8位定時器,T1是16位定時器,當noInterrputs函數執行之后,這三個計時器都會罷工。

1.不靠譜的tone,delay,millis函數

tone函數:
是利用T2定時器實現異步定時蜂鳴的,使用MsTimer2時要注意避免與tone發生沖突(癥狀:tone會影響MsTimer2的時鐘周期)。
這里可以考慮使用外國友人制作的TimerFreeTone庫,本質上是軟件實現的蜂鳴輸出,沒直接用定時器,但是用了millis(軟蜂鳴音與定時器產生的蜂鳴信號可能不是一個波形,用耳朵仔細聽會發現兩者音色不同,有強迫癥的朋友要小心了)
delay函數與millis函數:
是利用T0定時器實現延時,計時的,只要你不瞎調T0有關的寄存器,正常使用是沒問題的。
什么時候T0有關的寄存器會被更改呢?請看“PWM相關”一節。

2.題外話:VisualStudio相關

VisualStudio有個良心插件:VisualMicro,可以為用戶提供對Arduino調試的功能,然而Atmega xx8系列(Uno)統統是不支持JTAG調試的(兒童玩具實錘),剩下的方案就只有利用定時器實現軟調試,這個良心插件做到了軟調試,然而:

已知軟調試的不能做的:

  • 在不經任何處理的情況下,在attachInterrupt等中斷服務函數里跟蹤變量值
  • 在一切比定時器優先級高的中斷面前仍能守住控制權
  • 在noInterrupts之后與上位機保持聯系
  • 從兒童玩具變成實用工具
    除非你能保證本文里提到的除adc、串口外的一切資源,你都不會使用,否則用它很難讓你開心的調試。

二、attachInterrupt、Serial.event、Wire.begin等中斷相關

這個是用來設置外部中斷的(相似的有IIC從機模式中斷設置函數、串口中斷設置函數(MsTimer2的中斷函數設置暫時沒發現有下述問題)),通常會引發一些很迷的問題(“萬物皆失靈,中斷行不行。“),比如IIC設備輸出失靈,計時函數失靈

1.異常原因

進入使用attachInterrupt設置過的中斷函數前,arduino 會執行noInterrupts函數,關閉自己和比自己優先級低的中斷(優先級更低的中斷是否被關閉了有待考證)

2.異常名單

已測試可用的:

  • Serial.println()
  • pwm輸出

已測試有異常的:

  • IIC OLED輸出失靈
  • delay,tone瞬間完成
  • millis不計時

3.解決方法

在需要恢復定時器中斷的地方使用sei();恢復中斷
例子:

#inlcude "avr/io.h"//avr官方庫,可以引入高級底層函數 void isr() {Serial.println(millis());//可以正常輸出,但是在中斷開關打開前始終都是同一個值_delay_ms(100);//來自avr官方的軟延時,在這里不會被影響,用途是去抖sei();/*恢復定時器中斷,從這里開始millis和delay等就恢復正常了,同時中斷開關會再次被打開,有可能發生中斷還未結束,下一個中斷就又來了的情況(因此這個sei不應該被放在中斷函數的頂部,否則用戶的一次中斷操作可能會瞬間引發相當多次的中斷響應)*/delay(100);//正常Serial.println(millis());//跟上一次不一樣了 } void setup() {Serial.begin(9600);attachInterrupt(1,isr,LOW);pinMode(3,INPUT_PULLUP); } void loop() { }

三、PWM相關

arduino uno一共有6個PWM輸出腳,他們是基于定時器做輸出的
不同的引腳工作時占用的定時器不同(這里就可能有時鐘周期無意間被改動了的問題)
列表如下:

引腳定時器
5\6T0
9\10T1
11\3T2

如果你發現你設置的定時器本來應該每一秒做某事,結果這個周期突然就變了,可以考慮從這個方向排查一下,更換一組不與目前正在用的定時中斷沖突的PWM引腳

已經發現的異常

  • MsTimer2與tone()共用,結果MsTimer2突然飛快計時
  • (猜測)TimerOne與9/10腳pwm輸出同時使用,可能導致TimerOne周期異常

四、ADC相關

stc15系列做adc查詢推薦了一種中斷式查詢方案,在這里我想說,幸虧arduino沒用這個方案,所以目前看來analogRead()應該是你做過的最安全的事情之一,這個函數是阻塞式查詢的(這幾乎是廢話,因為異步查詢的函數一定會讓開發者提供個回調函數,或是個存返回值的地址,而analogRead顯然沒有)——在adc采完樣之前,cpu會一直等著,卡在while循環里等著adc忙位回零
但是仍然要小心,adc查詢過程可能會被中斷打斷,這就可能影響你采集數據的時效性,怎么說呢,analogRead還是挺耗時的,這就容易被中斷攔腰斬,所以,在時效性采集項目里,請管好你的中斷!

(未完待續 歡迎各位指正)

總結

以上是生活随笔為你收集整理的【待续】Arduino踩坑手册-《中断故障排查指南》-中断、串口、定时器等片内硬件资源之间的冲突的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。