资讯详情

Arduino——中断函数,定时中断的实现

用生活中一个简单的例子来解释中断。当你在家看书时,电话铃突然响了。你停止阅读,接电话,和打电话的人交谈。电话结束后,回来继续从刚才停下来的地方读你的书。这是生活中的中断现象,即正常的工作过程被外部事件打断。程序中的中断是指在主程序执行过程中被中断,执行中断服务程序,然后继续执行主程序。

Arduino 中断可分为外部中断和定时中断两类。 外部中断: 一般指外设发出的中断请求,即键盘中断、打印机中断等外部中断源。外部中断需要外部中断源发出中断请求。外部中断的详细用法见《Arduino 外部中断的使用。 定期中断:主程序在运行过程中一段时间内中断服务程序,不需要触发中断源的中断请求,而是自动执行。

根据实际情况,我们可以确定使用什么样的中断。 中断函数: 首先介绍关中断和开中断Interrupt()和noInterrupt()函数,用法如下。

{

代码可以中断

Interrupt()

代码不能中断

noInterrupt()

代码可以中断

}

定时中断

Arduino我们已经为我们写了定期中断的库函数,我们可以直接使用,这对于对底层知之甚少的学生来说是个好消息。常用的库有FlexiTimer2.h和MsTimer2.h,这两个库的用法相似。下面详细介绍几个常用函数。你可以很容易地从网上下载这两个库。 1.void set(unsigned long ms, void (*f)()) 该函数设置定时间隔和调用的中断服务程序。ms表示固定时间的间隔长度,单位为ms,void(*f)()表示被调用中断服务程序,只写函数名称。

2.void start() 开启定时中断

3.void stop() 定期关闭中断

注:以上三个函数都在MsTimer2.在使用过程中应添加作用域,如:MsTimer2::start();可以通过下面的例子详细了解定期中断。

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

///定时器库 头文件

#include <MsTimer2.h>

///中断处理函数,改变灯的状态

void flash()

{

static boolean output = HIGH;

digitalWrite(13, output);

output = !output;

}

void setup()

{

pinMode(13, OUTPUT);

// 中断设置函数,每 500ms 中断

MsTimer2::set(500, flash);

//开始计时

MsTimer2::start();

}

void loop(){

}


文章目录

  • 3. 使用 MsTimer2 库定期做多件事(教程)(定时器)timer2的使用)
    • 3.1 相关资料
    • 3.2 MsTimer2 库简单易用,
      • 3.2.1 库地址:
      • 3.2.2 MsTimer2 库函数介绍
      • 3.2.3 程序范例
        • 程序说明
    • 3.3 MsTimer2库注意事项
    • 3.4 疑问解答
      • 问答1
      • 问答2
      • 问答3
      • 问答4
      • 问答5
      • 问答6
      • 问答7
  • 6. 自己控制 timer2 定时器定时做多件事(教程, 设定timer2 定时器)

ARDUINO TIMER AND INTERRUPT TUTORIAL:https://oscarliang.com/arduino-timer-and-interrupt-tutorial/

3. 使用 MsTimer2 库定时做多件事(教程)(定时器timer2的使用)

转载:使用 MsTimer2 库定期做多件事(教程)(定时器)timer2的使用) https://www.arduino.cn/thread-12435-1-1.html (出处: Arduino中文社区)

3.1 相关资料

  1. 可以自己用 millis( ) 或 micros( ) 检查时间决定是否做事: http://arduino.cc/en/Reference/Millis http://arduino.cc/en/Reference/Micros

  2. 可以看看我写的这篇"不使用 Timer 图书馆应定期做一件事或两三件事(教程)": http://www.arduino.cn/thread-12408-1-2.html

  3. 也可以使用 Timer 库或 SimpleTimer 库或类似的库做设定: http://playground.arduino.cc/Code/Timer http://playground.arduino.cc/Code/SimpleTimer 不过 Timer 库和 SimpleTimer 库也是用的 millis( ), 很容易被 loop( ) 做其他事情"很不准"!

  4. 当然,你可以控制内部定时器 timer0, timer1, timer2 写ISR(), 可参考: http://www.hobbytronics.co.uk/arduino-timer-interrupts http://www.engblaze.com/we-interrupt-this-program-to-bring-you-a-tutorial-on-arduino-interrupts/ http://www.instructables.com/id/Arduino-Timer-Interrupts/step1/Prescalers-and-the-Compare-Match-Register/ http://www.instructables.com/id/Arduino-Timer-Interrupts/step2/Structuring-Timer-Interrupts/

  5. 控制内部定时器 ,比较难,容忍出错! 所以,想要比较精准定时做某件事, 最简单的就是使用硬件中断的 MsTimer2 库 http: //playground.arduino.cc/Main/MsTimer2 (注意这库精准度只有以 milli second 为单位)

3.2 MsTimer2 库简单又好用,

3.2.1 库地址:

https://www.pjrc.com/teensy/td_libs_MsTimer2.html MsTimer2, by Javier Valencia, lets you periodically run a function, by a configurable number of milliseconds.

FlexiTimer2 is version of MsTimer2 by Wim Leers, which makes the interval resolution configurable, rather than being fixed at 1 millisecond steps Javier Valencia的MsTimer2允许您定期运行一个函数,可配置为毫秒数。 FlexiTimer2是在MsTimer2版本基础上修改的,它可配置间隔分辨率,而不是固定在1毫秒级

Download: [Included with the Teensyduino Installer](https: //www.pjrc.com/teensy/td_download.html) Latest MsTimer2 on [Github](https: //github.com/PaulStoffregen/MsTimer2) Latest FlexiTimer2 on [Github](https: //github.com/PaulStoffregen/FlexiTimer2)

3.2.2 MsTimer2 库函数介绍

  • 设定时间与要执行的 function MsTimer2: : set( some_ms, your_function);
  • 启动中断 MsTimer2: : start();
  • 必要时可停止中断(当然随时可以再重新启动) MsTimer2: : stop(); 先来看一个简单范例: (改自原本范例)#

3.2.3 程序范例

#include <MsTimer2.h>
const int INTERVAL = 500;   // 0.5 秒 = 500ms
void ggyy( ) {
   static int gy = 0;
   gy = 1- gy;  // toggle 0,  1
   digitalWrite(13,  gy);  // pin 13 LED
}
void setup( ) {
  pinMode(13,  OUTPUT);
  MsTimer2::set(INTERVAL,  ggyy); // INTERVAL ms 
  MsTimer2::start( );
}
void loop( ) {
  delay(6123);  // 故意
  MsTimer2: : stop( );
  delay(3388);
  MsTimer2: : start( );
}

程序说明

  1. 这范例让 pin 13 的 LED 灯闪烁大约6秒, 然后停大约 3.4秒, 之后又闪烁大约6秒, 然后停大约 3.4秒, … 亮灭间隔是 0.5 秒(500 ms) !
  2. 你会发现: 用 MsTimer2 只能设定一件要定时做的事 ! 查看 MsTimer2 库的 source code 你会发现,重复使用 MsTimer2: : set( ) 只有最后一次有效,因为每次使用 MsTimer2: : set( ) 会盖掉前一次的设定 ! !
  3. 那如果我有两件事想要定时做呢? 其实也很简单: 就是把原先定时做的事改为负责计时,并判定是否要做其他事即可! 以下是要定时做两件事的范例: (A) 每 250 ms 做一次 myJobOne : 闪烁 LED on pin 13 (B) 每 250 ms 做一次 myJobTwo : 闪烁 LED on pin 8
#include <MsTimer2.h>
const int intA = 250;  //每 250 ms 做一次 myJobOne
const int intB = 250;  // 每 250 ms 做一次 myJobTwo
int led2 = 8;  // pin 8
const int INTERVAL = 1;   // 0.001 秒 = 1ms
void ggyy( ) {
   static unsigned int gy = 0;
   ++gy;
   if( gy % intA == 0) myJobOne( );   // gy 除以 intA 的余数是 0
   if( gy % intB == 0) myJobTwo( );
}
void setup( ) {
  pinMode(13,  OUTPUT);
  pinMode(led2,  OUTPUT);
  MsTimer2::set(INTERVAL,  ggyy); // INTERVAL ms 
  MsTimer2::start( );
}
void loop( ) {
  delay(6123);  // 故意
  MsTimer2::stop( );  
  delay(3388);  
  MsTimer2::start( );
}
void myJobOne( ) {
   static int gy = 0;
   gy = 1- gy;  // toggle 0,  1
   digitalWrite(13,  gy);  // pin 13 LED
}
void myJobTwo( ) {
   static int gy = 1; // 故意与 myJobOne 内gy不同 ! 
   gy = 1- gy;  // toggle 0,  1
   digitalWrite(led2,  gy);  // pin 8 LED
}

3.3 MsTimer2库注意事项

  1. 请注意, 如果你使用了 MsTimer2 库, 则 pin11 和 pin3 就不能再用做 PWM 输出了! 因为该 pin3 和 pin11 的 PWM 是靠 timer2 帮忙的! (tone( ) 也是)
  2. 注意 Servo.h 库与 TimerOne 都是使用内部定时器 timer1 会影响pin 9, pin 10 的 PWM
  3. **tone() function ** 使用 timer2 定时器; 若使用 Tone 库的 Tone 对象(Tone 变量)也是优先使用 timer2 定时器,若用两个 Tone 变量则 timer1 也会被用掉, 用三个 Tone 则连控制 millis( )的 timer0 也会被用掉 ! ! ! 别忘了, timer0 负责帮忙控制 pin 5 和 pin 6 的 PWM 输出 ! ! ! 只要不去改变 timer 的 Prescaler就不会影响其控制的 PWM pin, 但MsTimer2 库与 tone( )都会改变 Prescaler ! !

3.4 疑问解答

问答1

Q: 这范例显然每0.25秒都 “先” 做 myJobOne, 然后再做 myJobTwo, 并没有 “同时” 做啊? A: 不然还能怎样 ? Arduino 的 CPU 只有一个, 又不是多核心(multi core), 怎可能真的"同时"做呢 ? 不过 Arduino 在 16MHz 频率之下每个C语言的指令大约0.7到 3 micro seconds, 如果做了二十句 C语言指令也才大约 0.05 ms (milli second), 进入 ISR( )与离开 ISR( )总计大约要 3 micro seconds, 进入 function 与离开 function 也大约3 micro seconds, 所以, 两个工作前后差不到 0.1 个千分之一秒 ( 0.1 ms), 感觉还是 “同时” 做啦 ! 如果你认为应该优先处理 myJobTwo, 那就把该两句检查 gy 的 if 前后对调即可 !

问答2

Q: 例中 intA 和 intB 可不可以设不一样呢? A: 当然可以啊 ! 你可以把 intB 改为 500 或 1000 自己测试看看 !

问答3

Q: 那如果要设定为定时做三件事呢? ㄟ … 阿这个看完上面例子你应该就会了啊 ! 只要多用个类似 intA 与 intB 的 intC 就可以仿照写出了! 好啦, 为了让初学新手更清楚如何"仿照"写出多一件事要定时做, 以下再改一下上述范例给新手参考, 这次在第三个定时的变量我故意命名 int38 以免有人误以为一定要叫做 intC !

/// 利用 MsTimer2 定时做三件事
#include <MsTimer2.h>
const int intA = 250;  //每 250 ms 做一次 myJobOne
const int intB = 250;  // 每 250 ms 做一次 myJobTwo
int int38 = 1000; // 每 1 秒做一次 myJob666; 没规定说必须用 const : -)
int led2 = 8;  // pin 8
int led3 = 7;  // pin 7
const int INTERVAL = 1;   // 0.001 秒 = 1ms
void ggyy( ) {
   static unsigned int gy = 0;
   ++gy;
   if( gy % intA == 0) myJobOne( );
   if( gy % intB == 0) myJobTwo( );
   if( gy % int38 == 0) myJob666( );
}
void setup( ) {
  pinMode(13,  OUTPUT);
  pinMode(led2,  OUTPUT);  pinMode(led3,  OUTPUT);
  MsTimer2::set(INTERVAL,  ggyy); // INTERVAL ms 
  MsTimer2::start( );
}
void loop( ) {
  // 这次 loop( ) 内故意甚么都不写
}
void myJobOne( ) {
   static int gy = 0;
   gy = 1- gy;  // toggle 0,  1
   digitalWrite(13,  gy);  // pin 13 LED
}
void myJobTwo( ) {
   static int gy = 1; // 故意与 myJobOne 内gy不同 ! 
   gy = 1- gy;  // toggle 0,  1
   digitalWrite(led2,  gy);  // pin 8 LED
}
void myJob666( ) {
   static int gy = 0;
   gy = 1- gy;  // toggle 0,  1
   digitalWrite(led3,  gy);  // pin 7 LED
}

问答4

Q: 可不可以定时做四件事或更多呢? A: 用脚头乌(膝盖)想也知道当然可以, 不过这时你可能想用 Array 来记住 所有的设定时间与对应的 function, 以免 code 太长太丑看了不爽 : -)

问答5

Q: 还有哪些要注意或限制的呢? A:

  • 因为用 MsTimer2 库是在中断时做事, 每件事都要越快做完越好,
  • 还有, 这时中断在被禁止状态(interrupt is disable), 所以, 不要做会用到中断的事, 例如要避免做类似 Serial.print 的事 !
  • 本范例是每 1 ms 执行一次 ggyy( ); 所以, 你所有利用这来定时做的 myJob* 总运行时间要小于 1ms, 不然万一都要"几乎同时做"会来不及 !
  • 最后再提醒一下, 因为 MsTimer2 库会改变内部 timer2 定时器的 Prescaler, 也因为这样, 由 timer2 定时器帮忙做 PWM 的 pin 11 与 pin 3 就不能用 analogWrite 做 PWM 输出了 !

问答6

Q: 可是我需要定时做 Serial.print 怎办? A: 那你应该用个 volatile 变量的 flag, 在 myJob* 内设定该 flag, 然后在 loop( ) 内检查该 flag 以决定是否要使用 Serial.print 打印资料! 注意, 这时在 loop( ) 内也必须尽量不要使用 delay( ) 以免太慢才 检查到 flag 的变化! 我这两个范例故意在 loop( ) 内使用 delay( ) 只是要示范说 可以随时把 MsTimer2 的定时功能关闭,然后可以随时重新启动定时做事!

问答7

Q: 我用 MsTimer2 库定时 1000 做一个时钟, 可是好像时钟不太准确 !

A: 那如果你是设定 1000 想要定时 1000ms 做一次把秒数加 1, 像这: MsTimer2::set( 1000, ggyy); // 1000 ms MsTimer2: : start( ); 然后以为 ggyy( ) 是 每 1 秒做一次, 那就有点错了 ! Why ?? 因为 使用内部 timer2, timer2 的计数器 counter 与 timer0 的都只有 8 bit, 受限于 8-bit 配合 Prescaler 64, 无法做到真的刚好 1ms, 它所谓的 1ms 其实是 1.024ms; 这在大部分的应用不会有问题, 但如果你要拿来做时钟, 就必须学 Arduino 系统在计算 millis( ) 的做法做修正: 在由 timer0 每 1.024 ms 发动的 ISR( ) 内, 它除了每次中断把 millis 加 1, 另外把一个偷用的变量 gg += 3; 就是每次中断 +3; 然后检查是否 >= 125, 如下:

           if( gg >= 125) {
                gg-= 125;
                ++ millis;
           }
 这个动作使得中断每过大约 41次或42次会偷偷调整 millis,  以便弥补每次少算的 0.024ms;
  •  

所以, 如果你要拿 MsTimer2 库来写时钟, 请不要设 1000, 改为设 1 代表 1.024 ms 会产生一次中断, 然后, 自己学 millis( ) 函数的做法:

void ggyy( ) {
      static unsigned int  ms = 0;
      static unsigned char gg = 0;
      ++ms;  gg+=3;
      if(gg >= 125) { gg-=125;  ++ms;}
      if( ms < 1000) return;
      ms -= 1000;
     // 把秒 + 1
     检查秒是否 >= 60 ...
     ...
} // ggyy(

*更多关于 Arduino 内部定时器与中断的说明可以参考: http: //www.uchobby.com/index.php/2007/11/24/arduino-interrupts/ http: //www.engblaze.com/microcontroller-tutorial-avr-and-arduino-timer-interrupts/ http: //gammon.com.au/interrupts http: //www.avrbeginners.net/architecture/timers/timers.html http: //sphinx.mythic-beasts.com/~markt/ATmega-timers.html http: //maxembedded.com/2011/07/avr-timers-ctc-mode/

6. 自己控制 timer2 定时器定时做多件事(教程, 设定timer2 定时器)

自己控制 timer2 定时器定时做多件事(教程, 设定timer2 定时器) https: //www.arduino.cn/thread-12448-1-1.html (出处: Arduino中文社区)

昨天跟大家分享了自己控制 timer1 定时器做多件事: http: //www.arduino.cn/thread-12445-1-1.html 即使你看不太懂程序内的许多句子, 仍然可以稍微修改就能用来"定时"做你要做的事 {: soso_e100: } 但是,如果你用了 Servo.h 库就不能自己控制 timer1 定时器了 {: soso_e115: } 所以,我跟大家再分享如何改为控制 timer2 定时器做多件事。

以下这范例只是把我上次写的控制 timer1 定时器做两件事的程序拿来
  •  

改为控制 timer2 定时器做两件事: 仍然是以不同的频率闪烁 pin 13 LED 与 pin 8 LED; 提醒别忘了 pin 8 的 LED 要串接大约 220 奥姆的电阻, 不过万一没有电阻, 那就多串接一个 LED 应该也可避免 LED 灯烧坏

使用 timer2 与 timer1 定时器做定时原理完全一样, 主要差别是 timer1 是 16bits, 但 timer2 (和 timer0) 只有 8 bits, 意思是 TCNT2, OCR2A, OCR2B 都是 8位, 其内容只能是 0 到 255 (十六进制 0xFF); 所以 myTOP 改用8位的 uint8_t, 也就是 unsigned char, 要注意的是, 既然程序内 myTOP 就是要给 timer2 定时器的计数缓存器(register) OCR2A 使用, 因此 myTOP 的最大值就只能到 255; 这范例中我们使用 24 刚好没问题 设定 myTOP 为 24 的理由在程序内的这段批注(注释): /// For Prescaler == 64 /// 1 秒 / (16 000 000 / 64) = 1/250000 = 0.000004 sec / per cycle /// 0.1 sec / 0.000004 sec -1 = 25000 -1 = 24999 /// 0.0001 sec / 0.000004 sec -1 = 25 -1 = 24 ///需要减去 1 是因为 CTC mode 在比到 TCNT2 == OCR2A 时要重设 TCNT2 并发动中断需要 1 个 cycle (tick) 请注意这里是假设你的 Arduino 是使用 16MHz 的频率。 还有, 虽然同样是设定 Prescaler 为 64,在 timer2 与 timer1 的设定也不太一样。

我们仍用 CTC mode(Clear Timer on Compare), 可是设定 timer2 与设定 timer1 为 CTC mode 方法不太一样, 所以如果你只是复制之前的 timer1 版本来乱改不看手册是不通的 ! 由 datasheet 知道 timer2 的 mode 由 WGM22, WGM21, WGM20 这 3 bit决定, 这三位是 010 表示用 mode 2 的 CTC 且 TOP 在 OCR2A; 所以, 我们要把 WGM21 设定为 1, 但是, 要注意 WGM22 在 TCCR2B, 而 WGM21 与 WGM20 在 TCCR2A; 是 0 的位就不管它, 所以要写 TCCR2A = ( 1 << WGM21 ); 以便把 WGM21 设定为 1; (程序中我故意定义了一个 Macro 宏 bbs(x) 来帮忙做 ( 1 << x ) 这件事) 请参考 ATmega328 datasheet 关于 Timer2/Counter2 (See p.158-162): http: //www.atmel.com/Images/doc8161.pdf

kittenblock中小学创客名师推荐的图形化编程软件

// 控制 LED on pin 13亮灭,  每秒闪烁 2 次:  亮 0.25 秒灭 0.25 秒 ...
// LED on pin 8 每秒闪烁 1 次:  亮 0.5 秒灭 0.5 秒 ...
#define bbs(x)  (1<<x)
const int intA = 2500;   // 2500 * 0.1 ms = 250ms
const int intB = 5000;   // 5000 * 0.1 ms = 500ms = 0.5秒
// Prescaler 用 64
volatile int ggyy = 1;  // 使用这当 Flag 给  ISR 使用 ! 
int ledPin =13;
int led8 = 8;  // pin 8
/// For Prescaler == 64
///  1 秒 / (16 000 000 / 64) = 1/250000 =  0.000004 sec / per cycle
/// 0.1 sec / 0.000004 sec -1 = 25000 -1 = 24999
/// 0.0001 sec / 0.000004 sec -1 = 25 -1 = 24
const uint8_t myTOP = 24;  // 0.0001 sec when Prescaler == 64
/ Interrupt Service Routine for TIMER1 CTC on OCR1A as TOP
/// 注意以下名称是有意义的,  不可乱改 ! 
ISR(TIMER2_COMPA_vect)
{
   static unsigned int aaa = 0;
   static unsigned int bbb = 0;
   ++aaa; bbb++;
   if(aaa == intA){
      aaa=0; myJobOne( );
   }
   if(bbb == intB){
      bbb=0; myJobTwo( );
   }
}
void setup( ) {
  pinMode(ledPin,  OUTPUT);
  pinMode(led8,  OUTPUT); digitalWrite(led8,  1); // 故意
  digitalWrite(ledPin,  LOW); // turn Off the LED
  setMyTimer2( );
}
void loop() {
  //... 做其他事
  // if( ggyy == 1) ...
}
void myJobOne( ) {
  digitalWrite(ledPin,  ggyy);  // ggyy 是 0 或 1
  ggyy = 1 - ggyy; //  给下次进入 用
}
void myJobTwo( ) {
  digitalWrite(led8,  !  digitalRead(led8));  // Toggle led8
}

void setMyTimer2( ){
  cli();  // 禁止中断
  TCCR2A = bbs(WGM21);  // CTC mode 2; Clear Timer on Compare,  see p.158-162
  TCCR2B = bbs(CS22);  // Prescaler == 64; see p.162 in datasheet 
  / 注意 WGM22 在 TCCR2B,  但 WGM21 与 WGM20 在 TCCR2A; 
  / mode 由 WGM22,  WGM21,  WGM20 决定 (see datasheet p.158-162)
  OCR2A = myTOP;  // TOP count for CTC,  与 prescaler 有关
  TCNT2=0;  // counter 归零 
  TIMSK2 |= bbs(OCIE2A);  // enable CTC for TIMER2_COMPA_vect
  sei();  // 允许中断
}

/// ATmega328 datasheet http: //www.atmel.com/Images/doc8161.pdf (p.158-162) //

有了上面这精准度 0.1 ms 做中断的范例(使用 timer2 定时器), 即使你使用 Servo.h 库(会用到 timer1 定时器), 你仍然可以"定时"做某些事, 不会因 loop( ) { } 内有 delay( )影响到, 且应该也很容易修改为定时做三件或更多事。 注意这范例也是用两个不同的变数(变量 aaa, bbb)分别计数并检查 是否到了该做 myJobOne( ) 与 myJobTwo( ) 的时机 ! 所以要多设定一件事, 就仿照多弄个变量例如 ccc, 写个新工作的 function, 然后复制检查的 if 区块并稍微改一下即可

Q: 还有哪些要注意的吗 ? A: 提醒 timer2 控制 pin 11 和 pin 3 的 PWM 输出, 所以改变 timer2 的 Prescaler 就不能再对 pin 3 和 pin 11 做 analogWrite( )了, 还有, Arduino 自带的 tone( ) 函数也会改变 timer2 的 Prescaler: http: //arduino.cc/en/reference/tone 当然还要注意有些第三方的库也可能会使用 timer2 定时器, 其他注意事项请看可看我之前写的 “使用 MsTimer2 库” 的分享内容: http: //www.arduino.cn/thread-12435-1-1.html

以及关于 “使用 TimerOne 库” 的分享: http: //www.arduino.cn/thread-12441-1-1.html

更多关于中断(interrupt)的详细说明可以参考: http: //gammon.com.au/interrupts http: //www.uchobby.com/index.php/2007/11/24/arduino-interrupts/ http: //www.engblaze.com/microcontroller-tutorial-avr-and-arduino-timer-interrupts http: //www.avrbeginners.net/architecture/timers/timers.html http: //letsmakerobots.com/node/28278 http: //playground.arduino.cc/Main/MsTimer2

还有以下这三篇也很有用: http: //sphinx.mythic-beasts.com/~markt/ATmega-timers.html http: //maxembedded.com/2011/07/avr-timers-ctc-mode/ http: //arduino.cc/en/Tutorial/SecretsOfArduinoPWM

标签: au3电阻器定时器

锐单商城拥有海量元器件数据手册IC替代型号,打造 电子元器件IC百科大全!

锐单商城 - 一站式电子元器件采购平台