找回密码
 注册

QQ登录

只需一步,快速开始

查看: 23667|回复: 28

自制FC无线手柄

  [复制链接]
发表于 2019-5-22 14:16:45 | 显示全部楼层 |阅读模式
本帖最后由 雷精灵2046 于 2019-6-14 09:28 编辑
, D7 P; _( l/ z* m3 F( [/ y# }
+ V5 ]2 I1 {# F1 c$ x# T3 i没有用复杂的分立元件搭建发射接收电路,直接用的现成的2.4G无线模块jdy-40。
* w4 M0 E4 J, z& T( t0 r. H
# o  g, I/ {6 S0 o9 K2 `3 T6 J: I, ?2 g, q
发射端靠3.7V锂电池供电,用了一片SOP8封装的STC单片机,负责产生连发脉冲,同时负责检测电池电量,电压低于3V左右的时候触发低压中断,低压指示LED就会亮起来告知该充电了。平时发射模块和单片机均处于睡眠状态,有按键按下才会唤醒,从而实现省电。实测睡眠状态下整机电流约1~2uA。板子洗了一下稍微干净了一点。因为对于微功耗设备来说,焊接残余的助焊剂可能会增加漏电流。
4 P  I: e" i  y; ?
: s( K9 X) l( i9 g+ C" v买了一个火花的FC山寨手柄,去掉里面的牛屎板子,并修正一下塑料挡板,把锂电池和充电模块装进去。
8 z- @9 D' a! C0 k7 t为了减少体积,充电模块裁剪得十分小,并且更换了充电电阻使之适应这个小小的锂电池。这么小容量的电池,也不需要多么大的充电电流是吧?
" O6 V3 ~* d( p然后统统用热熔胶粘上。充电电流比较小,所以发热很少,不会熔化热熔胶。
& l  F6 {! e2 B
) n8 j5 ?* s  A% O! W2 W8 z4 w5 R- b- F& R

$ W! d/ J& J6 ^# t最后把按键、导电橡胶和电路板装上去。, q4 x; C. `+ ]4 s- R5 P
精心裁剪了电路板,正好扣上,不会阻碍其他元件,也不会影响后盖和拧螺丝。
! Q* x) p; B8 m# w3 F
. F/ F/ E# i" n# a. }# V5 Y3 a: D0 N$ j9 I! B
完工!
! }2 p! V. D* m. y* \; p  u& M
' u3 {2 |+ f% o. P2 ~4 ~4 }* Z: Q* }; t  |" i7 V! z! C' O& s
这是充电的MicroUSB插座。旁边的小孔用于透出低压报警LED的光线。2 u+ s6 D& }( a
! E7 R. ~- Q* X7 K4 [+ u6 Z$ g

; E( y5 t; C' w! g接收端用一片DIP16封装的STC单片机模拟CD4021。为啥要用单片机模拟而不是直接用CD4021?因为jdy-40模块接收端在有按键按下的时候输出高电平,无按键按下输出低电平,和普通手柄正好相反。当然我也可以用两片74HC00或者74HC04之类的逻辑门进行反相,但那就增加了芯片的数量。对于FC手柄这种工作频率并不高的设备来说,STC单片机完全可以胜任模拟工作。* k. L5 G3 m/ `- d

4 q0 ~) S" }  S/ B' i' b2 G  v" r; o$ l  l; u' `

& w; v  \3 z6 j2 `电路设计有点小小的错误,所以有几根飞线。原本设计使用低压差LDO是XC6206,结果在做这个接收模块的时候,买的LDO居然找不到了!无奈只好用了AMS1117。幸好对于接收模块来说是5V降到3.3V,1117可以胜任。要是发射端手柄的话,3.7V降到3.3V,那就非得用6206不可了。& w0 t/ C, a7 s" n
1 l% l: `* W, R$ @: |. f
实测十分灵敏,延迟极小几乎感觉不出来。可惜这山寨手柄的手感并不佳,尤其是方向键,软塌塌的。看来我得买个剪线手柄改装。
. c6 U5 n* K: x5 q: U1 R3 f7 s; K" `( O" k8 l8 W: m
这是电路图,有兴趣的朋友可以参考。' {' z9 @/ K9 {- Z& S* x

6 j8 |+ q; ?2 W4 j0 y+ t" N1 g3 \# h) d1 T$ t# ]1 q- R( p
我信奉开源主义,十分痛恨把技术藏着掖着。好东西大家分享嘛!所以两个单片机的源代码大公开!3 T! H9 d! t" \
编译器:Keil 51。, V( L: s2 ?1 E" n: I

% _, B/ r3 z0 c发射端:" z. h! r; i0 ^
  1. #include <INTRINS.H>3 E: a; n- E; P" _8 Q# S
  2. #include "STC15W.h"0 I8 S* W4 g- B: d4 E* I

  3. 9 Z1 p9 X8 Y) `" O+ _2 K* o
  4. " r$ E0 z- o+ D( W) O
  5. /** n& }* M' _6 c5 X
  6. --------------------------- b8 {: x9 D0 g1 F6 o
  7. |1 (OUT)        \__/   (INT1) 8|9 l0 U5 f8 l. ^6 v: f
  8. |                                                   |( O- H( [- n7 m
  9. |2 (VCC)                   (INT0) 7|; @# B: T. V: T2 d" }5 O2 }
  10. |                 STC15W204S                   |  d& p* w6 [2 J, ?! i
  11. |3 (LED)                         (TXD) 6|5 l9 i' L- D+ o- A+ X
  12. |                                                   |# f  L1 ]! }8 Y
  13. |4 (GND)                         (RXD) 5|
    $ v3 v& r; b) D- ~/ C* Z
  14. --------------------------
    + Q3 ^: |, M+ C
  15. . j) C4 e! l9 d& T% M( d
  16. LED ---|<|---[===]--- VCC- q- Y2 n) K# W/ p( H
  17.            Red          330
    8 w9 v# _* A8 b6 z! A
  18. 2 j4 _, P8 ^  o; C4 A+ [. ?$ O
  19. Fosc = 6MHz
    8 }1 o% w/ K" f4 O" H8 d8 q
  20. */# f1 }4 A3 I% ]7 p* J1 e+ A3 _5 [

  21. 8 R- C' ^+ k, w. v  T

  22. . h1 a" Z& @, h9 Q4 q( e
  23. // 矩形波输出脚
    9 X. |1 V3 G0 e9 p, N# s8 i  @) ^7 n
  24. sbit OUT = P5^4;
    2 N4 V6 U) G% ]
  25. // 低压指示灯引脚
    6 ^* l8 S- C( [& V- O
  26. sbit LED = P5^5;! U0 p3 @0 Y# X  t$ S2 W9 ~
  27. ) z' \) N6 V  h2 r6 _  W% y
  28. // 停机标志位/ c7 N! ^5 @8 K$ z% J% v* Z
  29. bit isReadyToHalt = 0;9 l/ Q3 D9 G( X1 s7 h

  30. 2 H, J: \$ D. v
  31. // 矩形波次数累计& e. H# z6 g5 H- [  q- A8 n
  32. static volatile unsigned char count = 0;" \" ^& p6 h3 N0 V8 T, f& X
  33. 7 T- J% S; |$ q

  34. 2 O6 b( B: N! |8 X7 x" `7 B1 V
  35. static void GPIO_Init(){
    3 y1 G/ Q  \- X7 ~5 c
  36.         // P3口设置为准双向,默认靠内部弱上拉输出高电平
    + z2 t9 W+ U4 k3 |7 E
  37.         P3M0 = 0;
    4 N6 u! k  ^* }9 p3 F
  38.         P3M1 = 0;# v3 \8 ^2 M  p. M2 P3 M2 k6 h
  39.         P3 = 0xFF;" S. F5 c; m. [
  40.         // P5口设置为准双向,默认靠内部弱上拉输出高电平* o% V# W: N# v$ C" a
  41.         P5M0 = 0;
    ) N' p+ R% n( m6 E9 C& @$ E
  42.         P5M1 = 0;) B+ P9 {& r/ [; w8 h' d
  43.         P5 = 0xFF;
    2 g5 F. ^3 e- v8 O  Q
  44. }
    4 I3 v+ F9 y, c% @9 g

  45. 1 L, F+ I8 s/ p9 J5 ?# i* R
  46. static void Timer0_Init(){
    8 l3 }: S3 b" D& I! k" f# |% ~
  47.         // 16毫秒@6.000MHz6 W! R! ?# x$ c% Y, q! M
  48.         AUXR &= 0x7F;        // 定时器时钟12T模式! f) g1 ^3 p! t; v! L2 T: x& l
  49.         TMOD &= 0xF0;        // 设置定时器模式
    ; M. }% t  y. F* D: n  s
  50.         TL0 = 0xC0;                // 设置定时初值3 \1 l# H! A2 b5 F9 {2 J
  51.         TH0 = 0xE0;                // 设置定时初值9 }2 z/ m& h' J5 e% @1 c
  52.         TF0 = 0;                // 清除TF0标志& C, w9 G, t! E
  53.         TR0 = 1;                // 定时器0开始计时
    0 b; T; s1 Z9 x6 v$ g1 i
  54. }
    ' d9 _' ?5 u& R
  55. & _; m3 i9 J9 Y' g3 S6 y+ l9 c
  56. static void Interrupt_Init(){
      v' i) T0 F2 q5 z
  57.         // INT0中断触发类型为下降沿触发1 V$ M8 A3 y7 x% ]
  58.         IT0 = 1;/ }& B# ~. z  e& T
  59.         // 允许INT0中断
    8 b* m# o" A& ]# {; L0 B' Z8 G6 h
  60.         EX0 = 1;; S- N8 g0 ?: j5 S
  61.         // INT1中断触发类型为下降沿触发1 Y( O7 u1 M1 p7 O2 [4 U9 Z
  62.         IT1 = 1;
      v, |2 N. R% s% a4 r% j. o
  63.         // 允许INT1中断
    ! @+ [0 n% c/ Y3 V' M  q
  64.         EX1 = 1;
    4 k/ B2 P; ]- b0 ^3 b" ?
  65.         // 允许定时器0中断
    4 ~3 E% e& ?+ y2 Y) n- u
  66.         ET0 = 1;9 P2 R% P8 j2 `! Y. [- |
  67.         // 允许全局中断0 x  q, W2 A% S( ~- k) h5 v
  68.         EA = 1;
    6 K; [1 T8 d1 L; \. R( H
  69. }  O7 D7 C& k) I

  70. 8 _0 V2 r% V6 J) v% r
  71. static void INT0_Isr() interrupt 0{
    / r+ \+ I" X7 X* w5 z/ n
  72.         // 矩形波次数累计归零
    + t4 }# D' q0 \' |6 |7 ]
  73.         count = 0;
    7 |2 W, X" e% V
  74.         // 重开定时器0中断4 c) A7 D3 G* R. f, R: x" R$ n4 j
  75.         ET0 = 1;1 J: u! d1 [  n/ H' k
  76. }
    , a$ g, y! t# u6 M5 k. Y0 L

  77. + U6 x' [4 ]! ?1 R
  78. static void Timer0_Isr() interrupt 1{) u/ q3 N" T0 H
  79.         // 输出矩形波
    2 R) |: ]: C& |. H0 ]
  80.         OUT = ~OUT;7 L! D" F$ z$ J
  81.         // 累计矩形波次数
    ' V0 {$ l2 o. i- I% }
  82.         count++;
    ( m: w. R% @8 v# e4 M& d/ j
  83.         // 超过250个矩形波,准备停机
    ' m; o% k: g* X: R/ m( y
  84.         if(count > 250){: h* _& O" _& F3 ~9 d! a" z
  85.                 count = 0;
    ; [4 C4 ^: w3 R. T
  86.                 isReadyToHalt = 1;4 F& X2 ~8 B3 ^  }! W: A0 t0 j/ n
  87.         }
    ) U8 w- a, L9 U1 H
  88. }6 \& [+ \* N* b; Z; y! G. e
  89. 2 z9 v3 d$ q" Y( f" e8 E
  90. static void INT1_Isr() interrupt 2{* a) Z8 B3 U4 @9 \1 t- ]& e
  91.         // 矩形波次数累计归零6 f( T; R9 |2 B& x3 @
  92.         count = 0;
      e8 Q# E- K$ R0 r3 f6 a0 t  }* G& ?
  93.         // 重开定时器0中断$ Y0 l' \5 x. j* Y+ u
  94.         ET0 = 1;
    ; }- U7 o. X% L6 @
  95. }
    5 _8 j+ W* q5 p" ]( m/ p9 W

  96. ; T" H: Q# A8 l: w& l

  97. , `7 j& y; o( i% {2 u
  98. void main(){2 i8 k/ @. v" S$ |7 o
  99.         // 初始化P3和P5口
    8 t# K. M) a' b+ |3 L! r6 S
  100.         GPIO_Init();
    & K8 `1 }4 m0 {2 _
  101.         // 初始化定时器0' Q$ P8 b) M3 F$ B% _; J7 }! Y
  102.         Timer0_Init();
    " ?+ A) s+ T' j1 v8 N% L, L* f4 y
  103.         // 初始化中断
    9 {# e+ O. \5 S; l% y, h4 a
  104.         Interrupt_Init();' Q0 n+ ?; l# y" Z
  105.         ( C3 L8 B; X- B
  106.         while(1){- k0 p' |  n. d* I
  107.                 // 检测电量; o& R' v* q. @7 I; V6 \5 D8 L
  108.                 if(PCON & (1 << 5)){6 N# V+ w3 V6 B- F! p- F% ~
  109.                         // 如果电量低,低压指示灯亮% ~# y2 W5 _  f, K% b
  110.                         LED = 0;4 n' H' `# \( w. s( u8 Q/ G
  111.                         // 清电量检测硬件标志位
    7 E/ n7 [7 `& L9 `$ r
  112.                         PCON &= ~(1 << 5);
    # M  J. J" _9 [" K' a
  113.                 }else{% G  Y' f, c- F9 E+ q& U5 n
  114.                         // 电量正常,低压指示灯灭
    6 u# \' |& J4 D$ q4 r% F) y
  115.                         LED = 1;! F* N* B+ c$ K' X1 F
  116.                 }
    1 r3 D! k  l$ x0 a: }5 z9 ^* M
  117. 4 w. g5 x2 G6 s7 D8 B1 T+ v* y
  118.                 // 检测到停机标志" F- A# [' C6 ?) ~, m
  119.                 if(isReadyToHalt == 1){; Q4 Q: l) U9 \& h& _' l7 J
  120.                         // 暂时关闭定时器0中断2 W- n0 j; L' T% }3 a0 s# e
  121.                         ET0 = 0;
    * F. T# ]3 R% `, e7 E# K* k
  122.                         // 停机之前先把矩形波输出脚置低电平,以方便INT0和INT1唤醒CPU+ u" q- a7 H! @+ z
  123.                         OUT = 0;3 ~% d& E' |7 i
  124.                         // 停机之前先把低压指示灯灭掉,以省电
    ( I, Q) l$ c) t' w
  125.                         LED = 1;
    ) {0 T8 C) r- z) \; f
  126.                         // 进入停机模式
    6 M1 K, P( f0 o* y" H
  127.                         PCON |= 0x02;7 D; w, K! \7 P7 s3 Z. A
  128.                         _nop_();
    4 D5 f; H; {0 C! `
  129.                         _nop_();
    ! {$ ?) L9 @) j$ O
  130.                         _nop_();
    ! l! p1 ], I6 ~8 Z, @5 ^3 m) N! k
  131.                         _nop_();. G9 s" n. |# _+ e* e& r
  132.                         // 唤醒,清标志位
    % q2 v; {5 R6 H" C; p6 e
  133.                         isReadyToHalt = 0;
    % {: k/ Z8 z2 k. t
  134.                         // 重开定时器0中断2 M6 X+ q. r6 C! z3 D5 n1 j
  135.                         ET0 = 1;
    " S: q# P+ f' }* ^
  136.                 }( P( d$ ~- [5 }# T+ M
  137.         }
    : U$ j& ~! M5 z! E! ]% t4 n0 c
  138. }
    - R/ k) H% s  i7 q( W7 w4 C
复制代码

4 p7 q& x5 b% j5 ~$ _硬件参数配置:
$ W$ c1 D+ n0 V* k7 r. ?- t% X& W+ a- w( o* u& _' H  @: M* d
7 j8 U" B8 h1 L- d% e
接收端:: \  E7 }8 o7 v) n# H
  1. #include <INTRINS.H>
    . m: s) J. A  [% r% G  W
  2. #include "STC15W.h"5 T# o9 G" X0 a/ w
  3. ; J0 J9 z9 J# `7 K

  4. ( T" }) b1 s7 s4 _  a5 x
  5. /*4 {  A3 G) V6 h; f2 u, v+ g

  6. 0 T8 Z; J7 o- |& O4 H$ @
  7. *---------------------------*
    5 l. u, U' ^& Q6 l: r8 d$ Z( R" ^) z
  8. |1 (GPIO2)         \__/  (GPIO1)16|4 Y  i1 h: W" ?* c
  9. |                                                        |
    + k, _% U( W- Z
  10. |2 (GPIO3)                   (GPIO0)15|3 M/ f' q6 B& `. v
  11. |                                                        |
    # d6 W( \2 T$ D8 P8 }* L) x, _2 M
  12. |3 (GPIO4)                                  14|+ z' K7 i$ A$ A- k( I, B# A
  13. |                                                        |! t, Q2 a  K5 l4 q; w3 h- u
  14. |4 (GPIO5)                        (DATA)13|6 l- R( ~5 [0 J" e  J* w! B
  15. |                  STC15W204S                |2 i7 ~  s: l! s( R
  16. |5 (GPIO6)                   (LATCH)12|
    / p" }4 U, w, M% ?) ?; x
  17. |                                                        |
    & e& E; Z9 I6 V& p) e
  18. |6 (VCC)                         (CLK)11|
    2 Q- r' J* }, F- n7 l7 C$ c
  19. |                                                          |8 F- V1 X9 H# W9 M& [4 T+ S, y
  20. |7 (GPIO7)                         (TXD)10|: k! {0 q9 t, n4 Y2 w! D
  21. |                                                        |1 V5 K  R. L! U( Z
  22. |8 (GND)                         (RXD) 9|
    % Y. i9 @5 l: F! D- H+ i: d; W
  23. *---------------------------*; N5 H) f/ m2 I. s4 M
  24. Fosc = 12MHz
    ' s; n, l1 z1 X2 _. N) }6 {

  25. 5 k1 Q; X* g8 J5 V
  26. P1.0 -> 上5 l( P  N8 o9 F; M8 L9 Q
  27. P1.1 -> 左
    " U8 ?1 p1 V8 M, P& ]
  28. P1.2 -> 下
    # f- P  l! k! l9 E( t) P2 T
  29. P1.3 -> 右9 m7 s# ~7 I- S, v0 f( F
  30. P1.4 -> SEL' e& ~0 @. L2 H- ?( u  a6 Z
  31. P1.5 -> STA. ?2 M8 G7 d$ Y+ Y; X; @, E
  32. P5.4 -> B
    4 U3 `$ h' l+ I2 k( A
  33. P5.5 -> A' h8 D. Y" y4 X5 l/ R8 _1 c

  34. 7 L2 J3 [5 e% A6 T) z) ^7 P
  35. */
    8 K: {7 b  R0 `) ]% e) }
  36. * B: e) }- w8 [+ x" i' k( h
  37. & a$ x7 Y$ I# b  x5 B: z
  38. sbit CLK        = P3^2;
    6 H' q. |% _0 z4 ~( p; v/ j+ A
  39. sbit LATCH        = P3^3;
    9 @9 W1 O/ b. Y6 H7 y$ g( I4 s
  40. sbit DATA        = P3^6;
    - Q' X8 x3 r3 x1 B' _
  41. " E1 E5 [! ~1 ~- i4 \1 U/ V+ V
  42. bit isReady = 0;* a- p  W, O2 X* @
  43. static unsigned char key = 0;! k5 q+ L, J3 ~. `
  44. static unsigned char buf = 0;        // 双缓冲。这个缓冲区保存从P1和P5组合而来的键值6 u0 w) n5 Z. B- h
  45. static unsigned char bufReady = 0;        // 双缓冲。这个缓冲区保存上面那个缓冲区的备份
    9 o' d' W# Z8 e& ]
  46. static const unsigned char data mask[] = {0x80, 0x40, 0x10, 0x20, 0x01, 0x04, 0x02, 0x08};        // A B SELECT START UP DOWN LEFT RIGHT。为提升速度,这个表放到RAM中
    5 ~' f. J- T4 R, D
  47. static unsigned char idx = 0;
    + u. |0 p5 H0 D7 n8 l" s

  48. & i+ ^( y* O* w

  49. 5 w% @/ ?" k+ O- T, E. P6 k: _
  50. static void GPIO_Init(){
    0 J+ v2 d& ]; J+ M/ J& q
  51.         // P1口和P5口用于接收并行信号,全部初始化为准双向,依靠内部弱上拉输出高电平
    8 ?0 K3 f" I: q8 f2 ~
  52.         P1M0 = 0;) I/ d. l/ [( R
  53.         P1M1 = 0;; L" j0 c8 A" i/ |" x& H
  54.         P1= 0xFF;
    & P/ T& Q) K4 o2 h$ y
  55.         P5M0 = 0;
    ! _+ N2 d3 s* @/ n% p5 [
  56.         P5M1 = 0;
    / f2 ]& X) ~" Q) B) O6 u; L
  57.         P5= 0xFF;
    8 t/ D7 r/ a% e  L2 ]" S) t
  58.         // P3口初始化为准双向
    % H8 v8 p9 S, Z. W+ _5 Y* f) s
  59.         P3M0 = 0;
    # @) Q' y" B& ?
  60.         P3M1 = 0;/ P! r' {8 S1 y! _
  61.         P3 = 0xFF;' k5 y' g0 ]/ M- k/ B4 d
  62. }+ `" ?1 J4 S& `" V6 E

  63.   G* @& n6 ~: |" E6 [
  64. static void Interrupt_Init(){
    0 @0 w1 `+ a: G
  65.         // INT0中断(CLK)触发类型为上升沿+下降沿
    3 K: I8 f2 \; Q' c1 _3 M) |
  66.         IT0 = 0;: S+ j/ C& O* @# q6 q% R* _
  67.         // 允许INT0中断
    0 N* y" e/ X; T. G2 L
  68.         EX0 = 1;, g2 Q' b- j( e! K; l5 j2 Q
  69.         // INT1中断(LATCH)触发类型为上升沿+下降沿
    / D, J3 h- T' H9 E% G- v  p9 ^
  70.         IT1 = 0;0 r  P/ x) A2 g; ~/ q! x8 @
  71.         // 允许INT1中断
    % n! h& u/ s8 H* x
  72.         EX1 = 1;
    ) k- l" j7 r! b" q
  73.         // 开启全局中断
    # o# c6 R: P$ _( b8 s0 q# y
  74.         EA = 1;
    4 m( e7 p" [) B9 h2 C
  75. }
    7 l; S' M( M/ _+ T, B0 S

  76. 9 y( r- o5 F; @. {  S: P
  77. static void INT0_Isr() interrupt 0{; A5 u2 l: x) c9 k6 K
  78.         // 只有已经成功锁存才允许CLK移位+ R9 m7 M, c" N; u8 b" g
  79.         if(isReady == 0)
    ' P- w& E1 y+ s  W# g! T
  80.                 return;
    ) \) }6 D9 ^6 v3 `# ^4 _
  81.         // 读当前引脚电平,如果是低电平则说明是下降沿,此时直接忽略该中断' ]1 ]( L  e" _
  82.         if(CLK == 0)
    9 _& S7 w1 K, k& w
  83.                 return;
    6 e! Z+ z" i, g: {
  84.         // CLK上升沿到来的时候,取锁存值的下一位输出6 l% s1 p; G" `6 T7 R$ T% z0 i4 e
  85.         idx++;
    ' L2 T) V& q; R- u2 v
  86.         DATA = key & mask[idx];! m: w. e' q8 C5 a0 r
  87.         // 如果已经完成7次移位,则一轮读取完成
      e' R# x) X* ^. B2 E4 o' W
  88.         if(idx >= 7)
    & J1 Q# ]# t  C
  89.                 isReady = 0;2 N0 I5 ]8 q" K
  90. }" F0 R3 w  P- ~4 ]# L

  91. ! z# f0 h7 v( z, M+ {! z
  92. static void INT1_Isr() interrupt 2{
    - j8 X" c7 c# v- A: l: W! X
  93.         // 读当前引脚电平,如果是低电平则说明是下降沿,此时直接忽略该中断
    ' [9 o( ]5 M- M, g
  94.         if(LATCH == 0)
    5 |" @% I/ {+ ]5 A
  95.                 return;
    % T. \8 n" Y9 c' i( |
  96.         // 当LATCH上升沿到来的时候,锁存所有按键状态,同时把键值A输出到DATA9 U4 Q/ U" T: j8 G9 c
  97.         key = bufReady;
    7 W+ J5 v! V. c/ X2 G8 w5 g
  98.         DATA = key & 0x80;//mask[0];        // 为了加速运算,直接取表中的值而不是读表+ P  I/ o- _/ T
  99.         idx = 0;; L: Y5 q2 e" b# e
  100.         // 允许CLK进行移位
    ! s8 d$ W% a3 K0 E- z. V1 U) {- P
  101.         isReady = 1;+ R% y' J0 E1 _( V
  102. }
    5 u8 P0 \% H, Y

  103. 0 E2 ^1 M* F1 m4 W5 C$ r
  104. void main(){
    8 k! }5 I0 A6 N' ^* T
  105.         GPIO_Init();
    6 e: T* \. W$ l2 A6 ~# o# o, C
  106.         Interrupt_Init();" J4 L$ D0 x9 R2 N  D
  107.         $ w! K4 u3 h( g4 K. v: R. v" r8 x3 p
  108.         while(1){
    4 i2 L3 t, H. n5 `( f) g
  109.                 //PCON |= 0x01;        // 进入省电模式2 {* E  F: u% o, D- F
  110.                 //_nop_();
    * r0 `8 k* B( {8 [& ]
  111.                 //_nop_();  N8 C) T5 \/ D- U9 a4 m
  112.                 //_nop_();5 d8 u9 ]/ f$ L  s  K# V/ R
  113.                 //_nop_();
    ' i: \1 m8 D% e1 V. [+ N
  114.                 buf = ~((P1 & 0x3F) | ((P5 << 2) & 0xC0));: P0 N, J% M  k, W  z2 {% |' W1 S  H% \  g0 h
  115.                 bufReady = buf;: t/ G) q- @0 _# R, _0 `* T
  116.         }3 n0 s4 `" _+ k1 ?
  117. }$ L5 C  z- O+ K0 e( O9 v9 ^
复制代码

1 v) ~' N7 }% R硬件参数配置无特殊要求,晶振频率选择12M即可。3 A6 w0 m' H$ R" J0 W$ t5 n

7 m/ v, ?' ?: k/ P9 o这是编译好的固件。

本帖子中包含更多资源

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

×

评分

参与人数 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# g1 o0 ]- `! v! F  _9 _5 n; ~
不错的设计,想问一下楼主,FC的15针公头怎么解决?普通的公头太短了,插不进去FC的扩展接口。 ...

: k; i, J6 b. \- ?/ h5 K) h坛友的改造方案
回复

使用道具 举报

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

使用道具 举报

发表于 2019-5-25 12:07:18 | 显示全部楼层
精彩,楼主动手强,也写得很详细。  s. I+ p4 M  q( u
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
$ Z7 O$ t7 V3 @+ f% I精彩,楼主动手强,也写得很详细。* g( s& v5 A0 h; n# P. w
2.4G方案是目前无线的最低延迟吗?
3 F% t0 D" |# C7 O. W+ L
我没用过其他无线手柄,所以实在不知道我自己做的这个手柄到底是不是最低延迟。
3 X5 d' _1 Z" j1 o# z不过根据网上的说法,延迟高低主要是由通信协议的复杂程度,以及数据传输速率决定的。这个模块虽然是2.4G无线模块,但由于协议很简单,所以延迟比较低。. K. X" x7 b* `2 e
我用这个手柄玩一些ACT游戏,比如超级马里奥、忍者龙剑传、热血系列,完全感觉不到延迟,和游戏机自带的手柄没有任何区别。唯一的区别就是这个手柄是用火花山寨手柄改造的,外壳是垃圾回收塑料,粗糙+脆弱,导电橡胶弹性不佳,手感不是一般的差。
9 V/ ?+ _+ Y  \# y! ~* o我手里还有十几张板子,等我有空了我再做一套,到时候买一个好一点的手柄改造。
回复

使用道具 举报

 楼主| 发表于 2019-5-29 16:56:14 | 显示全部楼层
ppad 发表于 2019-5-28 17:27% e6 s( G8 c# B6 D
给技术帝赞一个,有半成品发布吗,自己焊接改造就可以,编程实在不会啊 ...
' S+ u$ y9 N4 R0 w- I
很可惜,我手里没有多余的单片机了,LDO也找不到了,锂电池以及充电模块更是没有了。反正就是该用到的元件基本都没了,所以没法发布半成品。
; {4 t8 T5 z  i4 a( o, t3 o. C) @* p两个板子倒是有十几张剩余。$ `$ O! C8 O0 s& ^- z  E3 q+ [
你要是有USB转TTL串口板,完全可以自己买这两种单片机,然后我给你编译好的固件,你自己用串口板下载到单片机里面就行了。两个2.4G无线模块也得通过串口板用AT命令设置参数,不过好在我在设计电路的时候就已经预留好了串口,可以直接在线下载和在线设置参数。总的来说并不麻烦。
回复

使用道具 举报

 楼主| 发表于 2019-5-29 17:00:34 | 显示全部楼层
孙大师 发表于 2019-5-28 18:55
: C7 u6 \7 @  t& F$ z非常好,楼主是技术帝,到目前我都还没开发fc的无线套件,等空了,开发一套套件,等玩家自己组装。 ...
* M) ^9 ]$ F. H4 y6 y
能得到孙大师的赞誉,不胜荣幸!2 t4 C6 {6 x4 G% ~6 G* Q8 u% `8 d( u& v
不如开发一个多功能手柄,比如用SFC手柄改造,L/R键配合其他组合键可以用来切换2P~4P、调节连发速度、软重启等各种功能。接收端插到15PIN扩展口。
回复

使用道具 举报

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

本版积分规则

Archiver|手机版|小黑屋|Video Game Do It Yourself ( 闽ICP备14000865号-1|闽公网安备35018102240098号 )

GMT+8, 2026-2-7 11:41 , Processed in 0.114308 second(s), 15 queries .

Powered by Discuz! X3.5

© 2001-2025 Discuz! Team.

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