电玩DIY [ VG DIY ] - Video Game Do It Yourself

 找回密码
 注册

QQ登录

只需一步,快速开始

查看: 14930|回复: 27

自制FC无线手柄

  [复制链接]
发表于 2019-5-22 14:16:45 | 显示全部楼层 |阅读模式
本帖最后由 雷精灵2046 于 2019-6-14 09:28 编辑
! @7 Z, V; A0 p& u- j/ G1 Q$ h2 L$ H4 w8 d+ S* i4 S
没有用复杂的分立元件搭建发射接收电路,直接用的现成的2.4G无线模块jdy-40。
6 ?! ~* [& G# }/ D6 g4 G
5 ^4 h( X$ D3 b8 x4 ]) z
9 h/ K6 c, h6 n, T发射端靠3.7V锂电池供电,用了一片SOP8封装的STC单片机,负责产生连发脉冲,同时负责检测电池电量,电压低于3V左右的时候触发低压中断,低压指示LED就会亮起来告知该充电了。平时发射模块和单片机均处于睡眠状态,有按键按下才会唤醒,从而实现省电。实测睡眠状态下整机电流约1~2uA。板子洗了一下稍微干净了一点。因为对于微功耗设备来说,焊接残余的助焊剂可能会增加漏电流。
# q! q$ W8 w: U% [% E0 o. [
- p' y% Z4 f: n4 K9 l- U买了一个火花的FC山寨手柄,去掉里面的牛屎板子,并修正一下塑料挡板,把锂电池和充电模块装进去。' F/ `% C( W1 I2 U; N
为了减少体积,充电模块裁剪得十分小,并且更换了充电电阻使之适应这个小小的锂电池。这么小容量的电池,也不需要多么大的充电电流是吧?3 R9 ]" ]( U* d6 t; g0 K/ E
然后统统用热熔胶粘上。充电电流比较小,所以发热很少,不会熔化热熔胶。
4 u0 s9 I7 G' ?) E+ y6 ]: v$ t  G. v1 o( L! U/ g2 E

; S: r) p3 p& B9 t$ r# K& c: p% a# y: O+ {* {/ G# a0 b8 x# ]
最后把按键、导电橡胶和电路板装上去。
& ^2 ~' w# ]3 ]$ C精心裁剪了电路板,正好扣上,不会阻碍其他元件,也不会影响后盖和拧螺丝。* y6 |6 F1 r# D5 G

9 V0 J- x5 T. G* Q5 l: v4 m& i. R% A6 r; t- d3 H
完工!" \" e( C& @3 [5 X6 j" d

7 }- d: S1 A6 N8 w8 [- v3 G. P9 h3 e$ G+ t& g
这是充电的MicroUSB插座。旁边的小孔用于透出低压报警LED的光线。
" w2 K/ T$ l3 C( Y6 r0 U6 ?6 h2 k( ]+ }

# Z8 Q% n; o$ R' o! J9 J接收端用一片DIP16封装的STC单片机模拟CD4021。为啥要用单片机模拟而不是直接用CD4021?因为jdy-40模块接收端在有按键按下的时候输出高电平,无按键按下输出低电平,和普通手柄正好相反。当然我也可以用两片74HC00或者74HC04之类的逻辑门进行反相,但那就增加了芯片的数量。对于FC手柄这种工作频率并不高的设备来说,STC单片机完全可以胜任模拟工作。1 Z1 L2 P; Y) K: r* h/ F- E

# {( k6 I3 b4 y, z+ ~
* D- _5 e! j+ Z" _) {$ H  V
3 x" n; `7 O# m- Z3 _电路设计有点小小的错误,所以有几根飞线。原本设计使用低压差LDO是XC6206,结果在做这个接收模块的时候,买的LDO居然找不到了!无奈只好用了AMS1117。幸好对于接收模块来说是5V降到3.3V,1117可以胜任。要是发射端手柄的话,3.7V降到3.3V,那就非得用6206不可了。
- M% j% a& \! v
2 I3 l  D# T: [1 ^实测十分灵敏,延迟极小几乎感觉不出来。可惜这山寨手柄的手感并不佳,尤其是方向键,软塌塌的。看来我得买个剪线手柄改装。7 G. ]3 t6 a+ U4 f& e0 y0 Z, l# c# _

; m& c6 I4 P6 M8 M% t' {( X2 E这是电路图,有兴趣的朋友可以参考。4 w0 {$ t( ?* x( o% B3 R  b

2 I. p" D, }8 b4 L- q- o# e7 u/ a
; m! U/ P- F5 D我信奉开源主义,十分痛恨把技术藏着掖着。好东西大家分享嘛!所以两个单片机的源代码大公开!5 Z7 {# g9 ], G5 R4 J% t- v
编译器:Keil 51。/ r7 ~1 h7 Z/ [2 |2 ~
0 b5 B- w! I0 M' H7 x
发射端:8 U8 {: e* \) d! Z' T5 F  v) u
  1. #include <INTRINS.H>, g: z$ X( E0 U* e' N. J. k0 U
  2. #include "STC15W.h"
    5 `1 S, C; G3 b

  3. 2 N1 U% k  g0 L% ~, X* |

  4.   \9 {5 a; J/ z/ V/ I
  5. /*
    & G, S5 H6 V/ J" A7 z1 p3 t
  6. --------------------------
    ; z! z- o  D% w' ^
  7. |1 (OUT)        \__/   (INT1) 8|
    ! n" L% a  ]* q4 j. H
  8. |                                                   |; s/ j( a+ n( ]5 \( v
  9. |2 (VCC)                   (INT0) 7|
    % d5 {: Z$ i  Q  n  ]3 b! Y( O6 g
  10. |                 STC15W204S                   |
    3 d4 r3 B! t. p, `
  11. |3 (LED)                         (TXD) 6|
    4 `3 `+ u2 E7 Y. g5 `
  12. |                                                   |
    ! H) Q2 |; V8 Y1 n
  13. |4 (GND)                         (RXD) 5|
    ' k. c: M% ?& F8 d7 K% X+ R$ H
  14. --------------------------9 g5 k8 M. B1 Z8 K" `

  15. # X% ~& K! D5 {, Z1 D2 ]; a3 _1 |
  16. LED ---|<|---[===]--- VCC
    4 c2 y6 t2 u* r' @
  17.            Red          330
    4 W1 r4 L" i( P
  18. * \5 C8 y) s* {( Y" H8 u. z1 h- c
  19. Fosc = 6MHz  i" v& z4 k& i5 s' Z0 D
  20. */
    ! a5 R+ P  N1 j6 V0 H5 N4 z

  21. , z" l" M- O  G3 `  H

  22. ; |/ t* ~1 a* e- }3 `7 B0 }4 v( w: |
  23. // 矩形波输出脚
    ! |- J9 X! Y1 V3 x
  24. sbit OUT = P5^4;; ~. T2 T  ~4 ^; Y1 n, _
  25. // 低压指示灯引脚
    2 A6 P( [$ O/ C. k  Y
  26. sbit LED = P5^5;% s' W5 E* P8 M8 X4 r9 ~

  27. - H' h( Q, U! ?4 U8 [2 ]
  28. // 停机标志位  R/ Z4 L$ B9 k$ ?6 c) J7 A# N
  29. bit isReadyToHalt = 0;& U8 s* a0 X* S+ K
  30. 2 m) g7 _, o" H" v- L5 F* ?
  31. // 矩形波次数累计
    5 M, ^+ @8 G9 H- R  p8 Q/ F
  32. static volatile unsigned char count = 0;8 S0 l) Z! G5 ?, w- w
  33. 9 t3 m6 _5 e7 @+ ~; `
  34. / O$ b3 e3 a* r" h( {  O
  35. static void GPIO_Init(){
    ) l1 s* t% R0 o9 U
  36.         // P3口设置为准双向,默认靠内部弱上拉输出高电平
    6 p- w+ Y" e* e+ d- J
  37.         P3M0 = 0;
    1 Q, o, \7 t7 Z. i
  38.         P3M1 = 0;
    $ @' k4 x" g3 N4 t* ?
  39.         P3 = 0xFF;$ p% P3 r/ b5 ^& a( p5 a
  40.         // P5口设置为准双向,默认靠内部弱上拉输出高电平6 v; k4 E6 r  Z
  41.         P5M0 = 0;
    $ r7 n& M9 r" ^, e9 c" w9 Y. ]7 K
  42.         P5M1 = 0;
    ) u' b/ m, A, j- b5 ^. R
  43.         P5 = 0xFF;- j! h8 r2 K8 V: I! \5 i
  44. }& J0 W5 `) K5 j( N
  45. # F, [4 z: q0 [2 ~
  46. static void Timer0_Init(){7 w, V2 O' w8 c6 T' j3 y
  47.         // 16毫秒@6.000MHz
    ' _+ L  T8 d- u; d; |! Q6 R
  48.         AUXR &= 0x7F;        // 定时器时钟12T模式9 o2 s6 M1 l( V% E' V
  49.         TMOD &= 0xF0;        // 设置定时器模式4 P# U! v- O: V: Q% Z
  50.         TL0 = 0xC0;                // 设置定时初值
    * m; Q" s9 e/ d: t
  51.         TH0 = 0xE0;                // 设置定时初值
    ( P, S7 F5 }" o$ K
  52.         TF0 = 0;                // 清除TF0标志
    0 B0 z% Q( |/ |" r
  53.         TR0 = 1;                // 定时器0开始计时2 ]0 b3 C; B+ ?2 W8 E' x
  54. }* F  ]8 o- \( \+ i8 I0 V4 X
  55. 5 S) ]' |+ ~; H8 B+ Z
  56. static void Interrupt_Init(){; M' M6 q: F3 ~0 x9 N: x1 y9 }
  57.         // INT0中断触发类型为下降沿触发  t0 M4 }$ {! ]3 \# a
  58.         IT0 = 1;, T0 [- |4 L) |, }: r( a
  59.         // 允许INT0中断
    ; O. i, B' `5 k, \5 ^1 U- K
  60.         EX0 = 1;
    ( ]3 c2 x6 @) Y/ B7 g' ^) e' Z
  61.         // INT1中断触发类型为下降沿触发
    ! F0 K, w) P/ Y
  62.         IT1 = 1;+ X1 O( U/ K5 B* Z" }* H( [
  63.         // 允许INT1中断
    8 j/ b% h1 \+ y. G8 n3 Y/ z
  64.         EX1 = 1;
    4 R7 N* E5 ^- X$ X9 `, a, E
  65.         // 允许定时器0中断
    - ]4 k" J! D0 S" K2 V! g$ o
  66.         ET0 = 1;8 ^+ ^2 m8 |8 |9 L$ h
  67.         // 允许全局中断
    1 X+ a! a' V; N3 M
  68.         EA = 1;
    ; J9 S4 `( O) r% W$ i2 J4 y  `
  69. }
    / }6 M) h% h& U* @( f0 a. [4 M
  70. % M% j2 m: D8 f6 t
  71. static void INT0_Isr() interrupt 0{" }7 j- W! ~4 a% u. b! E6 d6 m! m
  72.         // 矩形波次数累计归零
    . \# b, W0 A! }9 S8 I
  73.         count = 0;
    5 M! e4 j9 B, z/ f
  74.         // 重开定时器0中断
    " m7 [( @4 t' z
  75.         ET0 = 1;& U8 d+ M) `6 e, P: G
  76. }
    6 m$ P* ?& m3 f! |  r7 f9 Y" n
  77. . {3 }8 s& g4 e) E6 D; x7 o
  78. static void Timer0_Isr() interrupt 1{5 d0 _+ E+ {  q
  79.         // 输出矩形波
    ! `. A/ Z: L, o! O
  80.         OUT = ~OUT;& F8 l, z! z5 E8 }' r! l: W  ^
  81.         // 累计矩形波次数& F: V0 p. K. |$ w3 a
  82.         count++;4 ?4 F: j- P5 A# X
  83.         // 超过250个矩形波,准备停机! @2 U7 E3 j$ ^+ K) j9 P
  84.         if(count > 250){$ S. C: E' |  B0 [
  85.                 count = 0;+ e" e1 E' K" G3 j' U8 Y4 j& _0 N1 O6 \
  86.                 isReadyToHalt = 1;
    $ Z& S; l! C. P6 @+ T8 P/ i
  87.         }9 E  N* q" o( a3 w
  88. }% \* }& R) ]' k$ @# @7 a

  89. ) d" `; l8 v: s) D
  90. static void INT1_Isr() interrupt 2{* k' [" ^( H1 u( W" l7 V5 \+ g
  91.         // 矩形波次数累计归零
    8 j$ B1 y' m$ y; t! i$ U/ g9 E$ f
  92.         count = 0;8 X1 O5 a9 F7 D; Z; g' m/ C. I
  93.         // 重开定时器0中断1 w9 m/ J- N& s
  94.         ET0 = 1;, O4 @+ a+ B3 r0 M
  95. }
    3 z  K: W% [. w

  96. 4 Z$ e( I1 R/ M
  97. % ]6 ~3 S  i2 l0 t$ j2 X* R& U4 M
  98. void main(){- p4 F" E! t7 c" W  Z
  99.         // 初始化P3和P5口- B/ }8 }5 r1 J* e  _# U) V% X
  100.         GPIO_Init();$ K- K5 K4 \4 f) ]1 q" n8 H
  101.         // 初始化定时器0
    9 ^/ r5 g- a4 M# x; r
  102.         Timer0_Init();4 s7 G  x# O" {. P. Y" l# F; w
  103.         // 初始化中断3 B) X" A4 A- u) t4 d8 ^
  104.         Interrupt_Init();  p' y3 i, d# }- A6 h* v
  105.        
    ( P4 R  k! l# l4 @" `
  106.         while(1){( l/ R  j& i( r- |
  107.                 // 检测电量0 K. A0 u( f; {5 A! S
  108.                 if(PCON & (1 << 5)){
    , E' P# e. y$ Z+ E; p& t
  109.                         // 如果电量低,低压指示灯亮) |4 X3 s/ S1 g- O. U0 @4 [
  110.                         LED = 0;
    / m* K8 I/ ]7 D
  111.                         // 清电量检测硬件标志位& x1 |! u( n/ V! E, r
  112.                         PCON &= ~(1 << 5);
    4 y, o- U% s, I
  113.                 }else{! @# u  w, ?5 z2 Q4 T
  114.                         // 电量正常,低压指示灯灭/ c5 s  [5 ]7 J7 o6 ~( _" A+ J
  115.                         LED = 1;
    * G: ]/ @7 W4 v' u' B: o* ^4 i
  116.                 }& ~9 X8 j! @4 U8 h2 O
  117. 9 [7 h( ]& k1 C, ?9 m# T6 ~
  118.                 // 检测到停机标志
    $ w6 _; [4 C" N2 W+ U% g
  119.                 if(isReadyToHalt == 1){# E) c* R  g4 |) e% ^5 l) T0 |3 c
  120.                         // 暂时关闭定时器0中断& V/ N1 U" @5 s& l0 X
  121.                         ET0 = 0;1 \$ R" O: H) F% @
  122.                         // 停机之前先把矩形波输出脚置低电平,以方便INT0和INT1唤醒CPU
    , D# D: f4 f4 g& P" S
  123.                         OUT = 0;9 F. e4 H; ?' ~5 }5 e
  124.                         // 停机之前先把低压指示灯灭掉,以省电% S7 M% t2 T' l0 m/ S; C: R, M
  125.                         LED = 1;
      g9 G( z1 l! J" V5 o; u
  126.                         // 进入停机模式
    + f$ `. z! R4 P5 H9 h, U
  127.                         PCON |= 0x02;$ r6 N5 V9 N& O, P. @
  128.                         _nop_();8 d2 T! D9 P+ q' n
  129.                         _nop_();# O/ }' u/ a9 R, x8 ^# W/ K
  130.                         _nop_();
    0 o1 {9 l# w5 w* J6 F
  131.                         _nop_();. }: C  M  u$ k
  132.                         // 唤醒,清标志位
    2 [: t+ z& I  @/ m& s2 n8 L0 F
  133.                         isReadyToHalt = 0;
    ' n, D! ~/ e% k
  134.                         // 重开定时器0中断
    & a5 B' L8 J' o6 J) I/ w
  135.                         ET0 = 1;! b/ U1 `) z' K
  136.                 }
    * o4 b8 ]+ R. i; z" N
  137.         }
    " v3 k  D+ O' M9 N: h
  138. }9 N* ^% k1 a* R2 [' e! [+ C
复制代码

- G9 I; i* L% c9 e# v9 g硬件参数配置:
5 D3 }  \* m9 A3 M& q
$ h% c% S4 [# B  n& b* p/ @  z5 W
接收端:2 v+ U# \0 X& p) Z! C% M( J
  1. #include <INTRINS.H>. f  `" s' D; S" K
  2. #include "STC15W.h"
    : d- t" k  b8 Z" K( V
  3. 8 ^9 }/ ^6 Y& m; Z. c& a

  4. 2 F! [, }/ Q' J1 D, S
  5. /*( T+ |1 o3 r" C8 \( h
  6. , Y' _7 h7 l7 v
  7. *---------------------------*5 k" r5 u, ^! Z$ N
  8. |1 (GPIO2)         \__/  (GPIO1)16|1 b% a' E& T# c+ A/ o
  9. |                                                        |! h4 c7 C5 Y+ Y+ [: p, w$ k! W- ]
  10. |2 (GPIO3)                   (GPIO0)15|+ p6 B" P: W  C* z( d' F
  11. |                                                        |; C# m" \. I, l) {! i; e
  12. |3 (GPIO4)                                  14|
      ]% ^/ t7 \' B; d  S- t$ z0 p
  13. |                                                        |: `% c% Z& j4 f* A
  14. |4 (GPIO5)                        (DATA)13|
    $ }3 ?3 Q3 |8 c" j1 U% J
  15. |                  STC15W204S                |6 V/ `7 }& z  \8 q
  16. |5 (GPIO6)                   (LATCH)12|
    9 s' Q5 M" [% B4 E
  17. |                                                        |7 f( t% a0 e* ^. L% r5 W: B
  18. |6 (VCC)                         (CLK)11|6 d) V: P7 A: P3 _( S! Y! C$ s: f
  19. |                                                          |  k2 t* q! G, {8 b6 g; W
  20. |7 (GPIO7)                         (TXD)10|
    2 s9 y; r+ C9 P' h; R. g# ]$ P
  21. |                                                        |& I/ |% y, z# D# W4 C) N) R
  22. |8 (GND)                         (RXD) 9|  @+ c% {7 G' o" b( K3 t
  23. *---------------------------*
    ; U: g- H; R; Z& E0 p8 W5 r3 t
  24. Fosc = 12MHz" g3 u& W- r( j0 z

  25. $ }* S: C7 q5 r2 A, W2 \5 u
  26. P1.0 -> 上
    $ S7 L, ]8 J8 M+ A% O$ f
  27. P1.1 -> 左
    0 h0 o$ e, X0 m2 z& l; g
  28. P1.2 -> 下6 u6 U6 f8 v! p6 e
  29. P1.3 -> 右
    ( p: Q: |6 u+ `% |2 S# L
  30. P1.4 -> SEL
    & z1 W( L6 |* q  M3 s
  31. P1.5 -> STA
    " h7 i: A0 Y3 R) G1 P8 N0 N# t
  32. P5.4 -> B
    # C, M! L! _5 ~4 H
  33. P5.5 -> A6 [) ?4 R1 a7 s9 _5 T  I

  34. ' o8 Z# q8 j; i, G& B  n1 @5 H( ]0 W+ ]
  35. */
    * D. J% J+ o! P3 ?' D* t4 F) Z* R0 ]" K

  36. $ I; q! V# O: k0 k

  37. 8 z  e' q* `. ]/ }# m8 {% R5 a. k
  38. sbit CLK        = P3^2;) X* n9 H) z( h  w" z0 N9 ]* H3 T
  39. sbit LATCH        = P3^3;
    6 o/ K) `3 I& z* j3 X# |# j& r
  40. sbit DATA        = P3^6;
      ?  ], G0 u" i$ v7 r) C( O. Z

  41. 1 _: _5 v3 L7 b+ B  \3 I- ?1 H% W
  42. bit isReady = 0;, a! N* o  r( e& C2 ~/ w, E
  43. static unsigned char key = 0;
    2 c2 C' A$ A! F  B
  44. static unsigned char buf = 0;        // 双缓冲。这个缓冲区保存从P1和P5组合而来的键值
    5 H' [) B$ D6 X! h0 L! P6 w; r0 E
  45. static unsigned char bufReady = 0;        // 双缓冲。这个缓冲区保存上面那个缓冲区的备份& d2 d9 P8 j7 Z2 m# n$ M, ]
  46. static const unsigned char data mask[] = {0x80, 0x40, 0x10, 0x20, 0x01, 0x04, 0x02, 0x08};        // A B SELECT START UP DOWN LEFT RIGHT。为提升速度,这个表放到RAM中
    2 ~4 e- }; @! p8 h) |( I* l
  47. static unsigned char idx = 0;1 e8 l, o- V  x1 C- }$ w' g- c
  48. ; P- ^$ M, t3 z: P! S* E. r  n
  49. ( Q) s, v  O+ @# }1 u* i6 U0 l" F
  50. static void GPIO_Init(){
    2 h& O& s' n3 V" j5 _
  51.         // P1口和P5口用于接收并行信号,全部初始化为准双向,依靠内部弱上拉输出高电平
    3 r- J- X. \1 K9 Z
  52.         P1M0 = 0;
    3 u3 @' D& i* u  L6 T  A
  53.         P1M1 = 0;7 l4 p: z& y8 v% |
  54.         P1= 0xFF;
    ( {( `% Z- B2 b1 E1 K* `7 t
  55.         P5M0 = 0;
    ' o  q( `& m1 E8 a: W# _8 @
  56.         P5M1 = 0;
    8 {1 X( J: D. t1 p; [" ]4 r
  57.         P5= 0xFF;, k  j$ Q) c9 i) ^0 \& p2 _0 p
  58.         // P3口初始化为准双向% n# d) [( l6 S0 b' E2 p
  59.         P3M0 = 0;. h  P1 W$ ]% A* j3 y: c
  60.         P3M1 = 0;
    & ]; ]6 R: c3 h* y
  61.         P3 = 0xFF;
    % Y6 e$ Q: [. G+ T6 M
  62. }* L, G" e- ^/ X6 x

  63. ! P1 o$ [7 X! V4 P
  64. static void Interrupt_Init(){
    8 H# C8 S0 T* z6 k' ^
  65.         // INT0中断(CLK)触发类型为上升沿+下降沿
    7 p: N8 o, j9 z/ z+ N% v
  66.         IT0 = 0;& R+ @3 d1 M# O, w/ K- ?$ d
  67.         // 允许INT0中断5 i& [( i# f* m( |) a) z0 D
  68.         EX0 = 1;  S: g" t  k% ]( R
  69.         // INT1中断(LATCH)触发类型为上升沿+下降沿! d& F2 _) V6 q- i" S  `* M; F
  70.         IT1 = 0;
    + c  e( ]8 ~5 K: c; ^" ^3 ~
  71.         // 允许INT1中断3 }" ?+ x% Z) }* p! M
  72.         EX1 = 1;% ]: U1 u. A+ e/ C* [
  73.         // 开启全局中断0 S- i: l4 K- u6 e
  74.         EA = 1;3 g2 @+ w9 J, Z8 d) N1 m; b
  75. }0 C9 O; d2 H7 q& e  Z7 K0 {  K! m
  76. % Z( ?& ?4 m9 e+ t" `
  77. static void INT0_Isr() interrupt 0{1 o7 C1 J( L9 i; x
  78.         // 只有已经成功锁存才允许CLK移位
      A, o5 g3 r) Z, c
  79.         if(isReady == 0). A+ F; g+ s+ J4 M% @, _( u: h
  80.                 return;; t) @  q1 n# O2 e; U  g9 j
  81.         // 读当前引脚电平,如果是低电平则说明是下降沿,此时直接忽略该中断
    8 B5 i* _1 a- ~
  82.         if(CLK == 0)6 U; z3 ]* C8 z# g  K
  83.                 return;, t" W  g; b8 \9 z- Q; O5 r) p
  84.         // CLK上升沿到来的时候,取锁存值的下一位输出9 W  H1 P2 s, W! N
  85.         idx++;
    6 T9 X3 R3 k( d" k; s7 j
  86.         DATA = key & mask[idx];6 t' b% j6 k8 H+ E
  87.         // 如果已经完成7次移位,则一轮读取完成" E" S  G- k; D- }. d, d
  88.         if(idx >= 7)
    & D: E1 N4 C$ ~$ G
  89.                 isReady = 0;8 {: [9 _8 O* d! A) l
  90. }
    ) m9 N8 e: Z! R3 a/ b4 ?- _' C) ~
  91. * Q+ S2 q2 K. g; @9 B9 d
  92. static void INT1_Isr() interrupt 2{
      A; s. ?0 ]5 c! \; c6 D
  93.         // 读当前引脚电平,如果是低电平则说明是下降沿,此时直接忽略该中断
    6 r0 e' q- G7 X/ a
  94.         if(LATCH == 0)
    7 l5 |( v+ j& q
  95.                 return;0 X& |+ Y5 Q3 I* O7 {
  96.         // 当LATCH上升沿到来的时候,锁存所有按键状态,同时把键值A输出到DATA
    ; V* ]! t! q! ^9 \) W
  97.         key = bufReady;. L8 l, l6 @8 J2 c7 O; m; P( ~
  98.         DATA = key & 0x80;//mask[0];        // 为了加速运算,直接取表中的值而不是读表1 P. K2 s7 t. C2 w3 K6 G
  99.         idx = 0;$ H) i0 |& [( z) A# j
  100.         // 允许CLK进行移位
    - N. T* v( m% d) p  @( m8 c3 |
  101.         isReady = 1;3 L3 W: q8 G, f; \
  102. }
    4 V; Z5 x( o- L# ]3 y9 M! p( |0 c

  103. 1 D( J$ V. Y- s8 B, d3 H# J& k
  104. void main(){
    2 F4 T6 y# u6 i' ?
  105.         GPIO_Init();9 t; l+ ]& I) |6 ]4 N$ f
  106.         Interrupt_Init();- X/ Q9 U! a, }6 G
  107.         & y- Q6 z/ V* k( d
  108.         while(1){
    5 g$ K/ _, Y4 H! y( j  x& t) j
  109.                 //PCON |= 0x01;        // 进入省电模式2 b$ D8 [+ v0 K+ S1 f+ Q
  110.                 //_nop_();* }( ]) N% A+ J0 x
  111.                 //_nop_();. Z& W3 @/ Y" l0 E: \& Y
  112.                 //_nop_();6 v9 Q* M. w; D9 Z9 i8 ^
  113.                 //_nop_();2 f( ]: ?8 {7 p3 }# C
  114.                 buf = ~((P1 & 0x3F) | ((P5 << 2) & 0xC0));. f# F4 }& B6 E
  115.                 bufReady = buf;! ]! m# |- |7 y6 [( [
  116.         }* `/ k/ j# I7 ^$ R
  117. }9 F' _  j+ c7 Z+ b# X
复制代码

! X9 P, K, L# n- |( S2 U! ~  S硬件参数配置无特殊要求,晶振频率选择12M即可。
$ Z6 q1 u0 A$ o
* ?$ ?6 S" m6 p& G: e0 I" O这是编译好的固件。

本帖子中包含更多资源

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

x

评分

参与人数 3威望 +1 Diy币 +3 热血 +110 收起 理由
sion + 5 顶一个
5911 + 5
xunxun + 1 + 3 + 100

查看全部评分

回复

使用道具 举报

发表于 2019-5-23 10:05:23 | 显示全部楼层
不错的设计,想问一下楼主,FC的15针公头怎么解决?普通的公头太短了,插不进去FC的扩展接口。
回复

使用道具 举报

 楼主| 发表于 2019-5-23 11:27:39 | 显示全部楼层
69yuan 发表于 2019-5-23 10:05
1 O3 o% h5 _, S& W* Z6 {8 o" M不错的设计,想问一下楼主,FC的15针公头怎么解决?普通的公头太短了,插不进去FC的扩展接口。 ...
0 m! b3 L4 K' N" |
坛友的改造方案
回复

使用道具 举报

发表于 2019-5-25 10:42:27 | 显示全部楼层
高手的无私奉贤值得表扬,辛苦了!
回复

使用道具 举报

发表于 2019-5-25 12:07:18 | 显示全部楼层
精彩,楼主动手强,也写得很详细。# u- z% ?0 f( s# z# S# z
2.4G方案是目前无线的最低延迟吗?
回复

使用道具 举报

发表于 2019-5-28 17:27:23 | 显示全部楼层
给技术帝赞一个,有半成品发布吗,自己焊接改造就可以,编程实在不会啊
回复

使用道具 举报

发表于 2019-5-28 18:55:54 | 显示全部楼层
非常好,楼主是技术帝,到目前我都还没开发fc的无线套件,等空了,开发一套套件,等玩家自己组装。
回复

使用道具 举报

 楼主| 发表于 2019-5-29 16:49:20 | 显示全部楼层
xunxun 发表于 2019-5-25 12:07
2 f9 m' T$ e1 E7 l6 J精彩,楼主动手强,也写得很详细。
7 d& U- y! L5 t/ z2.4G方案是目前无线的最低延迟吗?

% K- d+ C6 L3 j: n我没用过其他无线手柄,所以实在不知道我自己做的这个手柄到底是不是最低延迟。- E" f6 B; A  t1 u7 t6 C
不过根据网上的说法,延迟高低主要是由通信协议的复杂程度,以及数据传输速率决定的。这个模块虽然是2.4G无线模块,但由于协议很简单,所以延迟比较低。
! q% w" ]5 w3 G8 w- L我用这个手柄玩一些ACT游戏,比如超级马里奥、忍者龙剑传、热血系列,完全感觉不到延迟,和游戏机自带的手柄没有任何区别。唯一的区别就是这个手柄是用火花山寨手柄改造的,外壳是垃圾回收塑料,粗糙+脆弱,导电橡胶弹性不佳,手感不是一般的差。
( d( d! r9 q/ f$ V1 G$ x% w4 y我手里还有十几张板子,等我有空了我再做一套,到时候买一个好一点的手柄改造。
回复

使用道具 举报

 楼主| 发表于 2019-5-29 16:56:14 | 显示全部楼层
ppad 发表于 2019-5-28 17:27
1 I/ n$ a0 r. M' p+ a1 [给技术帝赞一个,有半成品发布吗,自己焊接改造就可以,编程实在不会啊 ...
4 g# ]/ R$ u+ M5 ^
很可惜,我手里没有多余的单片机了,LDO也找不到了,锂电池以及充电模块更是没有了。反正就是该用到的元件基本都没了,所以没法发布半成品。3 q( O2 Z( R* r; A" o
两个板子倒是有十几张剩余。- y. v+ W5 `& T; n. T
你要是有USB转TTL串口板,完全可以自己买这两种单片机,然后我给你编译好的固件,你自己用串口板下载到单片机里面就行了。两个2.4G无线模块也得通过串口板用AT命令设置参数,不过好在我在设计电路的时候就已经预留好了串口,可以直接在线下载和在线设置参数。总的来说并不麻烦。
回复

使用道具 举报

 楼主| 发表于 2019-5-29 17:00:34 | 显示全部楼层
孙大师 发表于 2019-5-28 18:557 K! Q: {6 k* Y( c% P
非常好,楼主是技术帝,到目前我都还没开发fc的无线套件,等空了,开发一套套件,等玩家自己组装。 ...

) x0 C) v. N7 |- w* U4 t# L能得到孙大师的赞誉,不胜荣幸!3 U( }$ `# F) F- ^) ~
不如开发一个多功能手柄,比如用SFC手柄改造,L/R键配合其他组合键可以用来切换2P~4P、调节连发速度、软重启等各种功能。接收端插到15PIN扩展口。
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则

小黑屋|手机版|Archiver|Video Game Do It Yourself ( 闽ICP备14000865号 )

GMT+8, 2024-5-9 07:57 , Processed in 0.066580 second(s), 14 queries .

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

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