查看: 55675|回复: 26

【教程】關於中断(Interrupt)的一些五四三... 中斷 . .

[复制链接]

该用户从未签到

发表于 2015-3-23 04:46 | 显示全部楼层 |阅读模式
本帖最后由 tsaiwn 于 2015-3-28 02:51 编辑

註: 五四三就是英文的 etc.

現在來跟大家分享關於中断處理的一些常見問題 . . .

常常看到有人問到:
   我在中斷的子程序内加進IIC通信後就進不了中斷了..求指點。
  或是
   我在中断程序内加入 Lcd_IIC 的程序後就死機...求指點。

其實, 不論是 IIC/TWI, 或是 SPI, 以及硬串口、軟串口甚至 Serial.print 都是要靠中断來幫忙處理,
如果你把中断禁止了, 那 IIC/TWI, SPI 都無法動作了 !

啥?
你說你沒有禁止中斷?
可是 Arduino 一旦進入中断程序 就會自動禁止中斷,
因此, 在中断程序內(包括它的子程序內)原則上無法做 IIC 與 SPI 以及軟硬串口的通信!
為何說原則上呢?
因為你還是可以在中断程序內把中斷打開,
只要這樣:
   sei( );
可是,
那是否有其他問題就要看看你的中断處理到底做何事情,
以及中断來的時間是否太短 ?
就是只要來得及處理或是中斷重進入(reentrant)不會有問題, 那就可以把中斷打開 !
關於中斷的重進入(reentrant), 請參考維基百科:
   http://en.wikipedia.org/wiki/Reentrancy_(computing)
當然, 如果你測試結果沒問題那就放心的打開中斷 !

關於中斷的概念可以看看奈何大神寫的這篇有趣文章:
   http://www.arduino.cn/thread-2421-1-1.html

該篇主要是介紹Arduino外部中斷INT0, INT1的使用,
也就是外部 0 號和 1 號中斷(pin2, pin 3)的介紹,
使用 attachInterrupt(INT_number, function, mode);
也可以參考:
   http://arduino.cc/en/Reference/attachInterrupt  

    如果你是要使用內部定時器(timer0, timer1, timer2)定時中斷,
請看我寫的這些貼文:
  使用 MsTimer2 庫定時做很多事(教程):
    http://www.arduino.cn/thread-12435-1-1.html
  使用TimerOne庫(Timer1)定時做多件事(教程):
    http://www.arduino.cn/thread-12441-1-4.html
  自己控制 timer1 計時器定時做多件事(教程):
    http://www.arduino.cn/thread-12445-1-1.html
  自己控制 timer2 定時器定時做多件事(教程)":
    http://www.arduino.cn/thread-12448-1-1.html
  補充設定 timer1 計時器和 timer2 定時器定時做多件事(教程)
    http://www.arduino.cn/thread-12452-1-2.html

    不論是 SPI, IIC 與軟串口都是大量使用中斷處理(Interrupt),
在中斷處理程序內工作沒處理完之前是在禁止其它中斷的狀態,
如果中斷處理程序做太多事, 本來就會影響其他中斷的進行!!

    IIC 使用 ISR(TWI_vect) 中斷處理,
軟串口SoftwareSerial 使用 ISR(PCINT0_vect) 或類似的(PCINT1/2)中斷,
   雖然 ISR(PCINT0_vect) 的優先權高於 ISR(TWI_vect),
但一旦進入 ISR(TWI_vect) 內由於中斷請求被禁止,
此時即使軟串口所用的  ISR(PCINT0_vect) 中斷來到,
一樣無法處理, 於是導致軟串口的通信失常或數據遺失 !


關於Arduino的 CPU 之25種中斷之優先順序可看:
  http://gammon.com.au/interrupts
就是說, 除了 Reset 之外, 還有 25種中斷可以使用:
(依照優先順序排列, 所以外部 pin 2 的 INT0 是最優先的!, 其次是 pin 3 的 INT1 中斷)


1  Reset
2  External Interrupt Request 0  (pin D2)          (INT0_vect)
3  External Interrupt Request 1  (pin D3)          (INT1_vect)
4  Pin Change Interrupt Request 0 (pins D8 to D13) (PCINT0_vect)
5  Pin Change Interrupt Request 1 (pins A0 to A5)  (PCINT1_vect)
6  Pin Change Interrupt Request 2 (pins D0 to D7)  (PCINT2_vect)
7  Watchdog Time-out Interrupt                     (WDT_vect)
8  Timer/Counter2 Compare Match A                  (TIMER2_COMPA_vect)
9  Timer/Counter2 Compare Match B                  (TIMER2_COMPB_vect)
10  Timer/Counter2 Overflow                             (TIMER2_OVF_vect)
11  Timer/Counter1 Capture Event                    (TIMER1_CAPT_vect)
12  Timer/Counter1 Compare Match A                  (TIMER1_COMPA_vect)
13  Timer/Counter1 Compare Match B                  (TIMER1_COMPB_vect)
14  Timer/Counter1 Overflow                           (TIMER1_OVF_vect)
15  Timer/Counter0 Compare Match A                  (TIMER0_COMPA_vect)
16  Timer/Counter0 Compare Match B                  (TIMER0_COMPB_vect)
17  Timer/Counter0 Overflow                         (TIMER0_OVF_vect)
18  SPI Serial Transfer Complete                     (SPI_STC_vect)
19  USART Rx Complete                                (USART_RX_vect)
20  USART, Data Register Empty                      (USART_UDRE_vect)
21  USART, Tx Complete                              (USART_TX_vect)
22  ADC Conversion Complete                         (ADC_vect)
23  EEPROM Ready                                     (EE_READY_vect)
24  Analog Comparator                               (ANALOG_COMP_vect)
25  2-wire Serial Interface  (I2C)                  (TWI_vect)
26  Store Program Memory Ready                      (SPM_READY_vect)
-----------------------------------------------------------

關於IIC與軟串口等的源代碼可看這
   https://github.com/arduino/Ardui ... duino/avr/libraries
   ( 軟串口是在 SoftwareSerial.cpp;
     IIC 要看 Wire.cpp 和其 utility 目錄內的 twi.c )

接下來,
我們來討論可以用在全部 pin 的 Pin Change Interrupt 針腳狀態改變中斷 !
   http://playground.arduino.cc/Main/PinChangeInterrupt
這個在官網已經有大神幫忙寫了Library庫可用:
   http://playground.arduino.cc/Main/PinChangeInt

請注意,
如果你使用了軟串口(SoftwareSerial),
就是說你用了以下:
   #include <SoftwareSerial.h>
那接著我們要講的 PCI (Pin Change Interrupt) 就不能用了,
因為軟串口的庫已經寫個該三個中斷處理 ISR( ) 如下:
#if defined(PCINT0_vect)
ISR(PCINT0_vect)
{
  SoftwareSerial::handle_interrupt();
}
#endif

#if defined(PCINT1_vect)
ISR(PCINT1_vect)
{
  SoftwareSerial::handle_interrupt();
}
#endif

#if defined(PCINT2_vect)
ISR(PCINT2_vect)
{
  SoftwareSerial::handle_interrupt();
}
#endif

這可以在你 Arduino IDE 目錄下的以下檔案找到:
   libraries\SoftwareSerial\SoftwareSerial.cpp

在Arduino UNO 以及大部分的板子有 Digital pin 0 到 pin 13,
以及 analog pin A0 到 A5 (又稱 pin 14 到 pin 19);
這 20支 pin 分為三組, 對應到 ISR(PCINT2_vect),
ISR(PCINT0_vect), 以及 ISR(PCINT1_vect) 這三個 ISR( ) 中斷程序:
     ISR (PCINT2_vect) 處理  Pin D0 to D7
     ISR (PCINT0_vect) 處理  Pin D8 to D13
     ISR (PCINT1_vect) 處理  Pin A0 to A5

Pin Change Interrupts 範例:[mw_shl_code=bash,true]ISR (PCINT0_vect)
{
// handle pin change interrupt for pin D8 to D13 here
} // end of PCINT0_vect

ISR (PCINT1_vect)
{
// handle pin change interrupt for pin A0 to A5 here
} // end of PCINT1_vect

ISR (PCINT2_vect)
{
// handle pin change interrupt for pin D0 to D7 here
} // end of PCINT2_vect


void setup ()
{
// pin change interrupt (example for pin D9)
PCMSK0 |= bit (PCINT1); // want pin 9
PCIFR |= bit (PCIF0); // clear any outstanding interrupts
PCICR |= bit (PCIE0); // enable pin change interrupts for D8 to D13
}


[/mw_shl_code]



Table of pins -> pin change names / masks[mw_shl_code=bash,true]
D0 PCINT16 (PCMSK2 / PCIF2 / PCIE2)
D1 PCINT17 (PCMSK2 / PCIF2 / PCIE2)
D2 PCINT18 (PCMSK2 / PCIF2 / PCIE2)
D3 PCINT19 (PCMSK2 / PCIF2 / PCIE2)
D4 PCINT20 (PCMSK2 / PCIF2 / PCIE2)
D5 PCINT21 (PCMSK2 / PCIF2 / PCIE2)
D6 PCINT22 (PCMSK2 / PCIF2 / PCIE2)
D7 PCINT23 (PCMSK2 / PCIF2 / PCIE2)
D8 PCINT0 (PCMSK0 / PCIF0 / PCIE0)
D9 PCINT1 (PCMSK0 / PCIF0 / PCIE0)  <===== PCINT1 代表 pin D9
D10 PCINT2 (PCMSK0 / PCIF0 / PCIE0)
D11 PCINT3 (PCMSK0 / PCIF0 / PCIE0)
D12 PCINT4 (PCMSK0 / PCIF0 / PCIE0)
D13 PCINT5 (PCMSK0 / PCIF0 / PCIE0)
A0 PCINT8 (PCMSK1 / PCIF1 / PCIE1)
A1 PCINT9 (PCMSK1 / PCIF1 / PCIE1)
A2 PCINT10 (PCMSK1 / PCIF1 / PCIE1)
A3 PCINT11 (PCMSK1 / PCIF1 / PCIE1)
A4 PCINT12 (PCMSK1 / PCIF1 / PCIE1)
A5 PCINT13 (PCMSK1 / PCIF1 / PCIE1)

[/mw_shl_code]




Reference:   http://gammon.com.au/interrupts

接下來我們來測試兩個使用中斷處理的按鈕 ! (兩個按鈕按下與放掉都會產生中斷)
也可以不必使用真的按鈕, 拿一條杜邦線或是一條電導線即可測試了 ,
(例如把沒用的網路線剝開裡面有八條電導線可用)
第一個按鈕接 pin2 以便使用外部中斷 INT0,
因為我們設定  pinMode(2, INPUT_PULLUP); 所以按鈕另一端接 GND 即可 !
另一個按鈕接 pin 8, (也是用 PULLUP, 且代碼已經寫成可把 pinPrint 可改為 9, 或 10 都可),
請看代碼如下:


[mw_shl_code=bash,true]// 按鈕接 pin 2
// 另一個測試按鈕接  pin 8 (pinPrint), 或改 9, 或 10 都可, pinPrint:
int pinPrint = 8;  // interrupt to print value of cnt; 8/9/10 OK
const byte led = 13;
const byte button = 2;  // pin2 是 INT0 外部中斷
volatile int cnt = 0;  // 紀錄 button  interrupt 次數
volatile int doPrint = 0;
// Interrupt Service Routine (ISR)
void btnChange ( ) {  // for INT0 to attach
  ++cnt;
  if (digitalRead (button) == HIGH) digitalWrite (led, HIGH);
  else digitalWrite (led, LOW);
}  // end of btnChange
////////////////
void setup ()
{
  pinMode(led, OUTPUT); digitalWrite(13, 0);
  Serial.begin(9600);
  pinMode(button, INPUT_PULLUP); //internal pull-up resistor
  setup555( pinPrint );  // set interrupt for pin 8
  attachInterrupt (0, btnChange, CHANGE);  //  INT0 == pin 2
  Serial.print("Started... cnt ="); Serial.println(cnt);
}  // end of setup
void loop ()
{
  // loop doing nothing
  if(doPrint) {
    doPrint = 0;
    Serial.println(String("Interrupt cnt=") +cnt+", time=" + millis( ) );
  }// if(
  // .. .. ..
} // loop(
void setup555(int pin ) {
  pinMode(pin, INPUT_PULLUP);  // 啟動內部上拉電阻
  cli( );
  switch(pin) {
    case 8: PCMSK0 |= bit (PCINT0);  break; // the pin 8
    case 9: PCMSK0 |= bit (PCINT1);  break; // the pin 9
    case 10: PCMSK0 |= bit (PCINT2);  break; // the pin 10
  }
  PCIFR  |= bit (PCIF0);   // clear any outstanding interrupts
  PCICR  |= bit (PCIE0);   // enable pin change interrupts for D8 to D13
  sei( );
}
void haha( ) {
  digitalWrite(led, 0 );
  doPrint = 1;   // 要求 loop ( ) 內要做一次 print
}
ISR (PCINT0_vect) {
  // one of pins D8 to D13 has changed
  haha( );
}
[/mw_shl_code]


如何測試呢?
(1)把串口監視器 Serial Monitor 開啟
(2)拿一根杜邦線或任意電導線, 一端接 GND,
    (a)另一端輕輕觸一下 pin 8  (由 pinPrint 決定, 目前寫成可以 8, 或 9, 或 10, 改 pinPrint 即可 !)
    (b)改輕輕觸一下 pin 2   (或按下這按鈕)
        你會發現按下這按鈕或插入 pin 2  時 Led 13 熄滅, 拉出時或放掉按鈕時 Led 13 燈亮 !
    (c)再改回輕輕觸一下 pin 8
        注意串口監視器輸出的答案!
  發現了沒, 只插入一下 pin 2 又拔掉,
  結果   cnt 的值就跳好多, 理論上應該是多 2 (按下放掉各加 1),
  但是實際卻好像發生了很多次甚至一二十次中斷 ! 這就是所謂抖動(Bouncing)的問題 !
  還有, 插一下 pin 8 卻印好幾次, 這也是抖動的問題 !
(3)重複剛剛 (2)全部步驟, 注意 LED 13 的亮滅, 以及串口監視器輸出的值 !

--------------------------------------------
再來把以上範例改為方便針對監看 pin 2, 3, 4, 5, 6, 7 這六支 pin
你只要對照面範例與對照表就會改為可監看 pin A0 到 A5 了 !
以下我故意把 pinPrint 設 2, 看看會怎樣 ?!
注意, pin 2 同時也是 INT0 的外部中斷,
就是說以下程序碼中 pinPrint 與 button 都是 2, 這樣用接 GND 線輕觸一下 pin 2,
勢必兩種中斷都會產生, 那先做哪個呢?
其實這之前就說過了 , 在 25 種中斷之中, INT0 的優先權是最高的 !

[mw_shl_code=bash,true]// 按鈕接 pin 2
// 另一個測試按鈕接  pin 7 (pinPrint), 或 6,5,4,3,2 都可, pinPrint:
int pinPrint = 2;  // 可故意改為 2 測試看看
const byte led = 13;
const byte button = 2;  // pin2 是 INT0 外部中斷
volatile int cnt = 0;  // 紀錄 button  interrupt 次數
volatile int cnt88 = 0; // by haha
volatile int doPrint = 0;
// Interrupt Service Routine (ISR)
void btnChange ( ) {  // for INT0 to attach
  ++cnt;
  //if (digitalRead (button) == HIGH)
  digitalWrite (led, HIGH);
  //else digitalWrite (led, LOW);
}  // end of btnChange
////////////////
void setup ()
{
  pinMode(led, OUTPUT); digitalWrite(13, 0);
  Serial.begin(9600);
  pinMode(button, INPUT_PULLUP); //internal pull-up resistor
  setup555( pinPrint );  // set interrupt for pin 8
  attachInterrupt (0, btnChange, FALLING);  //  INT0 == pin 2
  Serial.print("Started... cnt ="); Serial.println(cnt);
}  // end of setup
void loop ()
{
  // loop doing nothing
  if(doPrint) {
    doPrint = 0;
    Serial.println(String("Interrupt cnt=") +cnt+
    ", cnt88=" + cnt88 +
    ", time=" + millis( ) );
  }// if(
  // .. .. ..
} // loop(
void setup555(int pin ) {
  pinMode(pin, INPUT_PULLUP);  // 啟動內部上拉電阻
  cli( );
  switch(pin) {
    case 2: PCMSK2 |= bit (PCINT18);  break; // the pin 2
    case 3: PCMSK2 |= bit (PCINT19);  break; // the pin 3
    case 4: PCMSK2 |= bit (PCINT20);  break; // the pin 4
    case 5: PCMSK2 |= bit (PCINT21);  break; // the pin 5
    case 6: PCMSK2 |= bit (PCINT22);  break; // the pin 6
    case 7: PCMSK2 |= bit (PCINT23);  break; // the pin 7
  }
  PCIFR  |= bit (PCIF2);   // clear any outstanding interrupts
  PCICR  |= bit (PCIE2);   // enable pin change interrupts for D8 to D13
  sei( );
}
void haha( ) {
  cnt88++;
  digitalWrite(led, 0 );
  doPrint = 1;   // 要求 loop ( ) 內要做一次 print
}
ISR (PCINT2_vect) {
  // one of pins D8 to D13 has changed
  haha( );
}[/mw_shl_code]

以上這範例的測試結果也夾檔在後面 !
你可以看出 INT0 的中斷優先處理, 否則在 loop( )內第一次印出的 cnt 就應該是 0 才對 !
    [img]http://www.arduino.cn/forum.php?mod=attachment&aid=MTA0NDh8ZDRlZDg0NTF8MTQyNzQ4MTY3OHwzMDYwMXwxMzIwNQ%3D%3D¬humb=yes[/img]
forum.php?mod=attachment&aid=MTA0NDh8ZDRlZDg0NTF8MTQyNzQ4MTY3OHwzMDYwMXwxMzIwNQ%3D%3D&nothumb=yes.gif

請注意, 目前為止我們還沒用到國外某大神寫的 PinChangeInterrupt 的庫喔 !

關於 P-C-I 庫 : Pin Change Interrupt Library for the Arduino

要使用 Pin Change Interrupt 庫, 必須先下載該 P-C-I 庫來安裝:
  抓回 .zip 檔案之後, 從你的 Arduino IDE
     Sketch  >  Import Library...  >  Add Library...
  然後選到該 .zip 檔案, 把 PCI 庫加進去你的 Arduino IDE.
  (不必手動解壓縮再把PinChangeInt庫目錄複製到 libraris 目錄, 當然你要那麼做也可以!)
  該 P-C-I 庫可到這抓:
    https://github.com/GreyGnome/PinChangeInt

  或直接點以下連結: (PinChangeInt-master.zip)
    https://github.com/GreyGnome/PinChangeInt/archive/master.zip
  這個庫從以前 Version 1.0 的 4.5KB,
  到現在 2.40版已經有 49KB.

  如果你只是要在Arduino UNO 上用, 其實抓P-C-I 庫的 1.0版的就可以了 :-)
不過要注意 1.0版和 1.72版只可用舊的寫法:
   PCattachInterrupt(pin, yourISRFunction, FALLING);   // FALLING, RISING, CHANGE
   PCdetachInterrupt(pin);

(在這篇最後夾檔 1.0 版, 1.72版, 以及  2.402 版本)

其實, 這個 P-C-I 庫所用的方法就是類似上面我寫的範例,
只是P-C-I庫已經考慮所有的 pin, 但上述我寫的範例只有考慮 pin 8, 9, 10 這三支腳位,
且 P-C-I 庫設計成仿照外部中斷INT0, INT1的使用方法,
可以用類似寫法指定監看某 pin 的變化產生中斷, 例如:
   attachPinChangeInterrupt(pin, ggyy, FALLING);
表示只要 pin 由高電平往低電平下降(FALLING), 就產生中斷跳入函數 ggyy( ) 內 !
再次提醒, 關於外部中斷INT0, INT1的使用,以及中斷的概念,
還是請看看奈何大神寫的這篇有趣文章:
   http://www.arduino.cn/thread-2421-1-1.html


接著我們來看看使用該 P-C-I 庫的簡單範例,
這是我把範例拿來稍微改過,
測試 pin 8 產生中斷的次數, 你可以找一個按鈕連接 pin 8 (另一端接 GND),
或是拿一條杜邦線或任意電導線, 一端接 GND, 另一端輕觸 pin 8
記得要把串口監視器 Serial Monitor 打開觀看!
[mw_shl_code=bash,true]#include <inChangeInt.h>
//  以下用 pin 8, 你可以改為其他 pin
#define testPIN 8

volatile unsigned int interruptCount=0; // 最大到 65535, 接著會歸零從頭算起

// 儘量不要在中斷處理程序內用 Serial.print()  
// 中斷程序不要做太多事! 這裡我們只是把中斷次數 + 1
void ggyy() {   // 中斷處理程序
  interruptCount++;
}

// Attach the interrupt in setup()
void setup() {
  pinMode(testPIN, INPUT_PULLUP);  // 啟動內部上拉電阻 the pullup resistor.
  attachPinChangeInterrupt(testPIN, ggyy, FALLING);
  Serial.begin(9600);
  Serial.println("start ------");
}

void loop() {
  delay(3388);    // Every  3.388 second,
  Serial.print("Total: ");
  Serial.print(interruptCount, DEC);   // print the interrupt count.
  Serial.println(" interrupt times so far.");
}[/mw_shl_code]


看到了, 很簡單吧 ?
就是先寫好中斷處理函數例如 ggyy( );
然後用類似使用外部中斷 INT0 和 INT1 的方法:
    attachPinChangeInterrupt(testPIN, ggyy, FALLING);
表示監督 testPIN 的狀態,
當 testPIN 由高電平往低電平下降(FALLING)時產生中斷, 跳入函數 ggyy( );
你可以把上述例子複製並改變 testPIN 的值為其它 pin 多多測試看看 !

如果你是使用 1.0版本或 1.72版本,
則改用:
   PCattachInterrupt(testPIN, ggyy, FALLING);

如何停止某 pin 的中斷處理 ?
很簡單, 與使用外部中斷 INT0, INT1 類似:
   detachPinChangeInterrupt(pin);
這樣就可以了 !

如果你是使用 1.0版本或 1.72版本,
對某 pin 啟動中斷用:
   PCattachInterrupt(pin, yourFunction, mode);
停止中斷用:
   PCdetachInterrupt(pin);


更複雜的用法可自己看抓回 P-C-I 庫內的範例 {:soso_e100:}

參考:
   http://playground.arduino.cc/Main/PinChangeInt
   http://playground.arduino.cc/Main/PinChangeIntExample
   http://playground.arduino.cc/Code/ReadReceiver


javascript:;

javascript:;

故意測 pin2 的 pin change interrupt 與 INT0 (也是 pin2)

故意測 pin2 的 pin change interrupt 與 INT0 (也是 pin2)

PinChangeInt100.zip

4.46 KB, 下载次数: 39

Version 1.0

pinchangeint-v1.72.zip

20.92 KB, 下载次数: 38

Version 1.72

PinChangeInt-master.zip

49.04 KB, 下载次数: 47

Version 2.402

该用户从未签到

发表于 2015-3-24 09:18 | 显示全部楼层
好帖,总是那么详实。

该用户从未签到

 楼主| 发表于 2015-3-23 04:47 | 显示全部楼层
過幾天再寫其他 ...

该用户从未签到

发表于 2015-3-24 15:47 | 显示全部楼层
学些你使用国外大神的PinChangeInterrupt 的库
期待中,谢谢

该用户从未签到

 楼主| 发表于 2015-3-24 22:07 | 显示全部楼层
tsaiwn 发表于 2015-3-23 04:47
過幾天再寫其他 ...

已經更新加入使用 P-C-I Library 的簡單範例,

關於Chris J. Kiick和Michael Schwager寫的 P-C-I Library:
   https://github.com/GreyGnome/PinChangeInt
Alse see:
   http://playground.arduino.cc/Main/PinChangeInt
   http://playground.arduino.cc/Main/PinChangeIntExample
   http://playground.arduino.cc/Code/ReadReceiver

已經順便把 ver. 1.0, ver 1.72, ver 2.402 夾檔案在原貼文內.

该用户从未签到

发表于 2015-3-25 11:22 | 显示全部楼层
不错,技术贴,收藏再看。楼主加油

该用户从未签到

发表于 2015-5-5 17:24 | 显示全部楼层
tsaiwn 大的帖子總是值得細細品嚐學習

该用户从未签到

发表于 2015-10-23 10:50 | 显示全部楼层
学习了,看了几天     大神 我这里想加一个按键设置时间  可以指点一下吗?
http://www.arduino.cn/thread-17726-1-1.html
谢谢了!

该用户从未签到

发表于 2015-10-23 10:52 | 显示全部楼层
不知道怎么跳出它的中断   我加了按键 必须按住它才停止  一松开 时间就按照后台的时间继续走了

该用户从未签到

发表于 2016-3-9 16:42 | 显示全部楼层
请问串口中断怎么初始化?
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

热门推荐

原价299元【语音开发板套件】限时免费领!
原价299元【语音开发板套
教你让OLED动起来!多重字符串版!
教你让OLED动起来!多重字
大家都知道:arduino单片机是单线程的 而上次教程中的多段字符串的运行速度必须一致
TTGO T8 1.7.1使用TFT_eSPI库驱动2.4寸ILI9341屏幕显示板载SD内图片
TTGO T8 1.7.1使用TFT_eSP
TTGO T8 1.7.1采用Espressif官方ESP32-WROVER模块制作,4MB闪存和8MB PSRAM,支持TF
TTGO TFT屏幕Arduino使用的小结
TTGO TFT屏幕Arduino使用
TTGO TFT屏幕是一款ESP32和1.44寸LCD屏幕组合的产品,屏幕由ST7789驱动。ESP32自带520
分享我的第一个点灯程序——家庭控制中心
分享我的第一个点灯程序—
2020年,在B站上初识ESP8266,被ESP8266的低门槛、高性价比深深吸引,2020年6月20日,
Copyright   ©2015-2016  Arduino中文社区  Powered by©Discuz!   
快速回复 返回顶部 返回列表