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

 找回密码
 注册

QQ登录

只需一步,快速开始

查看: 14594|回复: 27

自制FC无线手柄

  [复制链接]
发表于 2019-5-22 14:16:45 | 显示全部楼层 |阅读模式
本帖最后由 雷精灵2046 于 2019-6-14 09:28 编辑 & D# u' v: ?3 C  t9 W

$ `3 C) H0 X: F6 G没有用复杂的分立元件搭建发射接收电路,直接用的现成的2.4G无线模块jdy-40。
: [, t& U( F9 F, e3 e
3 E% ]9 u3 U- i: r( h+ h5 Z% l/ z, V8 X
发射端靠3.7V锂电池供电,用了一片SOP8封装的STC单片机,负责产生连发脉冲,同时负责检测电池电量,电压低于3V左右的时候触发低压中断,低压指示LED就会亮起来告知该充电了。平时发射模块和单片机均处于睡眠状态,有按键按下才会唤醒,从而实现省电。实测睡眠状态下整机电流约1~2uA。板子洗了一下稍微干净了一点。因为对于微功耗设备来说,焊接残余的助焊剂可能会增加漏电流。/ v& M7 b; z9 m
& F" |! Q- t. y
买了一个火花的FC山寨手柄,去掉里面的牛屎板子,并修正一下塑料挡板,把锂电池和充电模块装进去。! j1 M. s8 u3 s
为了减少体积,充电模块裁剪得十分小,并且更换了充电电阻使之适应这个小小的锂电池。这么小容量的电池,也不需要多么大的充电电流是吧?# Q& d# X* C/ X1 J, }  F
然后统统用热熔胶粘上。充电电流比较小,所以发热很少,不会熔化热熔胶。2 z' \7 ?$ O  h+ B# I) g" z& L

: N) t- \% f/ w; Z- h
7 @* W% a. }) w3 q3 j* G' I+ D. o* _1 _5 @
最后把按键、导电橡胶和电路板装上去。$ F' J# Y, E1 [5 k0 b/ w0 }
精心裁剪了电路板,正好扣上,不会阻碍其他元件,也不会影响后盖和拧螺丝。+ {7 ?" @  m5 D3 r8 R

' g1 n2 x7 [  c" {
' r6 B( E0 \! C, m完工!$ o- I% _0 W1 @6 V. e) J

9 b, B6 {# n$ M& y9 r6 U
& Z/ I3 v( m' B# }$ o* b  l2 b/ m/ ~这是充电的MicroUSB插座。旁边的小孔用于透出低压报警LED的光线。! J3 T. o  \# H. E( e# Z
4 i8 H" P4 l5 N9 A: e( }4 l
# a: p& r5 Z- V5 B. `9 C
接收端用一片DIP16封装的STC单片机模拟CD4021。为啥要用单片机模拟而不是直接用CD4021?因为jdy-40模块接收端在有按键按下的时候输出高电平,无按键按下输出低电平,和普通手柄正好相反。当然我也可以用两片74HC00或者74HC04之类的逻辑门进行反相,但那就增加了芯片的数量。对于FC手柄这种工作频率并不高的设备来说,STC单片机完全可以胜任模拟工作。! o- Y# z5 ]% `8 T  S
8 {5 K+ t4 d$ k8 x2 ]
! D; P$ U0 g* C2 s9 _" E
8 ?+ s& f7 }2 X6 q7 e: K
电路设计有点小小的错误,所以有几根飞线。原本设计使用低压差LDO是XC6206,结果在做这个接收模块的时候,买的LDO居然找不到了!无奈只好用了AMS1117。幸好对于接收模块来说是5V降到3.3V,1117可以胜任。要是发射端手柄的话,3.7V降到3.3V,那就非得用6206不可了。/ L* n5 K: e3 j1 e( T
% J6 \1 w7 u" \  e
实测十分灵敏,延迟极小几乎感觉不出来。可惜这山寨手柄的手感并不佳,尤其是方向键,软塌塌的。看来我得买个剪线手柄改装。! _1 d: e5 D$ M" `# E: r1 l7 A

6 t% n, r/ H7 Z. s' S5 Y8 r" y0 `0 k这是电路图,有兴趣的朋友可以参考。2 b& ?1 T; p6 r( @/ E& W9 h3 k  v

$ B' A. I8 c' U8 G+ h0 W4 g- m/ k+ |" u1 }# A, V$ d! o2 G* S
我信奉开源主义,十分痛恨把技术藏着掖着。好东西大家分享嘛!所以两个单片机的源代码大公开!
- \% t9 y; }; w& g, ~3 k6 c编译器:Keil 51。+ ~' ?8 D7 z% d& X
$ w% u; ?  ^2 y3 V
发射端:: r- U" H5 o; i, X, o% c- O
  1. #include <INTRINS.H>
    - p  Z# X2 L8 a
  2. #include "STC15W.h"& U! Z+ _3 C  \/ Z/ b0 D3 H
  3. - t( }& J2 w! y  L

  4. ( M, p' I8 Z5 Z8 y  h
  5. /*
    7 M/ q2 Y# q) X+ e
  6. --------------------------
    # U0 I+ y* p/ e/ V( I
  7. |1 (OUT)        \__/   (INT1) 8|  @1 z, W& ^* m
  8. |                                                   |. S; O% P! P6 P- H( I3 i/ p3 i
  9. |2 (VCC)                   (INT0) 7|: N0 y( b- H! w* Z' ^8 H3 E1 b
  10. |                 STC15W204S                   |
    9 T2 _! e' ]' C5 O9 h7 A/ d
  11. |3 (LED)                         (TXD) 6|
    , B7 z  y8 h3 {/ d4 i
  12. |                                                   |# ?0 m% i4 V* g* w, L9 [
  13. |4 (GND)                         (RXD) 5|; o( B0 }' A+ A5 O' ~  j4 V8 c
  14. --------------------------+ ~# Z6 ?+ E& X) \: ~: O. K+ |
  15. % l  q/ U3 \. r* a$ z
  16. LED ---|<|---[===]--- VCC' x, j' e* _3 t* z
  17.            Red          330
    " n6 {# H- A0 S7 X

  18. $ m% I: V* w7 g( \- W2 _6 q
  19. Fosc = 6MHz% @* {) {3 }: A4 ?3 E6 ?/ O  O
  20. */
    7 O8 w* z* o, j: R8 M
  21. 1 Y5 J" p  \& e7 I5 I4 S7 V

  22. " z% S7 Z, I) {( l- I: Z* D# q9 [
  23. // 矩形波输出脚$ H- J2 U- I2 w, S& U
  24. sbit OUT = P5^4;
    ( D+ _# [$ L) L( Z" S' |& a9 P
  25. // 低压指示灯引脚& {: m. X3 T0 \4 Y) C/ N
  26. sbit LED = P5^5;4 z( w5 V3 |* O7 F$ H
  27. 3 [+ W, ]) i0 P6 E
  28. // 停机标志位
    $ \* [. u* l- Z3 e: `  k( G
  29. bit isReadyToHalt = 0;% P( O; |/ k- c9 f+ k6 }* q

  30. - O& k6 J( T# _' o
  31. // 矩形波次数累计# Y  O, _6 n: p
  32. static volatile unsigned char count = 0;: m; x" t: A& l1 n# i* e

  33. * s+ D$ B# l0 F; x: c

  34. : t( y, L* b2 m; u; }" w2 H
  35. static void GPIO_Init(){( P% i" [" |% ^, e7 `# j# Y
  36.         // P3口设置为准双向,默认靠内部弱上拉输出高电平8 i0 N# g- Y( c4 @
  37.         P3M0 = 0;
    . y4 N5 B+ Y7 }# u  t& H4 ^5 b1 ?
  38.         P3M1 = 0;
    * D6 H# Z  Y& i% p
  39.         P3 = 0xFF;0 x4 D# y5 Z9 T5 @/ _7 E# y
  40.         // P5口设置为准双向,默认靠内部弱上拉输出高电平
    1 G1 L6 O& P- q/ y! i
  41.         P5M0 = 0;' d, K6 F3 M) I
  42.         P5M1 = 0;
    5 Q) P" l3 U( h6 q5 y7 r: z* [
  43.         P5 = 0xFF;
      _/ p: T, u1 T
  44. }
    . c% s9 |- ^2 K: Y  R) Z3 S
  45. 9 L7 }* O1 \! a1 X
  46. static void Timer0_Init(){1 N: J' |& K' i: j* G' D  s6 V
  47.         // 16毫秒@6.000MHz" [# e  q- m& f3 E# C4 e) v
  48.         AUXR &= 0x7F;        // 定时器时钟12T模式* |& W  \/ n4 M5 D8 e1 }- {
  49.         TMOD &= 0xF0;        // 设置定时器模式6 v& T0 ^: E- n  e; b/ T' u8 K
  50.         TL0 = 0xC0;                // 设置定时初值
    - d0 A0 G; U6 r( I0 I& i0 E3 E
  51.         TH0 = 0xE0;                // 设置定时初值# s+ C% a2 G2 f! G3 Z* [+ _
  52.         TF0 = 0;                // 清除TF0标志" O  k$ W- w: f) `
  53.         TR0 = 1;                // 定时器0开始计时5 u* `2 @8 r% U& v& C
  54. }& G6 e% B5 x! r& W9 S* ]
  55. ( r/ Z7 p8 ?) P1 t2 M, u
  56. static void Interrupt_Init(){
    , ~2 @" f$ t2 v. ]5 S
  57.         // INT0中断触发类型为下降沿触发
    / \! g/ \0 E. j0 R
  58.         IT0 = 1;
    + M1 A, M! R! I# E
  59.         // 允许INT0中断
    $ R2 E, l2 X/ y9 [5 Z% S
  60.         EX0 = 1;. T# Y) h4 w% g0 d
  61.         // INT1中断触发类型为下降沿触发
    / v, w: A# c+ E5 y
  62.         IT1 = 1;- @1 X9 ^* i, C! _7 ]4 [" o
  63.         // 允许INT1中断. s3 }$ m; M- P6 n
  64.         EX1 = 1;
    " J5 L, F" S+ Q, H5 l% @; Q: b, X- b( b
  65.         // 允许定时器0中断
    7 ]9 S, o0 X& l: e
  66.         ET0 = 1;6 p! w$ |9 I  O) Q6 Z! b
  67.         // 允许全局中断
    7 W9 ~+ d8 h6 r1 M6 o
  68.         EA = 1;% z6 A, {2 }, G
  69. }
    ; s- h3 `) g1 q6 a

  70. & j, b3 z) Z( U1 y9 ~% ]
  71. static void INT0_Isr() interrupt 0{
    ! {2 D2 v- S' F# }4 V2 v' D
  72.         // 矩形波次数累计归零
    . {& @  a$ n% k; u
  73.         count = 0;
    , J+ A& N0 q8 W: J
  74.         // 重开定时器0中断
    - {6 g6 F# @, m+ [8 Z5 p3 E
  75.         ET0 = 1;1 W" I# n0 k  r. l' K
  76. }
    * i- `( s# M$ F4 c. W% B; ^
  77. 0 `! V+ g9 k# M/ v" W; N% `  j+ J
  78. static void Timer0_Isr() interrupt 1{  B. j5 W4 C+ o, E$ z
  79.         // 输出矩形波
    9 A8 ~- T# X% {) f4 W: b
  80.         OUT = ~OUT;
    ) r1 D! z" i, W- b( @1 K+ O
  81.         // 累计矩形波次数& W. D2 j% Q2 J) W
  82.         count++;; F1 P+ M3 E% {
  83.         // 超过250个矩形波,准备停机
    * p/ o+ L8 o% v  |% D
  84.         if(count > 250){# A7 E# ~. {8 i" e4 N( o* @1 b3 G1 |
  85.                 count = 0;
    , a9 L4 M5 e% F& J1 B
  86.                 isReadyToHalt = 1;
    2 k5 |# B4 j& [( L: Y4 k
  87.         }
    0 T* ?* j% ?2 ]
  88. }& k& ^1 u% o: }* ?- A
  89. 0 k: I, `' n+ A9 O1 {
  90. static void INT1_Isr() interrupt 2{
    ! G+ L# q5 A- s' z1 K4 U
  91.         // 矩形波次数累计归零8 K4 G0 H: n: p3 i- |5 n4 G+ }( d
  92.         count = 0;3 y4 a8 K: Z- H) R7 ]" j1 V
  93.         // 重开定时器0中断8 n6 r0 ]+ {9 j- {9 Y
  94.         ET0 = 1;
    % ~' O4 n4 S" |9 X) n
  95. }
    : ]: i3 v( _  b3 J- J- N8 I+ a& e) C

  96. ' e5 D' S& H5 A8 _# {

  97. 1 }1 e! a8 r# J7 Y# T% L. d
  98. void main(){7 U: x2 f5 X: K8 b/ _! R  }
  99.         // 初始化P3和P5口
    ' e/ M% I  |, `
  100.         GPIO_Init();
    ! \5 S, ?2 Y6 N; x% y) ]
  101.         // 初始化定时器00 c7 v# L  o- K
  102.         Timer0_Init();! ?* a8 V% J& ^) U6 ]
  103.         // 初始化中断
    8 f- S+ b8 s1 u; D9 {9 R
  104.         Interrupt_Init();
    - N2 `# @  q& ?
  105.         * J; ^7 ?, T2 t
  106.         while(1){2 `7 ?0 g; \  e' m; U8 d8 V
  107.                 // 检测电量
    : ?' H$ E( w- j
  108.                 if(PCON & (1 << 5)){
    ' c8 Z+ E: k1 J6 L
  109.                         // 如果电量低,低压指示灯亮
    / h3 F! [8 r/ `, d. D' G
  110.                         LED = 0;" l; c! W8 ]  r0 ~, h/ @
  111.                         // 清电量检测硬件标志位
      N0 R) z" H4 Z6 `, u- x
  112.                         PCON &= ~(1 << 5);
    ( W5 ]7 D6 q+ o  |4 q
  113.                 }else{
    4 @. v) I! u* h8 m$ |% ^7 x
  114.                         // 电量正常,低压指示灯灭
      `6 e& m$ J1 I
  115.                         LED = 1;9 n, F7 k/ G  C
  116.                 }
    7 G- V3 |) a4 Q# ^# i

  117. 4 k4 M2 G; M: Y% L* A* h
  118.                 // 检测到停机标志- z7 k5 z( J3 C1 Z; ^, B; T; H% T# X# @
  119.                 if(isReadyToHalt == 1){! }( ]! V9 b" \9 s
  120.                         // 暂时关闭定时器0中断, ~# X5 m& P3 ]$ ?
  121.                         ET0 = 0;
    % i4 J7 e, e9 X4 ]4 I  U* ~1 }8 L
  122.                         // 停机之前先把矩形波输出脚置低电平,以方便INT0和INT1唤醒CPU, a" d: r4 r- z; F3 F& `# I9 S
  123.                         OUT = 0;
    6 r: t, S7 C4 O) T0 n! _
  124.                         // 停机之前先把低压指示灯灭掉,以省电$ z' x" l" i! I/ N% R9 |4 x. F2 r
  125.                         LED = 1;
    - F6 D5 m# r" E7 ]
  126.                         // 进入停机模式0 A0 }3 u# {+ _7 q; V* t; v/ [& W
  127.                         PCON |= 0x02;+ G1 _3 W1 o5 H' _' c# S* ?
  128.                         _nop_();
    % u' `6 n, o/ R$ Q0 Y
  129.                         _nop_();
    4 e1 b& k0 {  S) a, K" P
  130.                         _nop_();
    - I7 l6 _+ h* w) g$ G( i
  131.                         _nop_();
    * d- L) G, N5 S3 U9 ?& ], P
  132.                         // 唤醒,清标志位7 @/ O" D1 v9 s
  133.                         isReadyToHalt = 0;( [4 {* O  M/ U' ]  G2 e$ w- |5 p
  134.                         // 重开定时器0中断: o! p+ M2 Y$ q8 ?$ F8 w
  135.                         ET0 = 1;$ f; i0 {5 [3 ~8 @9 O% R4 `
  136.                 }4 h+ y0 J# S" x, c6 c
  137.         }6 k9 }' `9 O1 y  _2 h- ~* a& ]
  138. }
    + L3 m% I2 p  B4 r3 ?% M' J" @# R
复制代码
9 K3 X  [' N6 x5 K7 \% U
硬件参数配置:
+ m; y. ?! i" Z8 M% o9 c" K: ]9 N5 L1 J6 R! m( C( T+ @
2 n) L5 `( s: c' |: F
接收端:
. c5 A6 L4 B8 n- u  ]! ?
  1. #include <INTRINS.H>
    + e8 C4 ]/ W$ S+ ~# g* Q. s8 [4 ]) Z
  2. #include "STC15W.h"
    & J% z* T2 w* Z# ]
  3. " y8 v( `1 s, M: K  a

  4. , w- I: G1 v) S0 q8 ]
  5. /*
    6 |1 e: z6 T8 e

  6. - n" a) L, X' I( o% L9 h
  7. *---------------------------*
    + _9 z8 f2 W0 [; b4 @' w+ \
  8. |1 (GPIO2)         \__/  (GPIO1)16|
    4 {# K( \; U6 u* a6 E  @  M
  9. |                                                        |3 c- ~" W0 @: F. Q6 P3 c
  10. |2 (GPIO3)                   (GPIO0)15|
    , o6 X5 h8 O( }6 c4 E  j
  11. |                                                        |* W7 l7 N% n: F4 s1 R
  12. |3 (GPIO4)                                  14|
    ) t) c2 A/ `" I* q  W& c8 U: J2 K
  13. |                                                        |
    " B" O+ s; T& [0 Y5 c2 y
  14. |4 (GPIO5)                        (DATA)13|" g" L3 T/ i9 v5 r8 z1 t; G' ]
  15. |                  STC15W204S                |
    7 i' N/ h/ t  T" R3 H( @* c
  16. |5 (GPIO6)                   (LATCH)12|
    # C5 r: K( @& |* q/ \3 t$ h6 l
  17. |                                                        |
    % \  M2 J% L& ]! K& F
  18. |6 (VCC)                         (CLK)11|* N" q; x7 {8 q0 z5 P3 `
  19. |                                                          |$ }& `! ]9 \+ i- h5 Y: q
  20. |7 (GPIO7)                         (TXD)10|
    5 j8 k" \# Y! f  o( q% {
  21. |                                                        |( M9 q2 d" [, I8 Z  l  `
  22. |8 (GND)                         (RXD) 9|$ t" e  W* {+ Q% v/ b
  23. *---------------------------*. e9 S" R4 |' Y; H
  24. Fosc = 12MHz0 F( M; U3 N9 a2 \3 d

  25. . l% N; s/ w% C3 N- W& g+ ~
  26. P1.0 -> 上
    3 J& Q% j9 U& H% a* O1 o' p) ?/ e
  27. P1.1 -> 左
    & M4 v* g8 p: w  V
  28. P1.2 -> 下
    / t; ^  `$ f1 m2 C
  29. P1.3 -> 右
    $ z/ ]. E) t' w, |  C3 f9 i
  30. P1.4 -> SEL
    3 ^8 \7 W! y# @/ {
  31. P1.5 -> STA) w7 _1 z" P% N' P. ~! ], W
  32. P5.4 -> B
    & h# {' D1 N4 _1 H& ~+ i
  33. P5.5 -> A) l3 i7 Y9 }2 U) `; t( M, K8 M2 D& O- c

  34. 3 M& r+ U; O2 _, h8 k
  35. */
    & Q) g; B: `$ n: K1 N3 H

  36. . C+ P6 G$ m, H9 U0 S( b% S
  37. 7 S* t( m; M( m" ^2 U( _. A  _3 E6 g
  38. sbit CLK        = P3^2;1 a4 T# d8 y) p' }4 \& L
  39. sbit LATCH        = P3^3;
    4 S/ W+ L+ X7 L3 W3 _
  40. sbit DATA        = P3^6;
      L2 {* ?  b3 E! O" M( o, E5 R

  41. 4 _* a0 t4 D) }  u' @7 Q: v; ^
  42. bit isReady = 0;
    6 W* \( _9 Q- W  S/ G* \; H
  43. static unsigned char key = 0;) S4 ^2 K3 N4 Q* J! Z5 O1 l; i
  44. static unsigned char buf = 0;        // 双缓冲。这个缓冲区保存从P1和P5组合而来的键值
    5 u3 R6 s2 d( d% E$ Z: Y; v( E
  45. static unsigned char bufReady = 0;        // 双缓冲。这个缓冲区保存上面那个缓冲区的备份+ h2 t0 j7 H/ ]
  46. static const unsigned char data mask[] = {0x80, 0x40, 0x10, 0x20, 0x01, 0x04, 0x02, 0x08};        // A B SELECT START UP DOWN LEFT RIGHT。为提升速度,这个表放到RAM中7 J6 b% O8 n" m% Z' g% ~; J
  47. static unsigned char idx = 0;8 c- `( ~# |! P8 q( E
  48. : Q) y" h/ R2 U2 M
  49. 6 h3 P  @# ?% v! a  q) V
  50. static void GPIO_Init(){* P% m" D; z; o$ s& w( x
  51.         // P1口和P5口用于接收并行信号,全部初始化为准双向,依靠内部弱上拉输出高电平, S# i/ E+ b- g$ T2 A9 Y7 n
  52.         P1M0 = 0;9 M4 C* R3 {: e# N2 h9 J
  53.         P1M1 = 0;. j* m* L/ {" G. @1 a% z
  54.         P1= 0xFF;0 j, R; l& }3 F9 O2 O
  55.         P5M0 = 0;4 K% R) m; @' F* k2 U
  56.         P5M1 = 0;
    9 t* T% Z- D; s
  57.         P5= 0xFF;. Q' \$ X; G' U4 a' [
  58.         // P3口初始化为准双向
    9 d. ?4 F6 H. A" r
  59.         P3M0 = 0;# e0 i* z5 t; ?& O
  60.         P3M1 = 0;  y7 {" H* A; G+ x1 d. N
  61.         P3 = 0xFF;+ {8 z) P# T% M  ]9 ]
  62. }
    + v& E4 i' C6 C

  63. . r1 o7 S6 c+ A/ _4 C
  64. static void Interrupt_Init(){. o  G; k4 e5 ?1 W4 @1 b
  65.         // INT0中断(CLK)触发类型为上升沿+下降沿
    : w3 E! K/ `! X1 [2 j. r9 J
  66.         IT0 = 0;
    , [8 B. U$ N$ ^  y
  67.         // 允许INT0中断
    5 `" V5 f. z" J6 Q/ E. y
  68.         EX0 = 1;; j* D  x* j& {0 a
  69.         // INT1中断(LATCH)触发类型为上升沿+下降沿
    ) l8 S0 G: f# E7 o  r+ e' s
  70.         IT1 = 0;
    0 R! M3 P) D' x' y2 o! _# k9 }
  71.         // 允许INT1中断
    9 h" S0 P; [  j  R
  72.         EX1 = 1;# j( p+ i9 X7 t+ M
  73.         // 开启全局中断3 M. ?3 Y) M. ]8 {
  74.         EA = 1;7 l6 {4 b8 a. d. m6 {4 m3 X
  75. }
    " X2 C# J# W+ v8 d( F9 V
  76. & p  w: \9 y' Z! K( H
  77. static void INT0_Isr() interrupt 0{1 r  I1 Q. k4 [8 q6 v9 V
  78.         // 只有已经成功锁存才允许CLK移位# U2 L/ C2 y+ B: J8 S7 B+ K  J
  79.         if(isReady == 0)$ w) B6 l6 `1 Z' a- ?
  80.                 return;
    2 H3 J6 ?: l: Q
  81.         // 读当前引脚电平,如果是低电平则说明是下降沿,此时直接忽略该中断# E' Q& G2 F: P. z
  82.         if(CLK == 0)  y! |) z5 l7 Q6 A0 {& [7 g
  83.                 return;9 ^/ R' Z: N$ L7 [3 o7 R9 `( O$ z* H
  84.         // CLK上升沿到来的时候,取锁存值的下一位输出$ `* t2 Q4 ]" m; D
  85.         idx++;
    ' G/ [' ^+ Z8 P. d0 f+ O
  86.         DATA = key & mask[idx];
    ! G6 o9 h: E% ~3 n
  87.         // 如果已经完成7次移位,则一轮读取完成& S' R' F8 e5 B: ]' f
  88.         if(idx >= 7)
    9 j& z* [  l4 v; M; O! }  G: T2 z
  89.                 isReady = 0;
    8 ^0 \4 s  c6 C
  90. }
    # f8 @7 m( E0 {# d8 d& i
  91. ' H- ]0 O, |9 ~7 y* i
  92. static void INT1_Isr() interrupt 2{
    3 k" U8 U6 o0 @" k* F+ }5 \
  93.         // 读当前引脚电平,如果是低电平则说明是下降沿,此时直接忽略该中断' b1 N* ?/ G# O4 q# P
  94.         if(LATCH == 0)  W7 c! I" N* p! T
  95.                 return;
    4 E) N& g8 V& n" O
  96.         // 当LATCH上升沿到来的时候,锁存所有按键状态,同时把键值A输出到DATA
    % i4 i* H+ v2 M
  97.         key = bufReady;
    2 J7 n7 s+ c" m
  98.         DATA = key & 0x80;//mask[0];        // 为了加速运算,直接取表中的值而不是读表, r! R" c4 V" t- O5 s
  99.         idx = 0;
    . u- L; t1 b" V% O8 c" z
  100.         // 允许CLK进行移位+ G: q9 R0 Y4 ?, l  I; Z! X% d
  101.         isReady = 1;
    5 q& p& m5 Q% D, t% D
  102. }
    8 A2 D) U' X  ^/ q) w% |( n
  103. 2 E1 C8 ?/ j0 D1 s! d2 @
  104. void main(){3 c( Y) ~1 M8 C1 V" H
  105.         GPIO_Init();  q6 p/ r" B2 Y
  106.         Interrupt_Init();: h4 _1 W2 ^& e; q5 ~* L" _( p
  107.         ; k) x8 n: q# V* ^& r) H
  108.         while(1){
    0 @; J) M+ T9 w3 e
  109.                 //PCON |= 0x01;        // 进入省电模式, c+ [' N6 u/ ]3 N2 G; `( a1 K! y4 Z
  110.                 //_nop_();
    ( F1 \4 c: F- v* K% F
  111.                 //_nop_();
    . u3 {; e! z' s
  112.                 //_nop_();
    0 L# G9 Q, E5 T  M, _; a( N: u
  113.                 //_nop_();9 a7 n0 v0 [$ B, d/ ]
  114.                 buf = ~((P1 & 0x3F) | ((P5 << 2) & 0xC0));, z" y) ?9 ?" Q& H4 s  L2 I& H
  115.                 bufReady = buf;( R: z$ i, d4 e% k/ d
  116.         }5 h+ Q, s$ A- r
  117. }( p' T  A1 p1 ]( o+ p
复制代码

4 `' a* ]9 B* F1 a/ {* n硬件参数配置无特殊要求,晶振频率选择12M即可。
  n) E7 w2 _0 R1 L3 j$ F! n9 f! l& r- T- \0 _
这是编译好的固件。

本帖子中包含更多资源

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

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
8 y1 L! v8 s8 q$ S不错的设计,想问一下楼主,FC的15针公头怎么解决?普通的公头太短了,插不进去FC的扩展接口。 ...
! k& S% s7 V$ v$ T7 m4 Z
坛友的改造方案
回复

使用道具 举报

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

使用道具 举报

发表于 2019-5-25 12:07:18 | 显示全部楼层
精彩,楼主动手强,也写得很详细。1 H4 t2 P: F. J( z9 c
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
+ b: ?' n5 c; I6 w9 l. {' e$ @精彩,楼主动手强,也写得很详细。
' n0 z$ S; I4 u  J  q/ N7 i1 Q2.4G方案是目前无线的最低延迟吗?
5 A' A4 K9 v0 d4 {( V
我没用过其他无线手柄,所以实在不知道我自己做的这个手柄到底是不是最低延迟。8 ?$ j  A/ W2 V- g1 Y, a7 `6 b' e  V
不过根据网上的说法,延迟高低主要是由通信协议的复杂程度,以及数据传输速率决定的。这个模块虽然是2.4G无线模块,但由于协议很简单,所以延迟比较低。4 J* O! R" u& \: v* J6 i5 l
我用这个手柄玩一些ACT游戏,比如超级马里奥、忍者龙剑传、热血系列,完全感觉不到延迟,和游戏机自带的手柄没有任何区别。唯一的区别就是这个手柄是用火花山寨手柄改造的,外壳是垃圾回收塑料,粗糙+脆弱,导电橡胶弹性不佳,手感不是一般的差。
8 h5 T) ^# K! N2 t! q1 B我手里还有十几张板子,等我有空了我再做一套,到时候买一个好一点的手柄改造。
回复

使用道具 举报

 楼主| 发表于 2019-5-29 16:56:14 | 显示全部楼层
ppad 发表于 2019-5-28 17:27
3 r) |9 |  E9 e- e给技术帝赞一个,有半成品发布吗,自己焊接改造就可以,编程实在不会啊 ...
" L8 p2 m  |' }. \) J
很可惜,我手里没有多余的单片机了,LDO也找不到了,锂电池以及充电模块更是没有了。反正就是该用到的元件基本都没了,所以没法发布半成品。1 k0 z9 \. k3 u9 g8 j! |" h
两个板子倒是有十几张剩余。# l  |2 c! L& ^8 A
你要是有USB转TTL串口板,完全可以自己买这两种单片机,然后我给你编译好的固件,你自己用串口板下载到单片机里面就行了。两个2.4G无线模块也得通过串口板用AT命令设置参数,不过好在我在设计电路的时候就已经预留好了串口,可以直接在线下载和在线设置参数。总的来说并不麻烦。
回复

使用道具 举报

 楼主| 发表于 2019-5-29 17:00:34 | 显示全部楼层
孙大师 发表于 2019-5-28 18:55
5 [. m, q! b+ l! t( A非常好,楼主是技术帝,到目前我都还没开发fc的无线套件,等空了,开发一套套件,等玩家自己组装。 ...
' m6 Q( \1 ~! S
能得到孙大师的赞誉,不胜荣幸!3 Y3 @( G  W: @" r" J, s
不如开发一个多功能手柄,比如用SFC手柄改造,L/R键配合其他组合键可以用来切换2P~4P、调节连发速度、软重启等各种功能。接收端插到15PIN扩展口。
回复

使用道具 举报

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

本版积分规则

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

GMT+8, 2024-4-20 17:36 , Processed in 0.055787 second(s), 14 queries .

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

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