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

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

[复制链接]

该用户从未签到

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

EDA365欢迎您登录!

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

x
本帖最后由 seewolf 于 2021-6-9 18:11 编辑
# z) u4 E# {+ P2 i  g* L# S- o9 k+ T# Z
自12年毕业至今工作将近一年,也积累了一些经验,接下来会一一分享出来,算是对阿莫的感恩吧!第一篇是关于手机音频通信方面的,12年上半年从事过几个月的手机音频通信的开发(我主要负责设备一端的程序和电路,手机软件部分不负责),积累了一点经验,在这里献丑了。
' `6 C" R% L  X& S3 U一、手机音频通信的特点. E8 k4 ?& T9 t! x+ q: `
1、通用性强:在智能手机普及的今天,手机的对外通信接口多种多样,而其中以3.5mm的音频接口通用新最强,基本所有的手机、平板电脑都会有这个接口,所以在一些要求通用性的设备上,音频接口登上了舞台。4 f, I/ X; p* h% L  |; j3 \
2、速率低:由于手机音频部分的采样频率一般为44.1KHZ(部分国产山寨为8KHZ),这极大的限制了音频通讯的速率。我们都知道44.1KHZ的采样频率,那么最高的信号频率只能为20KHZ左右,而信号周期也不可能只有2个采样点,通常要到10个以上,这样层层下来通讯速率可想而知。
- z: K( K  w: [3、小信号:音频通信的信号都是毫伏级的,各个手机厂商略有不同,但通常最大不超过200mv,通常我们通信使用的信号强度也就100mv左右,这导致信号比较容易受干扰,且在开发阶段对工具有着种种限制。% w" _0 Z, Z) y* N; f, {; V
二、手机音频通信分类
# Q8 f: a8 S  S. W! B' ~1、无线方式:
+ T8 t$ k# \  H9 K$ u& ta) 无线方式大家可能不太熟悉,容我慢慢道来。我们都知道人耳能听到的声音频率为20HZ~20KHZ,而手机通信的信号频率最高也就20KHZ,所以无线通信方式是可行的。因为虽然人耳的极限听力能到20KHZ,但普通人一般在19KHZ以上时基本就听不到了,所以如果信号的强度比较弱,且控制在19KHZ到20KHZ之间,那么我们就可以将之当做是“超声波”来看待了。$ a2 s. {# u/ z  [1 H: |6 _
b) 其实在此提到手机音频通信的无线方式,算是给大家一种产品开发思路吧。它的通讯半径在10M左右,前景还是很广阔的,大家有兴趣的可以试试。(其实已经有这方面的产品了)
. y7 {: b2 F% Q0 _" p. g8 L- U5 ?2、有线方式:* j7 ~. s5 r" V+ n- ^
a) 有线方式分为单向(设备→手机)和双向两种,单向的限制少,开发难度也小一些,但实际应用时会受限制。而双向通信限制多,开发难度也大一些,但实际应用时更方便些。
' g- ^# p& j" W3 |9 lb) 设备→手机:曼彻斯特编码;FSK;DTMF;自定义正弦波
% A& {. d1 _* `7 o4 ?( k, Ic)  手机→设备:由于手机输出的音频信号很小,无法直接使用,要么用运放发大到合适的范围,要么用电压比较器转换成TTL方波。
6 Y0 A- t8 y: N* t% H三、手机音频通信硬件通信方式分类:手机音频通信的硬件通信方式大体可分为方波和正弦波两种。1 Q' v9 a" w9 s: i8 |0 `; \( p
1、方波:方波通常使用的是曼彻斯特编码方式(什么是曼彻斯特编码自己去查),它的好处是可以用单片机直接输出方波,经过衰减后即可使用,方便简单。缺点是兼容性不好,因为手机音频部分有这样一个特性,它只识别变化的电平信号,当麦克输入的信号长时间保持在某一非零电平时,手机会将其视为零,而强行拉回零电位。这就是采用方波通讯方式的兼容性不好的最大原因了,并且方波也容易受干扰。
. v, i; a1 V' V; Z0 T6 \2、正弦波:正弦波不会出现上面所说的方波的问题,故正弦波的兼容性和稳定性更好一些。通常采用方案有FSK、DTMF、信号发生器、或方波转正弦波等。(后面会对以上方案逐一分析)' r% m& p1 ~9 p, L
3、通信信道分析
- _- D# k: ?; k, c! ?/ `a) 我们知道音频接口有4根线,MIC、地、左、右声道。设备→手机用MIC,手机→设备用地、左、右声道中的任意一个。这里说一下,实际产品中,有一些厂家会更换地线,即将原本左、有声道中的一根改为地线来用,其实道理是一样的。因为音频通信的信号时交流信号,而地其实也是悬浮地,即便地线换了,最终的波形还是一样的,因为最终手机解析信号时需要的是频率和幅值。这样还剩下一个声道,通常被用来帮助设备进行上电识别,因为音频通信的设备通常都是电池供电的。
4 L0 A0 h- t) J. Db) 另外还要在MIC和地之间并联一个4.99K的电阻,因为手机是通过检测MIC和地之间的阻抗是否为4.99K(也有其他阻值的)来判断是否有设备(耳机)插入,这一点要谨记。
6 p- c, }; k5 R四、各个通信方案对比分析
1 u$ i# b* ^8 ^, H% r( \, O1、设备→手机:5 v" z: i7 E3 v. j8 u5 {
a) 曼彻斯特编码:在诸多通信方式中,曼彻斯特编码是最灵活简便的一种方法,编码信号可由单片机直接产生,经衰减电路衰减后便可直接使用。注意事项:曼彻斯特编码信号的生成有两种方式,一种是用PWM生成,一种是用定时器中断翻转IO,我个人比较倾向于定时器中断方式。因为我们知道曼彻斯特编码中有宽沿河窄沿之分,且宽沿和窄沿可能会灵活变化,而用PWM方式不容易精确控制宽沿、窄沿输出的变化,而定时器中断方式则非常灵活且容易控制。(后面会送上我自己写的曼彻斯特编码、解码函数)
7 W' x$ \+ v6 d8 ~5 Z/ _b) FSK、DTMF方式:FSK和DTMF两种方式大同小异,使用时通常都是用集成的芯片来生成的,而这些芯片通常都是遵守固定的通信协议的的要求(FSK为Bell202或V.23协议,DTMF记不清名字了)。这两种通信方式的优点是采用正弦波通信、稳定性好且使用简便。但由于固定通信协议的限制导致通信速率、比特率也受到限制而缺乏灵活性。在这里跟他家推荐一款英国的通信芯片CMX系列,这个系列的芯片融合的FSK、DTMF的编码、解码,还是很不错的,大家有兴趣可以试试。(相关手册在附件里). B5 m9 k) U/ u) Y6 I
c) 信号发生器、锁相环方式:这种方式用信号发生器或者锁相环来产生方波或正玄波,由单片机来控制波形的输出,也可以实现音频通信,且十分灵活。但缺点是电路较复杂,且不同频率信号之间衔接不好掌握,用不好反而是麻烦。(相关手册在附件里)
' i' g: `  [" d3 n+ F- ud) 在这里送上一种我个人认为比较好的方案:就是曼彻斯特编码加低通滤波器,由单片机输出曼彻斯特编码,再经由低通滤波器将方波滤成正弦波后输出。既解决了FSK、DTMF灵活性的问题,又解决了曼彻斯特编码方波稳定性、通用性的问题。在低通滤波器方面我个人采用的是“集成低通开关电容滤波器”,它成本虽然高一些,但好处也是明显的,电路简单,使用方便,且占用的空间亦很小。(相关手册在附件里)  B2 y3 n) X  v$ b: T
2、手机→设备:
7 k5 o* ~$ _$ C9 A! g7 P/ @( `# Ra) 放大电路方式:将手机输出信号经放大电路放大到合适的幅值,然后有锁相环或者结成FSK、DTMF芯片进行解析。该中方式难度最大,需要非常强的模拟电路功底,我个人水平有限,故采用的另一种方式。
4 y% o7 y1 n1 v3 }b) 电压比较器方式:将手机输出的交流信号经电路强行拉到Vcc/2级别,然后加到电压比较器一端,另一段接比较电压Vcc/2,这样交流信号即被转化为TTL方波信号,此时再进行解析就变得很简单了。) y: m$ F- v, ~  q* v9 H
五、研发注意事项(通讯方案分析部分由于过长,放到最后来讲)
3 o0 H" u( `* a1、一个好手机录音软件是必须的,最好能在手机上直接看到波形的。
% v+ O& W  C5 u3 H+ B# ~4 i2 f8 n6 A2、建议用笔记本电脑进行开发,而非台式机。因为音频信号很小,容易受干扰,而台式机干扰较大,笔记本还有一个好处是必要时可将外接电源拔掉,用电池供电。
2 d3 r$ U2 c& F" J: K& g3、一个好录音笔必不可少,有时需要得到纯净的音频信号,方便更加准确的分析。
# x' O2 U. |0 M" K3 V; V5 f4、做一个转接板,一边接音频母座,一边接音频公头,将MIC、地、左、右声道4跟线用排阵引出,方便录音。) h% m, R, U4 }7 D4 m5 F# o; n. u
5、做一个信号衰减电路,可将设备电路产生的信号衰减至音频接口能承受的范围内。前期调试时,我们可以用该电路将信号录进电脑进行信号分析。(推荐一个电脑音频信号分析软件:Goldwave)7 \9 S( i/ U  j9 G" p
6、录音用的音频线切记不要太长,不然会给你带来不少麻烦。最好自己做,用音频裸头、杜邦线、排阵即可制作,方便好用。( N9 B0 I* j/ C+ t# _# A
, ?$ n, r) I9 M# Q7 Z' e6 i
曼彻斯特编码的编码解码函数如下:
" Z/ \; q$ p, m
  1. /**********************************************************************
    ) |/ k4 b5 w4 U) w' I/ N
  2. 注释:编码函数都是采用定时器中断的形式,以曼彻斯特编码的窄沿作为定时器周期。
    " e9 `% f. ]7 A
  3. 发送的数据包括1个起始位、8个数据位、1个奇偶校验位、3个停止位。
    / z$ |  M% `0 G1 ]# i: F% H% x
  4. ***********************************************************************/
      |7 G* H1 \+ U" `; y5 R, i+ T
  5. static void VIC_VECT_Fucton_00(void)//发送编码数据中断函数
      p2 i8 z5 I$ Y- |8 C% E! B! s# h4 ~
  6. {1 K4 l; e* w4 Z7 |8 m3 n( _
  7.         TIMER0IS =0x0;
    : x1 C8 j# x1 `" c8 {
  8.         if((send_time%2==0) && (send_start==1))0 }* t9 x) V- X4 K* `) C( ~; ~: r
  9.         {
    " H/ t  O# g1 Q6 j- S
  10.                 switch(FSK_txState)
    3 @% B$ n. V! j& ]( g) p& j) I, X  {
  11.         {& G% a( a9 L# G) k
  12.           case STARTBIT:: G% M; w$ y0 m
  13.                 if((GPIODATA&0x00000002)==0x00000000)//如果检测到数据发送管脚为零8 i* z$ f- u' P
  14.                         send_time++;
    ( O! Y3 {; t& d% N# t- O3 w
  15.                         else! f1 G8 T5 |# m. B$ ~
  16.                         {
    1 g* n) U2 d+ ^  y
  17.                                 currentSym=0;. J4 L* Q  L: i& t; n3 v
  18.                                 FSK_txState = BYTE;- z( ~  ~& b' `" l! t4 a
  19.                         }' K; n3 u7 D1 w- `
  20.                         break;* m6 p8 a1 c+ C! R% u
  21.           case BYTE:( L5 H( _- \) i9 R* ?9 X
  22.             if(txBit < 8)7 m6 ]7 k6 b9 k
  23.             {
    . l3 ~% T) Z+ A) p' u
  24.                     currentSym = (send_byte >> txBit) & 0x01;$ i; Y# f9 ~. g+ l$ I& F9 ^( `( ^3 r
  25.                 txBit++;
    / T! n  R, R% j) ]( w
  26.                 txParity += currentSym;                  //奇偶校验位
    - y/ D1 C8 l3 ]- T9 M8 @
  27.             }
    6 G5 S! o9 y' w, E
  28.                         else if (txBit == 8)# J/ l% @4 N9 G3 F3 d+ y6 U
  29.             {
    ) j5 b& X; F8 i: d* w- Q: N
  30.                     currentSym = txParity & 0x01; //发送奇偶校验位  G! C9 z! e8 [9 k7 S5 V: _
  31.                 txBit++;
    # |/ |. q9 E( u" [7 W
  32.             } / P$ @7 M1 E; U
  33.                         else if(txBit>8 && txBit<12)& d9 L/ k6 Z5 Q, C
  34.             {" `1 d* X" k' y# a) }" z* V
  35.                     // next bit is the stop bit
    * d# [$ y! ^/ K$ W
  36.                 currentSym = 1;                                  //发送停止位# c& I# ^6 S$ \
  37.                                 txBit++;1 G% y9 z/ J# X5 [' A; h
  38.             }0 g+ g! o# r8 X9 C" V% t
  39.                         else if(txBit == 12)1 ~# F" _1 n* x& l+ O+ u
  40.                         FSK_txState = STOPBIT;        
    7 ^0 [! z3 s& ~* }
  41.             break;
    3 e( x& q* @0 W" `5 T: M3 Z0 a
  42.           case STOPBIT :4 S) d7 \  v8 ^) v4 k) ]9 X
  43.             txBit=0;
    8 s( q0 q: H, F3 Q4 Z8 V
  44.                         FSK_txState=IDLE;
    / w. F( h/ A3 [! }
  45.                         send_start=0;
    . w0 P  J3 d, F7 i! G: {# c5 B9 Z# q+ _
  46.                         txParity=0;! h; I5 u! Y6 t
  47.                         send_byte=0;
    $ q; _6 k7 w1 y7 ^; q0 A/ ]  v2 O
  48.                         break;
    % `+ i8 n8 b  b
  49.                }
    $ n0 z7 [, L. f- n5 o  L) q! u' F
  50.                 if(lastSym!=currentSym)
    2 K- v3 g2 V/ t7 e( _
  51.                 {
    5 u6 ^0 }: `& [& n) r$ @5 p8 v
  52.                         timer1_num++;! x+ k+ C" B2 m; I
  53.                         lastSym=currentSym;
    ; S% O8 i6 q" Z4 I# Z( }2 @
  54.                 }/ J1 _1 G; L# m! }1 V0 p5 c
  55.         }
    1 n- R# D2 }! F6 s6 I) U( e2 \
  56.         if(timer1_num%2==0)" i4 ~! A4 K+ L3 h$ b8 {
  57.         GPIODATA&=0xFFFFFFFD;//输出管脚复位
    " M, L* y$ ?( P& S) z* n8 D
  58.         else
    ! b& H) N+ m+ n, o+ o
  59.         GPIODATA|=0x00000002;//输出管脚置位
    / i3 S3 |( H+ U9 D

  60. ; h2 J* A. J" [
  61.         timer1_num++;//用来控制IO口的电平翻转
    $ {9 f, ]5 j  M/ A7 j+ i0 y% d1 I# e
  62.         send_time++;//用来控制发送的字节的每一位$ B; x8 ~/ F- @! F* T
  63.         Delay++;//Delay就是延时函数1 Y1 ]0 W7 x2 K3 B4 R3 J) T1 b* n
  64. }, w5 [- p5 f& m' H
  65. /**********************************************************************
    8 g" u# ^& Y& Z) t7 \/ Q* E
  66. 注释:解码函数采用外部IO中断形式(上升沿或下降沿中断,即电平电平跳变中断),
    % P4 O4 d0 d1 ~* U) x
  67. 用一个定时器作为时钟,每次产生中断时便从定时器见时间值取出,并和上一次的
    " S0 _: n6 H6 O9 H% r) d
  68. 记录做差求出时间间隔,以此来判断当前为宽沿还是窄沿。
    6 {4 C( P' V4 r) A4 _
  69. ***********************************************************************/
    / u( t1 s6 @1 @1 a) ~2 @2 f
  70. static void VIC_VECT_Fucton_04(void)//接受解码数据中断函数
    / v6 [# {) _1 F& ~  Y4 Y
  71. {" H  D0 g6 m9 k5 t1 c$ p9 x
  72.         GPIOIC|=0x00000001;//清楚上一次中断内容9 N4 P4 K8 B! J1 J5 ^# a; j- D$ c  W' _
  73.         RX_time=TIMER1VALUE;/ A% Y7 s( T: J0 x% C- K2 J
  74.         if(RX_lasttime>=RX_time)) K+ Q7 I% F4 g+ K' s' O
  75.         RX_diff=RX_lasttime-RX_time;                  //lasttime初始值为07 \9 c. ^" A: u+ d# L
  76.         else& J" k# L' S& Y% Y0 h
  77.         RX_diff=65535-RX_time+RX_lasttime;
    1 g. I! V/ A$ Y2 z
  78.         RX_lasttime=RX_time;        
    3 c  a' L( ?3 L
  79.     switch(RX_state)                  //启动代码时state已经被配置为STARTBIT
    : o: M& C( ~, z$ P  |4 h4 D$ f
  80.     {
    6 t  l0 F3 B" g' |2 h) ~6 R% H3 s
  81.           case STARTBIT_FALL:
    $ N, i, e  J* [. o3 ~* g
  82.             if ((SHORTINTERVAL<RX_diff) && (RX_diff<LONGINTERVAL)): r) S* Y* N7 r. |) |: o
  83.         {/ w8 Y/ E: h2 B( ?' N/ g0 i
  84.                 if(RX_ones<5)           //ones初始值为08 j/ @" f. ?( J% @* u/ h
  85.             {8 H" [0 N0 w+ u, p2 c" t$ u
  86.                     RX_ones = 0;* D+ X# _& D: M0 ~1 y% ~
  87.             } ! ?, G8 @- v0 U/ A
  88.                         else
    ) t- O8 ?) `, S" F4 m- {
  89.                         {. F9 m- d2 h9 ~
  90.                                 RX_state = DECODE;        //将状态配置为解码
    9 L2 u7 f' `0 t3 \! c& g9 H+ m
  91.             }
    ! J1 A, D9 ^. d  {  `1 z
  92.         }5 D( i& `. z: L. U9 s; E9 m4 ^  V
  93.         else if(RX_diff < SHORTINTERVAL)
    ) [$ C8 y3 c  Q  ^. T2 g
  94.         RX_ones++;
    $ w$ ]8 ]% y) C( F
  95.                 else
    - V; k5 Z) C, \/ {0 L4 |! P
  96.                 RX_ones=0;: Z2 ~! s/ l; }) e7 J
  97.         break;- H6 ^0 p2 o, ]
  98.       case DECODE:8 Q& O* K5 N: k
  99.               /**************通过间隔长短来判定数据**************/* P" l2 o9 A% t1 t
  100.                 if ((SHORTINTERVAL<RX_diff) && (RX_diff<LONGINTERVAL))// 若间距在范围内则当前数据位值和前一个相反, r# s* v, @. A9 @
  101.         {                                                $ M' v5 i: \7 z
  102.                         currentbit=(currentbit+1)&0x01;0 f. u/ ^6 v8 C7 w4 ?' M- @
  103.                         RX_times+=2;" ^* o* x$ h+ u
  104.         }, e2 Q% G- o( A: Q5 V% x' N% Q% R
  105.         else if( RX_diff < SHORTINTERVAL)                                         4 _4 Q& N, l7 Z( G
  106.         {
    " r! _5 F8 @% O. u) l- b8 X
  107.                         currentbit=currentbit;
    2 S5 o1 h" j" l9 i  s
  108.                         RX_times++;
    2 X! E& e" J5 b: @; D/ {- O# s0 v5 P
  109.                 }$ ^7 k5 V  z2 W5 q
  110.         else9 d+ e( Q$ A, H( _/ p. O
  111.                 RX_state = DATAINIT;                           ' o0 x; X, R( B1 h; H+ B

  112. ( m' F" ^; p. R9 {
  113.                 /****************接受数据位,从低位接起****************/3 j/ ^, |/ _# y0 e% h
  114.                 if(RX_times%2==0)
    " r4 ~4 z& t) p% ?- _
  115.                 {
    5 p8 s0 K1 ?2 Z' f6 R1 t3 f
  116.                         if(RX_bitcounter<8)% b% i! ~2 S/ l, U' R
  117.                         {
    8 e! X, g( a. }2 r# P) X
  118.                                 if (currentbit==1)2 L3 y, y9 a: f. E/ ]4 h* R& R
  119.                             {
    % {, J( D; y4 K! }& j& L5 h2 @
  120.                                       uartByteRx = (uartByteRx >> 1) + (1<<7);
    " F5 U) L% M1 k
  121.                                         rxParity++;                                                //奇偶校验位* S0 c6 ?5 s) w% ]
  122.                                         RX_bitcounter++;                                //接受数据位数* Y8 f3 y9 q8 X# c6 f" }& n) y
  123.                             }
    : B( w+ |. b  O/ c
  124.                             else2 J, _& w' F' T7 |
  125.                             {
    & d; h8 ~8 S4 y& _  x$ A
  126.                                         uartByteRx = (uartByteRx >> 1);. k2 H/ D4 h' h: q. t6 l7 \
  127.                                         RX_bitcounter++;/ G/ B8 {3 r& n
  128.                             }7 X* ~/ L( i0 q: _- {( h
  129.                         }
    4 {8 m( _8 L9 \3 q
  130.                         else* r/ o: u  O  w8 t% C& _* G
  131.                         {8 F$ ]8 f. x) x6 H8 z2 U8 U
  132.                                 rxParity&=0x01;                                                 //进行奇偶校验3 ^( y% M* i: R: ~
  133.                                 if(rxParity==currentbit)+ {0 r) _0 F3 T
  134.                                 {
    5 T7 ^6 W& _( ~+ t8 O+ ~( n8 w( L3 @
  135.                                         RX_bitcounter++;
    6 g& c8 ^, f) F' |2 T
  136.                                         RX_finish=1;
    ! Z7 C* _/ h! u
  137.                                         RX_state=DATAINIT;
    2 w: s; C, C1 S) [" l; }
  138.                                 }
    0 i+ j+ k/ T, I, g% |! U
  139.                                 else2 p  A/ y1 J: w$ K2 z  [
  140.                                 RX_state=DATAINIT;                                         //若奇偶校验错误则,重新检测
    - O7 |4 q0 `1 F% a" H$ j4 g3 y2 ~
  141.                         }
    + c1 G' B# P' f2 \6 v
  142.                 }
    : e% `7 T% g' V
  143.                 break;
    3 G; v5 v% K' D9 r2 l5 n
  144.       case DATAINIT :                                                                 //初始化参数状态6 J4 B6 R  `$ \! {% u1 M( j) J0 c- Z  ^
  145.                 RX_bitcounter=0;
    # `  j, Q2 B' x' d  W: J
  146.                 RX_ones=0;; o/ X& P" q7 Y# H
  147.                 rxParity=0;% h) r7 j5 M1 @2 `
  148.                 currentbit=0;
    6 E9 {3 `+ x4 l: j7 y: c; U5 w
  149.                 RX_state=STARTBIT_FALL;
    : J" K' [9 Z: m
  150.                 RX_times=0;  U. K9 d. O4 ~6 t6 L; H# V$ E
  151.                 break;. z5 u: M0 B5 D9 o  q
  152.       default:
    . n0 U0 a( l" g1 f
  153.         break;
    ' f+ k- m4 a3 N4 S- \
  154.     }; {$ T! V" o) I* f' d, k
  155. }
复制代码

- j+ ]0 X# D4 S8 O- \& T8 c: {  A3 u% L0 X) f

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-7-31 19:12 , Processed in 0.140625 second(s), 26 queries , Gzip On.

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

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

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