找回密码
 注册
关于网站域名变更的通知
查看: 382|回复: 1
打印 上一主题 下一主题

关于手机音频通信实际开发经验分享(2012年旧贴备份)

[复制链接]

该用户从未签到

跳转到指定楼层
1#
发表于 2021-6-9 18:00 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式

EDA365欢迎您登录!

您需要 登录 才可以下载或查看,没有帐号?注册

x
本帖最后由 seewolf 于 2021-6-9 18:11 编辑
, `& N* ]$ d% w9 s  ?" m7 ]# N
5 L  o& b+ _! B# n自12年毕业至今工作将近一年,也积累了一些经验,接下来会一一分享出来,算是对阿莫的感恩吧!第一篇是关于手机音频通信方面的,12年上半年从事过几个月的手机音频通信的开发(我主要负责设备一端的程序和电路,手机软件部分不负责),积累了一点经验,在这里献丑了。; X) ~' O* Z6 @- S; e% b! h- \
一、手机音频通信的特点5 q* [& Y% R9 n7 O! Y# w
1、通用性强:在智能手机普及的今天,手机的对外通信接口多种多样,而其中以3.5mm的音频接口通用新最强,基本所有的手机、平板电脑都会有这个接口,所以在一些要求通用性的设备上,音频接口登上了舞台。
* s: I% w4 H1 A  n* ]2、速率低:由于手机音频部分的采样频率一般为44.1KHZ(部分国产山寨为8KHZ),这极大的限制了音频通讯的速率。我们都知道44.1KHZ的采样频率,那么最高的信号频率只能为20KHZ左右,而信号周期也不可能只有2个采样点,通常要到10个以上,这样层层下来通讯速率可想而知。% o2 Y- F3 i, M- g3 [
3、小信号:音频通信的信号都是毫伏级的,各个手机厂商略有不同,但通常最大不超过200mv,通常我们通信使用的信号强度也就100mv左右,这导致信号比较容易受干扰,且在开发阶段对工具有着种种限制。
3 p8 J" E1 s3 f- e% n4 c( K二、手机音频通信分类/ g: l' M  y5 m+ n
1、无线方式:) a. ~/ j, g9 W
a) 无线方式大家可能不太熟悉,容我慢慢道来。我们都知道人耳能听到的声音频率为20HZ~20KHZ,而手机通信的信号频率最高也就20KHZ,所以无线通信方式是可行的。因为虽然人耳的极限听力能到20KHZ,但普通人一般在19KHZ以上时基本就听不到了,所以如果信号的强度比较弱,且控制在19KHZ到20KHZ之间,那么我们就可以将之当做是“超声波”来看待了。  I$ U: ]$ ^2 y  x9 [( c+ A4 F
b) 其实在此提到手机音频通信的无线方式,算是给大家一种产品开发思路吧。它的通讯半径在10M左右,前景还是很广阔的,大家有兴趣的可以试试。(其实已经有这方面的产品了)
* I$ M6 H( R, L9 t1 A3 b8 b4 a0 x2、有线方式:
( z- y8 X  l% R3 z( x8 }a) 有线方式分为单向(设备→手机)和双向两种,单向的限制少,开发难度也小一些,但实际应用时会受限制。而双向通信限制多,开发难度也大一些,但实际应用时更方便些。
; o8 t2 a; E8 M( g6 }) ^3 e" Yb) 设备→手机:曼彻斯特编码;FSK;DTMF;自定义正弦波* \! y7 g0 |/ ^; i" |. N
c)  手机→设备:由于手机输出的音频信号很小,无法直接使用,要么用运放发大到合适的范围,要么用电压比较器转换成TTL方波。
! X  \6 p" `! x三、手机音频通信硬件通信方式分类:手机音频通信的硬件通信方式大体可分为方波和正弦波两种。
; r& W$ g7 L2 V% }1、方波:方波通常使用的是曼彻斯特编码方式(什么是曼彻斯特编码自己去查),它的好处是可以用单片机直接输出方波,经过衰减后即可使用,方便简单。缺点是兼容性不好,因为手机音频部分有这样一个特性,它只识别变化的电平信号,当麦克输入的信号长时间保持在某一非零电平时,手机会将其视为零,而强行拉回零电位。这就是采用方波通讯方式的兼容性不好的最大原因了,并且方波也容易受干扰。* F/ n9 ^! L. n
2、正弦波:正弦波不会出现上面所说的方波的问题,故正弦波的兼容性和稳定性更好一些。通常采用方案有FSK、DTMF、信号发生器、或方波转正弦波等。(后面会对以上方案逐一分析). V% S3 C4 [( f# m2 i
3、通信信道分析  V5 N+ B0 Z* [7 W0 `
a) 我们知道音频接口有4根线,MIC、地、左、右声道。设备→手机用MIC,手机→设备用地、左、右声道中的任意一个。这里说一下,实际产品中,有一些厂家会更换地线,即将原本左、有声道中的一根改为地线来用,其实道理是一样的。因为音频通信的信号时交流信号,而地其实也是悬浮地,即便地线换了,最终的波形还是一样的,因为最终手机解析信号时需要的是频率和幅值。这样还剩下一个声道,通常被用来帮助设备进行上电识别,因为音频通信的设备通常都是电池供电的。6 N' Y+ q' R" H$ Y
b) 另外还要在MIC和地之间并联一个4.99K的电阻,因为手机是通过检测MIC和地之间的阻抗是否为4.99K(也有其他阻值的)来判断是否有设备(耳机)插入,这一点要谨记。
8 @5 }& H" H# r( C9 i/ \四、各个通信方案对比分析
4 L1 m3 j4 h1 @, Y( Y1、设备→手机:
9 ?3 m5 u! L! {% _0 Ra) 曼彻斯特编码:在诸多通信方式中,曼彻斯特编码是最灵活简便的一种方法,编码信号可由单片机直接产生,经衰减电路衰减后便可直接使用。注意事项:曼彻斯特编码信号的生成有两种方式,一种是用PWM生成,一种是用定时器中断翻转IO,我个人比较倾向于定时器中断方式。因为我们知道曼彻斯特编码中有宽沿河窄沿之分,且宽沿和窄沿可能会灵活变化,而用PWM方式不容易精确控制宽沿、窄沿输出的变化,而定时器中断方式则非常灵活且容易控制。(后面会送上我自己写的曼彻斯特编码、解码函数)
4 i$ x& E- R/ Fb) FSK、DTMF方式:FSK和DTMF两种方式大同小异,使用时通常都是用集成的芯片来生成的,而这些芯片通常都是遵守固定的通信协议的的要求(FSK为Bell202或V.23协议,DTMF记不清名字了)。这两种通信方式的优点是采用正弦波通信、稳定性好且使用简便。但由于固定通信协议的限制导致通信速率、比特率也受到限制而缺乏灵活性。在这里跟他家推荐一款英国的通信芯片CMX系列,这个系列的芯片融合的FSK、DTMF的编码、解码,还是很不错的,大家有兴趣可以试试。(相关手册在附件里)
1 C' C' _1 {8 G: o8 R/ Hc) 信号发生器、锁相环方式:这种方式用信号发生器或者锁相环来产生方波或正玄波,由单片机来控制波形的输出,也可以实现音频通信,且十分灵活。但缺点是电路较复杂,且不同频率信号之间衔接不好掌握,用不好反而是麻烦。(相关手册在附件里)
) m, T- C" q* s* F( Jd) 在这里送上一种我个人认为比较好的方案:就是曼彻斯特编码加低通滤波器,由单片机输出曼彻斯特编码,再经由低通滤波器将方波滤成正弦波后输出。既解决了FSK、DTMF灵活性的问题,又解决了曼彻斯特编码方波稳定性、通用性的问题。在低通滤波器方面我个人采用的是“集成低通开关电容滤波器”,它成本虽然高一些,但好处也是明显的,电路简单,使用方便,且占用的空间亦很小。(相关手册在附件里)
7 K+ S; g  d. b2 x- u) ]/ a5 U- f2、手机→设备:
" X8 n: ^  }4 R- T  i: |a) 放大电路方式:将手机输出信号经放大电路放大到合适的幅值,然后有锁相环或者结成FSK、DTMF芯片进行解析。该中方式难度最大,需要非常强的模拟电路功底,我个人水平有限,故采用的另一种方式。
% I+ k' h7 Y2 C' M# B; zb) 电压比较器方式:将手机输出的交流信号经电路强行拉到Vcc/2级别,然后加到电压比较器一端,另一段接比较电压Vcc/2,这样交流信号即被转化为TTL方波信号,此时再进行解析就变得很简单了。
' d$ H/ f' Z4 C" @1 H( w五、研发注意事项(通讯方案分析部分由于过长,放到最后来讲)
  O$ _, {2 s# z1 _1、一个好手机录音软件是必须的,最好能在手机上直接看到波形的。
9 x) |0 D8 Z* L$ J2、建议用笔记本电脑进行开发,而非台式机。因为音频信号很小,容易受干扰,而台式机干扰较大,笔记本还有一个好处是必要时可将外接电源拔掉,用电池供电。" W2 s3 @( S$ \$ D, I' _; R' O
3、一个好录音笔必不可少,有时需要得到纯净的音频信号,方便更加准确的分析。
( k$ ^8 _- H5 x& K4、做一个转接板,一边接音频母座,一边接音频公头,将MIC、地、左、右声道4跟线用排阵引出,方便录音。
" ~+ I& Q& A) `- c; J5 ]5、做一个信号衰减电路,可将设备电路产生的信号衰减至音频接口能承受的范围内。前期调试时,我们可以用该电路将信号录进电脑进行信号分析。(推荐一个电脑音频信号分析软件:Goldwave)) o. ?8 u" `) u# Y
6、录音用的音频线切记不要太长,不然会给你带来不少麻烦。最好自己做,用音频裸头、杜邦线、排阵即可制作,方便好用。' K$ t# p% G8 s: i# M) X9 q
9 m2 ?7 J% N+ Y$ R/ b, I
曼彻斯特编码的编码解码函数如下:$ ?0 ^# T4 x0 ^; K0 s( ?
  1. /**********************************************************************
    ) k7 ^; C- z" M# e  n" c0 j) w  n
  2. 注释:编码函数都是采用定时器中断的形式,以曼彻斯特编码的窄沿作为定时器周期。9 \3 O+ ^$ Z# q" t6 o# X
  3. 发送的数据包括1个起始位、8个数据位、1个奇偶校验位、3个停止位。9 k" A' I; l, Y9 i9 o1 N4 r$ y* M
  4. ***********************************************************************/4 U7 a% x4 X% p3 [
  5. static void VIC_VECT_Fucton_00(void)//发送编码数据中断函数1 w: R. ~+ }8 P" R: k4 P1 g4 r
  6. {* E: l  {" x" U8 z/ ^7 c8 f0 V3 @
  7.         TIMER0IS =0x0;: e$ k# w. b5 I" z0 f
  8.         if((send_time%2==0) && (send_start==1))
    9 _1 ]8 T- t& I0 S, `
  9.         {0 D& T5 B* y7 Z) N+ s5 y
  10.                 switch(FSK_txState)
    2 H3 ]) p" ^/ ?" a
  11.         {
    ( m3 e1 X% p8 |" l2 l: m
  12.           case STARTBIT:2 p+ W, }# ]. g( e2 k4 [
  13.                 if((GPIODATA&0x00000002)==0x00000000)//如果检测到数据发送管脚为零
    , K, w: C, t! _; ^# V
  14.                         send_time++;% j4 @; p, b9 S, K5 D2 v9 f
  15.                         else" K& ~2 @! H+ N- `
  16.                         {- i. j! a" T, b- B& r
  17.                                 currentSym=0;$ l8 P. a+ j/ W5 ]1 L, [1 L& j+ S
  18.                                 FSK_txState = BYTE;  x8 f2 j' K* `) V4 h' [1 _! B/ w+ ?
  19.                         }! }% [2 a* K3 D& d; H. g4 H) A% X
  20.                         break;
    ; P' E  i! |" s4 G5 S! E
  21.           case BYTE:
    - {5 ?' q- L2 ?& O/ s! b
  22.             if(txBit < 8)
    ' k" s) m5 H  p/ W) x" X
  23.             {
    9 X" d' {. u, r: @4 v1 ?( Y
  24.                     currentSym = (send_byte >> txBit) & 0x01;
    . t: e7 N  z+ p% l6 p
  25.                 txBit++;
    6 v1 y) |/ d6 _) l, X
  26.                 txParity += currentSym;                  //奇偶校验位, Y% I% l( a0 t6 t. [' p7 R
  27.             }
    # n4 U3 b* }/ Z# U  H7 P/ \
  28.                         else if (txBit == 8)7 F1 p6 J% W1 O+ v- o( V
  29.             {+ L, }) C/ p2 I/ p, T, a" i
  30.                     currentSym = txParity & 0x01; //发送奇偶校验位
    + e/ B0 x, Y5 m) l4 L. [# Y
  31.                 txBit++;# a, y4 N9 i" L! x
  32.             }
    : M) g: P7 X! v- X9 _3 Z& Q
  33.                         else if(txBit>8 && txBit<12)8 ^/ C& k, Z; Y4 [* ]3 I& X
  34.             {
    % i4 T' O+ H8 ?* F6 \
  35.                     // next bit is the stop bit2 q5 U8 X$ c- Z; @; I, o9 ~
  36.                 currentSym = 1;                                  //发送停止位# R2 B7 A+ W' Z% J4 m; ]4 u: H: t! s
  37.                                 txBit++;
    3 y- e# n/ u9 v8 {
  38.             }. C$ ?4 K+ T/ @, d  P
  39.                         else if(txBit == 12)
    # @- n6 q3 g% O) M- d3 D
  40.                         FSK_txState = STOPBIT;          z- L0 R  P8 ^( i$ J, N& z" s  r3 X
  41.             break;
    " g( J: m: p# `! p1 a+ [
  42.           case STOPBIT :
    9 P# s6 ]$ W' ~2 B" r0 c0 F
  43.             txBit=0;1 P, K! a( K" t  h: x+ u
  44.                         FSK_txState=IDLE;$ `' P+ @- Y# `
  45.                         send_start=0;. g- J; _) \" n5 B" V
  46.                         txParity=0;8 e# L$ G+ K; t' T" y# |2 q
  47.                         send_byte=0;
    * X* z( \, @3 Q8 s! G; t5 X
  48.                         break;
      k- I+ {# }  r! }- x9 w
  49.                }
    & o/ [# H, M3 l6 L' P. u
  50.                 if(lastSym!=currentSym)6 X  u4 Y& L! m; m
  51.                 {# W7 y$ t# p  M& u' T" h
  52.                         timer1_num++;( M* {8 B0 i7 `: X% [
  53.                         lastSym=currentSym;+ J% b$ C! [0 N$ p) i, f
  54.                 }
    6 @+ ^; W' Z# i! o
  55.         }, I( k& E8 o1 B+ m4 r
  56.         if(timer1_num%2==0)
    : V' Y- S* h; R; S
  57.         GPIODATA&=0xFFFFFFFD;//输出管脚复位3 A5 _1 `3 b; q% f
  58.         else
    0 D4 ^7 l+ C' \+ ]
  59.         GPIODATA|=0x00000002;//输出管脚置位
    . w, B" F# G0 k0 ]$ I

  60. / j9 Z6 X! X9 e2 \! z
  61.         timer1_num++;//用来控制IO口的电平翻转
    7 o+ l2 U3 q9 C! u
  62.         send_time++;//用来控制发送的字节的每一位* n# l) l5 o! u2 }8 \
  63.         Delay++;//Delay就是延时函数
    2 @* c+ [9 l3 t5 f( d; l
  64. }
    # X0 s- D$ q/ y8 T* m  u, G
  65. /**********************************************************************
    7 d6 `- i% O. J; m- N  Y( }
  66. 注释:解码函数采用外部IO中断形式(上升沿或下降沿中断,即电平电平跳变中断),
    , z1 w+ l8 x$ E/ W8 R& H& `
  67. 用一个定时器作为时钟,每次产生中断时便从定时器见时间值取出,并和上一次的0 [) K; C3 W( ]  I: h- `
  68. 记录做差求出时间间隔,以此来判断当前为宽沿还是窄沿。) I' B. z& t, p( _" O- |
  69. ***********************************************************************/
    " M% J4 I5 K0 f% y0 `3 F( {
  70. static void VIC_VECT_Fucton_04(void)//接受解码数据中断函数
    / v, d# ~) w! _, V$ c
  71. {& L4 V* ^' D/ Q" C! F: B8 V, g( @) Q
  72.         GPIOIC|=0x00000001;//清楚上一次中断内容
    " M6 E% M( _$ D% }& w
  73.         RX_time=TIMER1VALUE;- `, L0 V- L, N  X
  74.         if(RX_lasttime>=RX_time)3 K$ u; c$ `$ a3 Z) U! z
  75.         RX_diff=RX_lasttime-RX_time;                  //lasttime初始值为0- b) i& C: d. Q7 _  ^% N, y
  76.         else
    ' c  n5 A! y# B) M* e  B
  77.         RX_diff=65535-RX_time+RX_lasttime;6 W; a' K! U4 F: y4 t' W
  78.         RX_lasttime=RX_time;        5 L9 Q3 j( f4 d6 N/ E& h
  79.     switch(RX_state)                  //启动代码时state已经被配置为STARTBIT
    2 \$ R1 y1 x& ^$ ?3 {( Y" u" c
  80.     {6 c. D2 @$ W, F) r
  81.           case STARTBIT_FALL:
    9 G8 s$ |: z  {, d# a
  82.             if ((SHORTINTERVAL<RX_diff) && (RX_diff<LONGINTERVAL))/ M" V* p; H8 a' c) ^! ]
  83.         {
    , u; ?* L9 J- R: S
  84.                 if(RX_ones<5)           //ones初始值为0' e* b/ k  E- Z, s2 f4 G
  85.             {
    3 ^8 ^. k6 s0 c$ ]
  86.                     RX_ones = 0;# f0 @+ Z  j0 ~7 c& L
  87.             } 9 E7 K( i8 S, E
  88.                         else $ N* s% M6 o7 H, l' d3 u  g7 n
  89.                         {
    4 V; z* m9 w# Q! d1 a" s% i
  90.                                 RX_state = DECODE;        //将状态配置为解码/ ?* g! Z0 X7 b- R; N- K
  91.             }
    # Q  A, c0 y/ q
  92.         }
    9 g8 f' P/ R! S9 v9 @' ~, |: \+ |1 H
  93.         else if(RX_diff < SHORTINTERVAL)8 D' Y: _5 v' b8 A8 P# z( s/ v
  94.         RX_ones++;
    . |& q/ R8 C% r' Z" |
  95.                 else4 ~9 H7 G' v7 m( ]% B; w
  96.                 RX_ones=0;6 }" z( ^+ `1 ]# o, F  Y2 A% i. T
  97.         break;  E; e- N9 C1 H  G1 ~# U6 R! P
  98.       case DECODE:/ X: a! b5 x/ {
  99.               /**************通过间隔长短来判定数据**************/
    ; |2 @! C' |9 X, n7 b) S
  100.                 if ((SHORTINTERVAL<RX_diff) && (RX_diff<LONGINTERVAL))// 若间距在范围内则当前数据位值和前一个相反/ f& M2 S7 _) s6 \0 c5 M2 |, x
  101.         {                                                5 M7 u- K% d3 G6 k
  102.                         currentbit=(currentbit+1)&0x01;4 N, M0 s8 k$ C. [+ w6 ?" f( R: k
  103.                         RX_times+=2;
    , F) ]! [- A& L( F
  104.         }
    2 i$ q% y. A2 {! n: T- `8 N0 y. `7 i
  105.         else if( RX_diff < SHORTINTERVAL)                                         1 X6 N+ \/ E. X7 [& c0 u/ Z
  106.         {, v, u0 |6 E5 C$ [  d
  107.                         currentbit=currentbit;
    # V1 J) d  A- O' Q% g
  108.                         RX_times++;8 t* N' ~$ J7 q* V' |4 R
  109.                 }
    ! G' e; [* J4 x- T* U% O& ~
  110.         else
    1 B4 L) [0 Q: ^  d
  111.                 RX_state = DATAINIT;                           & J* s' o" z, U
  112. 5 f6 U8 W; f+ z6 X3 A/ `8 j; c
  113.                 /****************接受数据位,从低位接起****************/) F, B* M2 y, g/ r, F
  114.                 if(RX_times%2==0)
    : v. z/ k4 p" i# D$ [3 P0 _, y: J+ R  ?
  115.                 {
    4 u: i6 H- S+ Z0 x
  116.                         if(RX_bitcounter<8)
    0 M% G& a( h1 ?' ^: r
  117.                         {7 y4 }$ ~1 i# s' ]
  118.                                 if (currentbit==1)1 C" e8 o/ `( h* T& k% d
  119.                             {/ `. H& \; n- S4 ]' \) k8 ^
  120.                                       uartByteRx = (uartByteRx >> 1) + (1<<7);! u' r$ V/ {  R4 f
  121.                                         rxParity++;                                                //奇偶校验位
    5 ^( z! r7 {9 y3 J9 s
  122.                                         RX_bitcounter++;                                //接受数据位数1 t- @2 i# F9 t* E# E# F
  123.                             }
    ( Z, S1 F" f1 o- _/ S' i1 m8 \% _
  124.                             else
    . p; W9 r! i/ w3 k, s6 Y  V
  125.                             {
    * D+ F2 o# W! b9 C: O+ Z
  126.                                         uartByteRx = (uartByteRx >> 1);
    + r- A/ q$ `# H4 C. t
  127.                                         RX_bitcounter++;
    8 S2 t0 \+ Z4 I7 l" A& _
  128.                             }
    " w7 q1 C" j) b- V9 `: L
  129.                         }
    $ S: O3 _' `2 P
  130.                         else
    0 A# d7 E- ~% e$ R6 |% v0 s
  131.                         {% b+ B# U. {- A0 z
  132.                                 rxParity&=0x01;                                                 //进行奇偶校验
    , d( {' v- i, o  t/ ^  Q8 r% ?" r
  133.                                 if(rxParity==currentbit)
    # L' @& [; l- J( `) j( ]
  134.                                 {# {$ D6 v( b2 W, z! y5 f
  135.                                         RX_bitcounter++;
    : G& ]9 f0 L* E+ g, a1 O$ I; {
  136.                                         RX_finish=1;' C3 H4 t2 O; N8 O4 R" E: W
  137.                                         RX_state=DATAINIT;
    , @) v- ~8 f/ S3 x, d
  138.                                 }
    8 ]1 {$ ]2 v# s6 I! X
  139.                                 else( c* \6 m2 \6 @' H$ j
  140.                                 RX_state=DATAINIT;                                         //若奇偶校验错误则,重新检测
    ) C; _: Z8 y1 i9 u
  141.                         }$ Q3 l) Q4 T# \: N$ W  s' N0 K2 G, Y
  142.                 }' {: l" O4 P  Y( A+ R
  143.                 break;: e  p; v, w! O! H- V  p2 i2 F
  144.       case DATAINIT :                                                                 //初始化参数状态3 B; s# H+ N& J3 M% ]9 a* q% ?
  145.                 RX_bitcounter=0;$ G7 m6 S( {* F8 E
  146.                 RX_ones=0;# {  ^( E/ p+ `
  147.                 rxParity=0;6 ^4 O4 t: ~; U
  148.                 currentbit=0;
    * X  F9 g/ k7 W0 v" \
  149.                 RX_state=STARTBIT_FALL;' W$ G6 S2 g( d9 A/ J* ~
  150.                 RX_times=0;2 Y; Y' ]! w! l! B
  151.                 break;6 r- v) O3 l+ `# y! E  K
  152.       default:$ C8 s  [1 ^$ n$ m. `
  153.         break;
    8 c$ r) \# `1 {! [
  154.     }; e6 |" i  L& C4 O4 w' o1 O$ Z% V2 r
  155. }
复制代码
/ Q0 _: ~& z7 s2 a2 Q& r. ~

% B/ F- E- J0 ^9 i" x+ R9 Y

FSK、DTMF通信类.zip

4.56 MB, 下载次数: 0, 下载积分: 威望 -5

方波信号发生器.zip

1.05 MB, 下载次数: 0, 下载积分: 威望 -5

开关电容滤波器.zip

1.15 MB, 下载次数: 0, 下载积分: 威望 -5

耦合电感.zip

2.24 MB, 下载次数: 0, 下载积分: 威望 -5

锁相环及信号发生.zip

4.05 MB, 下载次数: 0, 下载积分: 威望 -5

  • TA的每日心情
    开心
    2022-12-5 15:37
  • 签到天数: 2 天

    [LV.1]初来乍到

    2#
    发表于 2021-6-10 08:56 | 只看该作者
    这个好,都是经验之谈
    您需要登录后才可以回帖 登录 | 注册

    本版积分规则

    关闭

    推荐内容上一条 /1 下一条

    EDA365公众号

    关于我们|手机版|EDA365电子论坛网 ( 粤ICP备18020198号-1 )

    GMT+8, 2025-10-30 04:10 , Processed in 0.171875 second(s), 26 queries , Gzip On.

    深圳市墨知创新科技有限公司

    地址:深圳市南山区科技生态园2栋A座805 电话:19926409050

    快速回复 返回顶部 返回列表