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

基于STM32的简单电子书的实现

[复制链接]

该用户从未签到

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

EDA365欢迎您登录!

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

x
  今天玩了会液晶屏,原来显示汉字都是也取模软件区模后在液晶屏上显示,显示内容改变以后还需要重新做字模,比较麻烦。这两天有时间,参考网友资料,实现了读取汉字的内码从SD卡的GB2312点阵字库读取点阵在液晶屏上显示,字库的生成软件用的是易木雨的点阵字库生成器。能生成很多种语言的字库。做完了读取显示后,我自己又琢磨了一下,简单的实现了从SD卡中读取txt文档然后再液晶屏上显示txt内容。
- w; I8 ?" y7 `4 a* m# D  取模过程注意点阵的宽、高和字体大小的关系,宽、高是我们在液晶屏上要显示的像素大小,字体是汉字大小,如果宽、高一定,字体大小太到的话,字在液晶屏上只能显示一部分,可以在左侧的预览区看出来,如果字体在宽高像素点的范围内则可以在液晶上显示完整的字,如果不能显示完整则可以调整宽高或者字体大小。
  Q- ~' L& J* k7 R6 x  国标字有GB2312和GBK编码,GBK完全兼容GB2312包括内码的兼容,A而且GBK字库增加了很多字。汉字都是用的两个字节表示,第一个字节是区号,第二个字节是在区内的相对偏移位置。通过内码来获取字库内的偏移位置,偏移位置与内码和生成字库的宽高都有关系。我生成的GB2312字库是16*16个像素点显示一个汉字,那在字库内的偏移位置:+ y% ^$ z/ D5 \$ o( }
  offset=32* ( (H-0xa1)*94+(L-0xa1) )
8 M& E' n1 ~5 d2 C3 J2 A+ b  H 表示内码的高字节,L表示内码的低字节。GB2312高字节是0xa1~0xfe表示区号,每个区有94个字节所以*94得到区的相对位置,L表示内码低字节也是从0xa1~0xfe,L-0xa1 得到的是在当前区内的偏移位置。 因为每个汉字有16*16=32个自己组成,所以最后乘以32得到在点阵字库中的偏移位置,从这个位置开始取出32个字节的点阵数据然后打点显示就可以把一个汉字显示出来了。+ \/ m5 @9 _) `( x
  获取点阵的代码如下
' Z% Y) J/ `$ `% M% J5 g8 |8 J9 ?( |4 V! _3 l% e: \& {
  1. FATFS fs1; // 挂载SD卡的分区用2 t3 g$ j, H! Q# i
  2.   u+ N2 d4 o3 u7 O2 B
  3.   FIL f1; // SD卡中字库的文件描述符: C6 _) p. D9 w( C  O

  4. + m7 X/ Z5 D1 D! H
  5.   FIL ftxt; // 要读取的txt文档的文件描述符
    4 z0 x/ K, ?( [2 T9 P1 k# z. \

  6. 9 D; u% o; t$ ]. }0 b, r0 v) w6 V- z
  7.   u8 fnGetChinese(u8 *p,u8 *buff) // 形参是要读取的汉字
    . j7 `- I9 `$ x" B6 ~& s
  8. - @! e; n5 p7 u
  9.   {
    8 S. j$ H( r' h+ N7 h# q3 p

  10. ' G8 G4 W+ ?* _# A% X3 [2 O
  11.   u8 res=0;9 N$ X& I6 ?2 I" |1 @: K

  12. 3 t0 @# G* w# R
  13.   u8 H8,L8;$ ^) g, r  e$ `* d% i- C4 m* l

  14. . m0 u* x: I. E4 O
  15.   UINT num;
    & F( r* m5 [& u6 f" \1 M. V( I& g

  16.   o1 I' f; K1 S/ J
  17.   H8=*p;
    & O; J: u) {2 @( o( o/ [& K# }5 c
  18. 2 {9 m' G' c: c. y; B( G. c
  19.   L8=*(p+1);/ C1 ^1 S9 ~2 X! h0 u7 [3 ]# ^
  20. ' ~* X# ^" G4 I& v  L' C% W" |( K2 |
  21.   f_mount(&fs1,"",1); // 挂载SD卡; a9 v6 V3 k7 U6 r) ^& I) J

  22. + J4 I7 D* @& t, B3 E
  23.   res=f_open(&f1,ReadPath,FA_OPEN_EXIStiNG|FA_READ); // 打开SD卡下的点阵字库$ `0 d" Z# N$ s8 z# h/ D

  24. 8 j3 ?* k: _7 Y3 L
  25.   IF(res!=0) // 判断点阵字库是否打开成功3 N7 ~+ z9 s2 ~, F& I- a+ Z& ?! L
  26. 3 S  O2 u) q: k& f9 h
  27.   {3 T4 ]! C$ X5 m! |

  28.   w: b; a& f  O: p! j6 {# u
  29.   fnShowString(10,120,"open hzk fail",16,RED,WHITE,0);
    5 k1 B$ _( i8 z4 f

  30. $ s$ Y* O! W  j: W- x( m% ~9 P- i
  31.   printf("res=%x",res);
    0 m9 K! ?5 Y. @6 Q, k/ q5 r

  32. & I4 F% p* F( y+ j* l
  33.   return 1;
    ! Q( _3 ~, i: j; y  h/ g( j- N7 Y2 Z+ K

  34. 5 J* k. b) \" u3 E1 j, e  ]
  35.   }
    2 u* s$ e' `+ T7 Q
  36. 8 m7 u7 b- |4 H! \/ G
  37.   else
    ; c; |6 p* s* \& N& M8 C4 B

  38. 7 d/ ?) @- O# b2 d% L" W, E# R6 j
  39.   {! I/ o2 a$ }# H6 V1 f' y, _

  40. 7 a: L1 q% L4 X5 t9 p% S7 N1 w
  41.   fnShowString(10,120,"open ok",16,RED,WHITE,0);/ x. `9 T! }5 p, F* R2 i+ j: X0 A5 B
  42. ! k6 ~- d- P2 @. S) \, B% L4 D. U
  43.   }7 ?8 u, x8 C4 \* j
  44. 8 X' _7 K* v- ^! G# c- O/ {
  45.   f_lseek(&f1,32*((H8-0xa0-1)*94+(L8-0xa0-1))); // 在字库文件中做偏移取出32个字节的点阵数据' T- s, V! c9 l( _% d
  46. 5 p& S/ ^$ O2 I
  47.   res=f_read(&f1,buff,32,&num);
    ; _$ s# m; w% {, g
  48. 4 r- l% c9 `* B0 V
  49.   f_close(&f1); // 读完后关闭点阵字库文件
    8 Y/ B9 d- \7 o! w4 i' }) b

  50. . L, R% V5 n! U+ t4 i7 J
  51.   f_mount(&fs1,"",NULL); // 卸载SD卡" A, h2 F1 Y3 V2 L1 V) m7 s( v

  52. ' G+ _, E7 `2 U0 x8 y! H
  53.   return 0;6 O8 a- A' t1 b( w

  54. % Z' j5 R5 {3 w0 J2 x: J# X
  55.   }
复制代码
3 C# C# ?- X! ]9 ~, M) y1 X* ^! w
  这个是得到汉字点阵的实现过程,得到点阵数据后就可以在液晶上打点实现汉字的显示,具体的底层驱动不再详细介绍。( z; x  l: y# |+ ~5 K
  实现了在单片内显示汉字串以后,能不能读取SD卡中的txt文档中的汉字在液晶屏上显示呢?这块是我自己想的,不知道与别人的一样不一样,反正是实现了。
$ k: g$ \0 y* k+ Q- V4 \  首先我读取SD卡上txt文档上的一个汉字,然后用串口打印出来,发现,读到的就是汉字的内码,百度了下说windows中txt文档的显示的用GB2312的字库。既然读到直接是内码,那就好办了。汉字内码用的是两个字节,字符用的是一个字节,这个一定要注意,因为在以后显示的过程中要用。
: ~7 v+ q3 a: {" q  Y4 M. Y  下面直接贴代码:  m% s* l( K& \" S$ u

3 |5 S. G4 `% y, f
  1. // x,y在液晶屏上的显示位置,我的液晶屏是320*240 ,竖屏显示' L6 u' a) W1 Z& Y" y2 j

  2. 7 E/ T" P0 P" n, e, M1 h$ j
  3.   // color 是画笔的颜色,BkColor 是背景颜色5 ?9 M- ]* W* @

  4. ) D# w1 ]& n% }
  5.   u8 fnShowTxt( u16 x, u16 y , u16 color ,u16 BkColor )$ l( K2 Z% N7 e: u7 e& ^. l  n
  6. 6 w- B6 o; _" N' ^" `
  7.   {, |# y7 q+ \, H& j- L0 w
  8. ) P& {  C7 X! N% I( G* y1 \. v# R
  9.   u8 res=0; // SD卡函数的返回值
    5 k7 A, F. V0 U4 ]

  10. 1 G+ R5 O0 Q: }. }
  11.   u8 buff[100]={0}; // 存储从txt文档中读到的100个字节的内码
    ( h& Q2 G; L$ C, h

  12. 7 g: X5 A' m+ S2 m/ G$ i
  13.   u8 bitbuff[32]={0}; // 存储从点阵字库获得的32个字节的点阵数据
    . {1 g) B' Q1 O# T; b9 v  _' ]* Z/ ~

  14. . n0 j0 C2 x9 l8 L1 h+ C% m
  15.   u8 NeiMaH,NeiMaL; // GB2312内码的高位和低位0 y! _4 P9 H4 y. Z/ r

  16. " l/ _. D8 }- R1 |( z4 [2 i
  17.   u8 CntnuF=1; // 用来 判断是不是读到文档的末尾了,如果读到字节的个数小于100则表示读到末尾了
    % s- e  W/ U0 w

  18. $ x) }3 R8 P# M! V+ K' o
  19.   u16 offset=0; // 读txt文档的偏移地址  i$ A7 a" p! [" A9 t: e) ?
  20. " ]/ Q8 D) Z6 |+ j, g* e4 N
  21.   u8 i=0;
    ( f9 k: B* r! d* M% Y/ m( j
  22. 0 R; W3 }; Y+ r/ e# A
  23.   UINT Hznum,bytenum; // 实际读回的内码字节个数、点阵字节个数
    8 x# V& c5 q! n$ V. l2 X# N
  24. 3 z2 S% w6 j: @% v' Z. l
  25.   u16 x0,y0; // 点阵显示的位置, Z# X/ n7 {% _

  26. 3 z9 I6 C% ?4 F( P# n3 u
  27.   u8 charCnt=0; // 读取的100个字节内码中有几个字符,如果字符个数是偶数则下次偏移再偏移100,如果是奇数,& h% N1 ~; q% f5 C

  28. ' r1 E* ?: q6 `- S* H6 i0 Z0 Q# X" \
  29.   // 则读取的100个字节中的最后一个字节可能是下一个汉字的内码高位字节,则偏移99,下次再把这个字节读上。
    & }% J  H5 c8 @( B$ f8 m, a

  30.   C' x' X( z+ \
  31.   x0=x;
    . Q9 z! N; R+ U* }

  32. 7 n  ]1 T4 I! b7 `
  33.   y0=y;0 ?  o. r4 \, E% I+ u$ O

  34. : J7 |% F; M8 j) a* y7 A+ T
  35.   f_mount(&fs1,"",1); // 挂载SD卡
    % x& c( O) e2 h7 z# h) w

  36. 7 `4 s# ]  B, ^3 `
  37.   res=f_open(&f1,ReadPath,FA_OPEN_EXISTING|FA_READ); // 打开字库文件
    ! Q- B: h+ U1 c5 ^

  38. & D% J5 I* j% M# {8 x
  39.   if(res!=0)' Y* L5 B& R% r3 B8 f) j2 [6 o

  40. 3 P6 K6 I  a+ @& V5 r  b7 x8 |3 |
  41.   {2 ~' H3 k9 T2 ?1 _

  42. $ ^) K* a* n) g; q
  43.   fnShowString(10,120,"open hzk fail",16,RED,WHITE,0);
    ( A0 T/ T2 Z3 ?+ u' t" f" Y

  44. " p+ W, w- e/ t. Z2 A
  45.   printf("res=%x",res);
    # T- {5 f6 `* e6 @* O7 {

  46. . D- w9 a( G6 [/ f2 A, Y. [
  47.   return 1;
    $ f6 a+ F# C8 `% A; q! Z

  48. # f, p6 m+ y; t
  49.   }& W9 e) \; J1 K
  50. 9 P( r+ N% ^+ }- p. ]" `
  51.   res=f_open(&ftxt,TxtPath,FA_OPEN_EXISTING|FA_READ); // 打开txt文档. Q; z3 l; E! b2 H1 U. \8 R
  52. - h9 ~5 w$ h, U% L
  53.   if(res!=0)
    0 p0 f3 X- F: V5 A: H

  54. # Q+ b4 Z3 x/ O$ W, J, ?
  55.   {
    6 D6 {) M& Z! O/ `

  56. 0 _3 B+ ^' o" G$ v8 ~3 G
  57.   fnShowString(10,120,"open txt fail",16,RED,WHITE,0);
    4 v6 T* U& {. z3 ]

  58. 2 y3 @4 I9 d$ K7 |7 g$ s
  59.   printf("res=%x",res);+ b+ h/ f4 z/ a
  60. * P! k4 |& r' o8 q
  61.   return 1;! q* ]% j# _" M. n1 M

  62. * X- N  }6 [  e3 E. D
  63.   }# t) Y8 J4 j2 g( H. z/ P' C
  64. ' d% u7 b; U. s3 E7 h, w# d; {( J; r  I) B
  65.   f_lseek(&ftxt,offset); // 初始化偏移为0从头开始读。/ a: I2 [$ E* ]& a% H' r

  66. * J3 x6 m! }% A( D& J
  67.   res=f_read(&ftxt,buff,100,&Hznum); // 每次读100个内码字节
    ; b9 B$ e. ~5 a5 X) ^/ e

  68.   |/ z$ D6 M0 G8 J1 P) P, [
  69.   while(CntnuF) // 循环判断是不是读到文件末尾了1 N0 K: E/ s0 f
  70. & T7 q5 q& R8 `+ Q' @3 k8 }1 x% V
  71.   {1 e1 v# V/ Q3 `! u- y  d9 g, q

  72. , y1 Z" M" B$ P- l! v/ j) W
  73.   for(i=0;i" k4 l0 d6 u" d7 b% o$ \$ [8 U. M8 [
  74. ! z9 B* p" t: w6 W* u8 H  s/ R3 n
  75.   {
    & B7 X/ o8 z6 D* V* a9 ]' [  [) O

  76. 0 Z  _' f) r3 y5 b: Y) |
  77.   if(x>220) // 显示位置的判断5 L7 I! C& d$ v9 ?- b: C" R
  78. # S  _7 c1 }( F4 `, G" x4 z4 H
  79.   {, X+ ?1 V. _4 Y  f+ }

  80. # j* G% f9 B& D! i  n
  81.   x=x0;
      o( I  p: O; w3 P% `8 s
  82. 9 G/ F( k, s: [9 @2 N; r1 r' M
  83.   y+=16;
    ; Z" z  {" @5 _7 G# b- f" n% J

  84. ' a- {6 G1 N( u0 K) V: K
  85.   }
    ) b+ w! ~7 B' C/ P$ x* t' a
  86. 7 x$ F7 `0 i0 ]; t) Z
  87.   if((y>300))% J7 O- f  w% W' j  u

  88. - B/ d5 v+ O) w3 Q6 P- M6 F- A
  89.   {* t1 s) m' }. q8 o" C7 W- Y

  90. % y) k( Q8 u6 q) p/ K4 j$ O
  91.   fnRefreshscreen(WHITE);
    7 k9 Z4 u5 `+ @- {" h2 X

  92. , @9 I4 d0 ~# f5 t! ?: |+ x5 e$ f
  93.   x=x0;3 ?1 m( y' s1 ?" d9 Y0 q- ^8 h

  94. % W0 M6 q' Q4 c4 E
  95.   y=y0;/ f3 x  [' M- _5 e0 U

  96. 2 O! ?, i: {! s. [% c7 b
  97.   }5 I" R( j8 X$ r: K- Q9 W# |

  98. 6 A% E* h9 w8 n* _
  99.   if(buff>0x80) // 是不是汉字% B1 G- f+ k$ a( m; r1 D

  100. " h1 h# a3 b- \, v0 V- H; z
  101.   {; a" ~& _+ `' V
  102. : L4 n4 c5 Z4 N9 u$ `
  103.   f_lseek(&f1,32*((buff-0xa0-1)*94+(buff[i+1]-0xa0-1))); // 点阵字库内的偏移+ H/ I; v9 E( a

  104. # ], n% ?7 Q  w9 `8 n) N$ I
  105.   res=f_read(&f1,bitbuff,32,&bytenum);, S  V/ L: b# k, ]

  106. . b/ r9 l! m& d0 x! Z: I
  107.   fnShowHzk(x,y,bitbuff,color,BkColor);+ b' a+ }& \" ^: }+ y9 s

  108. 0 G$ I* S6 o% i  q
  109.   x+=16;
    $ R! E7 [2 ~$ X# C6 o
  110.   M2 ~3 ~9 z) t
  111.   i++; // 这个i++非常重要,因为一个汉字两个字节,除了判断语句i++,+ A( R  r$ X  U. U! l; P

  112. 5 @5 V0 C+ q. B! `! t$ _4 |
  113.   // 这里需要还要一个( |0 W1 d/ _- p

  114. & K" U1 f( a9 x
  115.   memset(bitbuff,0,sizeof(bitbuff));
    # s; u9 Q' W. g6 I

  116. " \' Y- w- q& t( d- J6 e- W9 T
  117.   }
    1 q2 R8 s+ ^/ G
  118. 3 y" [: Y3 Q; s/ I
  119.   else // 可能是标点也可能是换行符
    $ J( [( j2 W* X% y
  120. 3 W1 j* P0 C, O( Z2 ^3 K% B+ o
  121.   {
    9 n5 r+ W; @# Z( X  r  [* |

  122.   o( }; v+ C5 J
  123.   if(buff==0x0D) // 换行标志! S" y3 e+ z( c, K% l& V

  124. $ x8 `$ a4 V- @3 b1 {& G
  125.   y+=16;# i  W6 M+ t# z0 r: L/ R+ D
  126. 6 Q: y, h' a- [" H1 A* ?2 f3 [
  127.   else) I- Y) v( A4 G2 O! Y* d
  128. 3 x5 Z% C% w9 R3 k
  129.   fnShowChar( x,y,buff,16,color,BkColor,0); // 字符' E1 h" E1 Y7 u& y" C

  130.   O) w, q  N, G) L
  131.   x+=8;7 h7 L" L1 V3 ^# e" q" T
  132. - |, h, N$ R4 j! |' t8 |
  133.   charCnt++; // 字符个数计算,用于判断下一次读txt文档的偏移地址
    - _$ U" H) T  b% j

  134. 0 E2 d- A4 ^8 {3 C, W, h% B
  135.   }- ^+ }1 \. c- n2 h/ W- T" I9 x9 B
  136. 3 L/ L6 ~, b2 s1 k
  137.   }
      e& ?( [& n9 f/ W. ?3 J
  138. $ @- l1 Z5 Y( p# E
  139.   // 计算txt文档的偏移地址0 ?3 G1 E' P& F8 B
  140. ! \+ Y- i, ?7 f/ Y) e# [9 z
  141.   if(Hznum!=100) // 判断是不是读到文档末尾了% m  Q) _6 `0 @& _; L3 f0 j' m
  142. + v/ i3 ?( K. W) x0 @9 P# I
  143.   {  K+ M& j' X9 K3 c+ m
  144. " L* e1 f9 \( q1 b6 N% Z
  145.   CntnuF=0;
    1 n8 O0 n: \2 Y9 \- `$ \  S: |
  146. ' [6 P+ ?4 x7 [! g
  147.   }* q' N5 N( v* D& g/ U. D

  148. 4 f( e  A. j) Y9 N
  149.   else // 没有读到末尾继续读+ f/ N8 n( y$ J" {/ B- n
  150. 0 V% Q5 Q, _$ h( F) p. c" U
  151.   {
    # c6 ~. g+ [! k) |; R" n4 q

  152. 1 ?, ^/ S. N! Z7 B' z- |1 }' b* r
  153.   if(charCnt%2==0) // 字符个数是偶数,100个字节内码里边正好成对出现,地址偏移+100
    2 N9 ~* ?7 d% D+ m' M
  154. . o6 Z3 s, I8 u$ \. ?) R
  155.   offset +=100;- l/ e5 P1 Z9 ^2 b9 B$ J

  156. . t1 h% u, n; B! ]9 w
  157.   else" P* b+ D0 I2 z$ ]
  158. : X- \: D1 J9 f
  159.   offset +=99;  l0 z* _2 f5 P7 g+ m( |1 ?. O
  160. # J/ b: ~. c6 C8 ]
  161.   memset(buff,0,sizeof(buff));% f$ r  m$ t4 D) K& U. x2 N

  162. 8 A) j; i5 B4 k6 o
  163.   f_lseek(&ftxt,offset); // txt 文档地址偏移4 Z( d- H# q- x3 L

  164. & B5 Y3 U) z- n4 ?* I/ k
  165.   res=f_read(&ftxt,buff,100,&Hznum); // 读内码数据
    $ u* R6 ]0 |' ~. c+ F' l) D, [
  166. 9 R, x9 s! Y# [
  167.   }
    3 D! d* p) ?$ f5 a& d6 v! |: _6 f& O& [

  168. 3 N% R, i. d- @4 W* a. k8 X5 ?& B! p
  169.   }4 b6 f& o. Q7 ^7 o, b1 S: C
  170. $ k  n( ?  ?5 v$ z# v% d& F
  171.   f_close(&f1); // 关闭打开的点阵字库
    , K. Y( m+ N" `3 w" W
  172. - @" o5 c7 e$ K! q! f8 D( z
  173.   f_close(&ftxt); // 关闭打开的txt文档
    , x+ O2 s# F9 ~  \

  174. 5 V; N0 V7 ]  x4 H8 I' C$ \
  175.   f_mount(&fs1,"",NULL); // 卸载磁盘
    ( R! h- _! n2 [) L( x2 f$ E) G9 h# e

  176. % n2 l! R- p2 q( G. K9 C2 P; c
  177.   return 0;8 h( E2 z& S$ u. {4 Y

  178. ' h- }4 f% }, Y9 z8 r
  179.   }
复制代码
, k3 R3 V6 {1 o0 S; [( g
  以上是简单的电子书的实现。  G3 \3 ~% U1 B% o# u5 Q
  因为不同的系统有不同的编码这个要注意,比如我再Windows上的汉字拷贝到CSDN网页上就是乱码,这是因为使用的汉字的编码不同,对于不同的编码格式,还需要做内码的对应转换,把其他的格式转换成GB2312或者GBK格式然后调用字库显示。( X' M: C7 u/ x/ J* b3 E, i
  其他常用编码格式Unicode、utf-8等的具体介绍和转换成GB编码可以百度。' @, P) `# _/ M0 z
  SD卡注意事项:
) U; S1 Q) d  T5 ]3 T  对一个文件读,必须先打开文件,读完后关闭。
( I# B- Z0 y& T1 z0 p) k4 f3 P. y  对一个文件写,必须先打开文件,根据情况确定打开的权限,只读,读、写、创建等,先完后最好调用f_sync()函数,这是一个同步函数,类似于linux中的同步函数。SD卡中的写函数应该是带缓冲(猜的),在关闭之前调用这个函数将缓冲区的内容写入SD卡中,然后关闭文件,否则可能写入失败,不能将内容成功写到文件上。
4 u: i1 E$ u3 _/ E  ?( |  文件的打开路径,Windows中的文档可能是隐藏文件类型的,这个一定要注意,隐藏文件类型的a.txt和不隐藏文件类型的a.txt 不是同一个文件,这个一定要非常注意。
& g  n0 P3 Y) o; v7 f
: {6 J/ A' F3 B& F) t' e  B: J7 v+ _0 p4 Q# y
  • TA的每日心情
    开心
    2023-5-15 15:25
  • 签到天数: 1 天

    [LV.1]初来乍到

    2#
    发表于 2020-4-20 10:29 | 只看该作者
    现在STM32单片机用得人很多,资料也很详细
    您需要登录后才可以回帖 登录 | 注册

    本版积分规则

    关闭

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

    EDA365公众号

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

    GMT+8, 2025-8-12 17:02 , Processed in 0.109375 second(s), 23 queries , Gzip On.

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

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

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