找回密码
 注册

QQ登录

只需一步,快速开始

查看: 26715|回复: 33

自制FC无线手柄

  [复制链接]
发表于 2019-5-22 14:16:45 | 显示全部楼层 |阅读模式
本帖最后由 雷精灵2046 于 2019-6-14 09:28 编辑 ! w8 G- n/ k" O/ j+ U8 ^6 u. f
* W9 N0 E3 u: q1 q
没有用复杂的分立元件搭建发射接收电路,直接用的现成的2.4G无线模块jdy-40。
8 S5 t* d' z) A. [8 [4 x/ B* H
8 X* [! f' k2 m% E5 p1 v) o, i8 Z: G( |! |, a
发射端靠3.7V锂电池供电,用了一片SOP8封装的STC单片机,负责产生连发脉冲,同时负责检测电池电量,电压低于3V左右的时候触发低压中断,低压指示LED就会亮起来告知该充电了。平时发射模块和单片机均处于睡眠状态,有按键按下才会唤醒,从而实现省电。实测睡眠状态下整机电流约1~2uA。板子洗了一下稍微干净了一点。因为对于微功耗设备来说,焊接残余的助焊剂可能会增加漏电流。- Z) X- t5 t% W

% u9 e% B! ^! D( r: p5 }) M  Z买了一个火花的FC山寨手柄,去掉里面的牛屎板子,并修正一下塑料挡板,把锂电池和充电模块装进去。6 f9 v" _9 t( l% I  Q! w
为了减少体积,充电模块裁剪得十分小,并且更换了充电电阻使之适应这个小小的锂电池。这么小容量的电池,也不需要多么大的充电电流是吧?/ o7 h0 k) \% c' v
然后统统用热熔胶粘上。充电电流比较小,所以发热很少,不会熔化热熔胶。8 i& s& U. ^) L0 A2 e

' N' {7 m8 x3 [9 ?" d7 K# a; G! t' r6 m9 X( ^
$ `* _3 @0 n  Q) P; E! ]
最后把按键、导电橡胶和电路板装上去。, [) d& J. X9 {
精心裁剪了电路板,正好扣上,不会阻碍其他元件,也不会影响后盖和拧螺丝。
6 w3 K- k7 k  Y( x! ?+ `+ V( I, z
& }. {4 f- J4 x1 a: n8 L
; p  v; \$ J+ x完工!' x7 D3 s$ J4 Y  p
/ F: t4 `) t9 @3 R  z& }9 g
9 j) i, o* a9 X) @5 K* H, |
这是充电的MicroUSB插座。旁边的小孔用于透出低压报警LED的光线。  G; _( E7 l9 _1 M+ g, W  H

1 S$ N- X1 U# K4 }. A
& t/ J7 d2 _' C$ R  y+ e: x% g接收端用一片DIP16封装的STC单片机模拟CD4021。为啥要用单片机模拟而不是直接用CD4021?因为jdy-40模块接收端在有按键按下的时候输出高电平,无按键按下输出低电平,和普通手柄正好相反。当然我也可以用两片74HC00或者74HC04之类的逻辑门进行反相,但那就增加了芯片的数量。对于FC手柄这种工作频率并不高的设备来说,STC单片机完全可以胜任模拟工作。
$ Y0 A# M9 {# ~3 e6 L$ W2 h% h& _5 R4 s2 L8 U$ f

# o8 @5 K/ M, d( v* o4 i2 g1 [' ?1 s$ v  A; m( o' z
电路设计有点小小的错误,所以有几根飞线。原本设计使用低压差LDO是XC6206,结果在做这个接收模块的时候,买的LDO居然找不到了!无奈只好用了AMS1117。幸好对于接收模块来说是5V降到3.3V,1117可以胜任。要是发射端手柄的话,3.7V降到3.3V,那就非得用6206不可了。" I6 X+ o0 v8 O, q1 n- Z2 j( R, L- h

' O. _8 t- i# o# B  w6 O. ^实测十分灵敏,延迟极小几乎感觉不出来。可惜这山寨手柄的手感并不佳,尤其是方向键,软塌塌的。看来我得买个剪线手柄改装。
; R" V6 a: c( Y( _& z% h
5 u/ a) [( Z6 Y4 R8 [这是电路图,有兴趣的朋友可以参考。
% I: j7 e' k1 o
* e1 d3 @& H+ D
% i$ Z" z, \9 y* f我信奉开源主义,十分痛恨把技术藏着掖着。好东西大家分享嘛!所以两个单片机的源代码大公开!
8 y. D3 u8 s8 Z: _编译器:Keil 51。0 d7 |1 k) E" n  O

  Y8 S( S( ^* b! \$ u6 F1 l  n发射端:
! B9 {  J" s/ e; n' s7 F$ p
  1. #include <INTRINS.H>; T9 y# R: q$ q$ [' J3 r$ q
  2. #include "STC15W.h"
    % Y& n1 t2 N6 e; C* J
  3. 6 W$ {" U6 K3 n
  4. ( [9 j3 D6 \2 C
  5. /*- S$ D) P+ g1 n  x. _0 C
  6. --------------------------
    ! ]$ g$ M4 Y  g, x
  7. |1 (OUT)        \__/   (INT1) 8|
    # A8 n5 Q' v8 I, S
  8. |                                                   |9 L! O$ @  |1 U" \/ `
  9. |2 (VCC)                   (INT0) 7|
    $ c+ T6 ?( y. [/ k
  10. |                 STC15W204S                   |
    " U' R/ N1 R1 q1 \+ b
  11. |3 (LED)                         (TXD) 6|
    ( t% z. X# x) B9 o! ]% l
  12. |                                                   |3 g$ B" J; t; ?" y; v) D9 L2 Q
  13. |4 (GND)                         (RXD) 5|
    9 n) g0 Z" N! D; l# ]
  14. --------------------------
    7 g8 P- Y% B0 h1 l. A1 T% |

  15. " B, x- y  k1 T8 S9 Z+ ~) s
  16. LED ---|<|---[===]--- VCC
    ( f- P) a6 M* Z
  17.            Red          330
    1 f1 p' o; C! r* ^' w( E
  18. ' k- J* q- L/ b- O4 E9 Q, r2 o# B, z
  19. Fosc = 6MHz
    8 `9 j- M% Q5 X1 |) n9 N: ~/ b' m
  20. */0 s1 ?, n5 M) n9 F( t3 B
  21. % ?* N# K9 c, D& h( v
  22. 7 [, h* o8 z7 `- o
  23. // 矩形波输出脚
    : Z  j: t) A' Z$ p
  24. sbit OUT = P5^4;
    9 D8 T$ q+ [. T; s
  25. // 低压指示灯引脚9 i5 r6 p( k  G9 y
  26. sbit LED = P5^5;
    ! Q( V' D$ _( o

  27. ' W2 b- p$ r/ B) E* f
  28. // 停机标志位
    + z0 V+ [0 {0 b+ D3 Q3 S' ]
  29. bit isReadyToHalt = 0;
    & v& U, Z% F; ]) a+ F
  30. 3 d9 G6 O) M1 N7 Z
  31. // 矩形波次数累计6 Z! ]+ H9 s; C2 }
  32. static volatile unsigned char count = 0;; u3 H! t' d$ [$ Z0 ]5 g% F4 i3 z

  33. . r& r0 t" |' o2 n: I5 q5 f: i
  34. , {' g5 o; E7 t
  35. static void GPIO_Init(){! m- a6 ~) s+ k' R2 E
  36.         // P3口设置为准双向,默认靠内部弱上拉输出高电平
    7 K7 h$ b4 k4 C: S3 \/ ^
  37.         P3M0 = 0;
    # ~% y7 O0 r* p6 z0 @" |
  38.         P3M1 = 0;
    6 A+ j/ k8 f! @  j
  39.         P3 = 0xFF;' H: F1 ]8 V2 h* @
  40.         // P5口设置为准双向,默认靠内部弱上拉输出高电平  e. o# v/ m1 {
  41.         P5M0 = 0;8 [, u1 j. u8 ?
  42.         P5M1 = 0;3 x* J% g* c9 |8 V/ r2 \
  43.         P5 = 0xFF;8 V6 @& m: J1 e" r7 P' r
  44. }
      @  v2 C; W" N

  45. 2 z- z6 O% W' N
  46. static void Timer0_Init(){
    9 C" |; A7 @6 I/ w9 k
  47.         // 16毫秒@6.000MHz
    0 T" z* E: ?% `+ W: a2 A9 h
  48.         AUXR &= 0x7F;        // 定时器时钟12T模式
    8 u3 ]' M. Q. i7 t& y
  49.         TMOD &= 0xF0;        // 设置定时器模式
    + E  [) R9 G$ @2 f. j" J2 z
  50.         TL0 = 0xC0;                // 设置定时初值  }7 b$ ]' t7 @, h5 M; s' ^" O; }
  51.         TH0 = 0xE0;                // 设置定时初值# e% ?4 n, f4 Y% B) V
  52.         TF0 = 0;                // 清除TF0标志
    2 d+ F3 C& u# \1 v, T/ S
  53.         TR0 = 1;                // 定时器0开始计时2 H2 v8 s7 Z& I2 E* h4 f& S
  54. }( a1 n: ]# ]5 ^  z7 V

  55. & K. ^. |% i1 Y/ l  o% V% J6 P
  56. static void Interrupt_Init(){$ {+ S* u! \+ r: f
  57.         // INT0中断触发类型为下降沿触发7 \2 T8 B, B0 p, Q! \
  58.         IT0 = 1;9 t+ S+ S4 O& }* Z5 c% Q. _1 N
  59.         // 允许INT0中断, i' t5 l( b9 o* V! M' p: f
  60.         EX0 = 1;2 Y( v/ b( u7 T/ Q( M' ^
  61.         // INT1中断触发类型为下降沿触发
    1 `! ]* _: g) q' u" [
  62.         IT1 = 1;! h9 q6 [  x/ Z1 f% P
  63.         // 允许INT1中断( M) w2 \/ t( R( j7 U2 O4 T# P: D, _- R
  64.         EX1 = 1;1 W% d5 Z( T8 ^% F4 U
  65.         // 允许定时器0中断( ^8 F: Y* H4 z* m* q
  66.         ET0 = 1;4 z& E2 i, f! V/ R/ ]- T
  67.         // 允许全局中断
    ( S5 [) L8 m3 W4 }4 Q
  68.         EA = 1;+ X/ ~: B( P7 c$ i% l8 v6 I
  69. }  d! B2 q- G8 a! {; Y4 {: o
  70. 5 ?, A) O1 c" d: k7 x' N) P) {9 c! _
  71. static void INT0_Isr() interrupt 0{
    & f1 F! x6 q$ I2 @$ u, i" N1 }
  72.         // 矩形波次数累计归零
    # `2 D0 N, u# ~4 H9 y
  73.         count = 0;% ?' w8 H( g# c0 j" o
  74.         // 重开定时器0中断" z6 r$ y4 Z* m# G
  75.         ET0 = 1;- F. ^7 J) Y) b9 k4 B1 k) v7 R
  76. }/ z/ m# v1 a9 B' w

  77. + x' ^0 a8 f- z7 B
  78. static void Timer0_Isr() interrupt 1{2 ~0 t& l7 `  h& H2 u+ S( f
  79.         // 输出矩形波
    2 X: [+ w9 ?5 H. |) f' A% J+ B
  80.         OUT = ~OUT;% {  D0 b! Q8 @$ ?
  81.         // 累计矩形波次数: X- ~3 B  T' {) l- Z0 e0 v) H6 A
  82.         count++;
    $ V3 j* a1 [* k
  83.         // 超过250个矩形波,准备停机' ]9 S+ h' G4 \3 k( m7 C
  84.         if(count > 250){
    - J7 v, E. E" m5 `# V+ X
  85.                 count = 0;
    - D+ t$ `- N8 o+ u
  86.                 isReadyToHalt = 1;
    7 X- @' F3 _. N6 B# B# }. B8 P/ b
  87.         }
    ; x5 a* l! v. t" l/ \8 ?
  88. }
    0 X$ p9 G. [4 p
  89. 3 b* I% ?+ a0 K9 U& d5 s0 u) |
  90. static void INT1_Isr() interrupt 2{' j( ~+ ?( q# z" a7 `
  91.         // 矩形波次数累计归零! Q3 c- e# o/ k
  92.         count = 0;' n# \" S9 K) r" E" y. c& e
  93.         // 重开定时器0中断
    * A( @$ S  y7 {8 M# n
  94.         ET0 = 1;
    8 A; c% {( T) Q1 S0 A- q4 v, G( P
  95. }, `" _) ^; e* f8 x$ `) w

  96. 6 j- B! v6 r, Y, `( C- b
  97. 3 k( E6 C4 }3 s9 r
  98. void main(){
    ' j; b- i8 O0 J" x& x0 O7 y
  99.         // 初始化P3和P5口  ?; `! K9 T$ ~; A- S( g
  100.         GPIO_Init();8 P% V7 U4 t, s1 l5 C
  101.         // 初始化定时器08 [. Y0 ^' U7 s+ F
  102.         Timer0_Init();& J/ ]1 r* N% L3 X5 J. v6 \& A
  103.         // 初始化中断& y/ v# @2 K. Q4 i$ s3 y
  104.         Interrupt_Init();& J5 S, G2 z1 S( y" V- D
  105.        
    ! X/ X5 R: z) u( W
  106.         while(1){# V; q2 q1 X  ^. x6 W
  107.                 // 检测电量: `  C( f" s  V6 ]
  108.                 if(PCON & (1 << 5)){  h& S2 |: c6 ~4 z2 l0 r
  109.                         // 如果电量低,低压指示灯亮
    4 p1 s0 R! t+ Q0 m) e( `
  110.                         LED = 0;6 L& B9 @6 i7 y1 {
  111.                         // 清电量检测硬件标志位3 ]8 c* i5 g6 q: N1 ^
  112.                         PCON &= ~(1 << 5);
    3 \8 I" x- ~6 L, |) m  D
  113.                 }else{
    - y& m3 @. ^2 q: ?% i
  114.                         // 电量正常,低压指示灯灭3 Z' i" l# e3 L) `  X6 N7 G
  115.                         LED = 1;* F. N5 I9 }$ d, @6 R' L1 F4 ~
  116.                 }
    ! L7 c& ?5 A/ Q$ A& C
  117. . O  D( \# |2 y' M/ Z
  118.                 // 检测到停机标志
    ( n% d4 y7 ]' [3 U6 P3 z
  119.                 if(isReadyToHalt == 1){
    $ y/ r; |4 K$ X  @0 }. s3 ^4 H
  120.                         // 暂时关闭定时器0中断" z# {; ^6 u. T( `
  121.                         ET0 = 0;# K  {7 g. e8 I. G1 \2 I
  122.                         // 停机之前先把矩形波输出脚置低电平,以方便INT0和INT1唤醒CPU
    . |8 a; v) r  V4 s
  123.                         OUT = 0;  _3 e+ @+ b6 {3 J" M
  124.                         // 停机之前先把低压指示灯灭掉,以省电) X' G- ~. C* o: W$ k
  125.                         LED = 1;
    4 y# t) i5 [; G4 I- [
  126.                         // 进入停机模式, d; e- `2 Z/ M3 T) p
  127.                         PCON |= 0x02;
    7 q( i$ i- R" G7 O
  128.                         _nop_();3 y: k/ ]" a4 ?4 S. ]
  129.                         _nop_();" _$ k1 a4 F+ T7 J# s
  130.                         _nop_();. v9 U/ P7 B' d' q/ p; j. e2 k
  131.                         _nop_();
    * j9 S8 F6 G0 v) r
  132.                         // 唤醒,清标志位
    / @- S( V7 u' t  _4 m" W( `
  133.                         isReadyToHalt = 0;
    , {# j: }2 S4 p  |. ?8 e
  134.                         // 重开定时器0中断
      g& H: P1 P! E7 R( `  Q2 A7 u
  135.                         ET0 = 1;
    , ~3 W0 W7 X+ t3 |7 l
  136.                 }2 r' I3 U+ `; d3 |
  137.         }! [- U2 D/ d7 ]! i
  138. }) i" `' z+ v6 r+ G- f! H! C# A: d, X
复制代码
" _. W# [. f& ^  }: h. W! F5 X$ `
硬件参数配置:
+ g! p$ c1 Z0 k- d: k5 l+ ?2 N/ `; Q+ H/ P8 G) g' ?. y

& Q7 l/ p( Y" t( o3 @接收端:
" q( \, ~' @3 b; [0 }# Q
  1. #include <INTRINS.H>
    8 p4 W' L# o( F4 o% ^9 A
  2. #include "STC15W.h"; ]; R& m( n+ O4 V! b. t8 T
  3. 9 v# z+ |# ^8 V/ [  S6 g
  4. : G) l8 x8 d: ]3 Y4 @
  5. /*  G1 f) ~5 o1 i6 e: R4 I! b

  6. ! i4 C" M! w3 y
  7. *---------------------------*6 T2 [* Y* s5 ]$ I
  8. |1 (GPIO2)         \__/  (GPIO1)16|
    9 U: s  u' g" s0 p' N: q& }3 w
  9. |                                                        |
    0 w' g/ t% @% h; R' I  R
  10. |2 (GPIO3)                   (GPIO0)15|5 q$ z! I0 r; Y7 m5 [) J8 m2 h
  11. |                                                        |
      I( K( `! K  k* U
  12. |3 (GPIO4)                                  14|  ^; Z7 v9 v: N# D$ y( E* g9 @3 q
  13. |                                                        |
    1 U5 z+ T  l- f  U$ r% K# O; o
  14. |4 (GPIO5)                        (DATA)13|
    , X( a* o% i; t1 c. _2 G& }
  15. |                  STC15W204S                |
    6 r8 W& l* ~" p' I0 \- b; ~- j
  16. |5 (GPIO6)                   (LATCH)12|) K7 h: {# V+ O5 y0 T4 e0 Z
  17. |                                                        |
    2 k/ a* D  }* @: G% p
  18. |6 (VCC)                         (CLK)11|" o: F- z! E1 u1 z' F/ \+ z) ^" |- I
  19. |                                                          |
      a3 D3 L4 @* k  ^$ L5 Z
  20. |7 (GPIO7)                         (TXD)10|
    5 ?  p  o9 ?! K% M! T
  21. |                                                        |
    # q+ P; A& {9 S! a8 {3 D% B
  22. |8 (GND)                         (RXD) 9|
    - t5 P  N& Z( m+ h$ {* |
  23. *---------------------------*2 l& u. X/ d1 Q/ O& a+ N( k- x  Q4 A
  24. Fosc = 12MHz
      ]9 L+ V& U4 }1 c4 r0 t# C
  25. 3 p9 P  m- u. Z+ Z3 A6 ]8 y2 Q
  26. P1.0 -> 上
    : H$ h/ k' U0 \
  27. P1.1 -> 左5 \- a+ ]9 D; V6 s  u, T0 h& n/ N
  28. P1.2 -> 下( e& V, t% i7 i
  29. P1.3 -> 右- ]" J. A; ], b1 g' o, `
  30. P1.4 -> SEL
    8 f; g) c/ }- ?% K3 w
  31. P1.5 -> STA
    ' x5 I$ s! |: x5 [! M# R
  32. P5.4 -> B
    2 k6 X3 ^  F4 m) c7 y1 W, D+ X
  33. P5.5 -> A+ m  S# ]+ r0 Y, k- x

  34. . S! C; H' p9 V2 m! z- O( j
  35. */; i2 E3 P. Q  n& F9 K0 ^' d
  36. , r3 a# Z" G; k$ r+ b) F/ L9 z
  37. % [/ T, f; l# F; z0 u6 }
  38. sbit CLK        = P3^2;
    6 O- x% S, ^/ Q4 ]
  39. sbit LATCH        = P3^3;
    & w/ x/ i& p" S9 S+ A
  40. sbit DATA        = P3^6;
    : n$ ]1 U& g2 ~; V4 ^8 `! m
  41. ' ^, J' d& n+ r2 m. ^
  42. bit isReady = 0;; s/ ~2 M  @5 z+ h* M
  43. static unsigned char key = 0;% J0 ^9 a9 O$ [5 C$ G
  44. static unsigned char buf = 0;        // 双缓冲。这个缓冲区保存从P1和P5组合而来的键值5 S: J; t& x/ Q* L) p" u
  45. static unsigned char bufReady = 0;        // 双缓冲。这个缓冲区保存上面那个缓冲区的备份* Q0 q$ O% ~5 Y+ G5 x; X
  46. static const unsigned char data mask[] = {0x80, 0x40, 0x10, 0x20, 0x01, 0x04, 0x02, 0x08};        // A B SELECT START UP DOWN LEFT RIGHT。为提升速度,这个表放到RAM中
    1 P8 J( F! j! G- c
  47. static unsigned char idx = 0;
    % F9 k; @& h" Z% L3 \1 `
  48. . J. \, b7 @3 O

  49. , P) a7 W: @3 S
  50. static void GPIO_Init(){
    0 q- C9 R6 g. l8 \
  51.         // P1口和P5口用于接收并行信号,全部初始化为准双向,依靠内部弱上拉输出高电平- g7 v0 O! x5 L6 r: F# r
  52.         P1M0 = 0;) I# \7 a* s$ d9 Z9 _7 v
  53.         P1M1 = 0;
    3 u( s9 a, |- p( N* ?
  54.         P1= 0xFF;
    4 O  `' R: p1 q* `5 w& h
  55.         P5M0 = 0;- U2 f. a  p* p9 d" E2 O& i
  56.         P5M1 = 0;
    5 d, K( q+ y5 L; x! W; T2 P( ~& Q  _
  57.         P5= 0xFF;* S. p* i' k; ]3 w; A
  58.         // P3口初始化为准双向
    5 U. e8 m) {4 C
  59.         P3M0 = 0;5 t, Y7 @" ^  @; D- g# m' p
  60.         P3M1 = 0;1 n/ i$ Y  {: C
  61.         P3 = 0xFF;
    & ?$ l! t; V3 U" n
  62. }
    , ]1 \  c" k0 a- j5 ?0 \

  63. ! n: R4 g  Z" C) k7 T) D2 Y
  64. static void Interrupt_Init(){* Z5 m! o' J$ W  C
  65.         // INT0中断(CLK)触发类型为上升沿+下降沿
    1 m, P& ]  t7 ?' a- h
  66.         IT0 = 0;& G# e' r2 f% I- j4 k
  67.         // 允许INT0中断% ?8 Y' s: B; j& ^) Z
  68.         EX0 = 1;
    ' Q" m2 r6 P# l: Y. }, M- |# ~
  69.         // INT1中断(LATCH)触发类型为上升沿+下降沿
      }3 S6 x& g# J& I1 D5 T8 R, Q' @  b
  70.         IT1 = 0;: K: m3 F) s  s, [* Y4 s2 L" q
  71.         // 允许INT1中断
    $ A8 c: [; ?8 J# Q, Z5 \
  72.         EX1 = 1;
    + u' ^( P. O8 K2 @1 U
  73.         // 开启全局中断% L, G1 \. G  f+ f% u2 l
  74.         EA = 1;
    6 ^4 X! u: `1 U; N/ P
  75. }' k' g6 a8 O2 C8 S5 h- H
  76. ( H/ I* N) d1 n) G, l5 V/ v9 [
  77. static void INT0_Isr() interrupt 0{
    & ?8 x  E+ _$ `/ x" I. y5 p6 D  ^
  78.         // 只有已经成功锁存才允许CLK移位8 H8 j; y6 }% Z% r+ {
  79.         if(isReady == 0)
    ! u: C& l9 X. Y1 ]9 N! E+ z
  80.                 return;
    6 R0 S/ E/ c+ ~: J9 K" Q
  81.         // 读当前引脚电平,如果是低电平则说明是下降沿,此时直接忽略该中断
    / @) @$ L9 b& {, U
  82.         if(CLK == 0)
    * x* X& w- s* i. D* y' q
  83.                 return;5 W8 {1 R/ s; K1 k$ g) q8 Y
  84.         // CLK上升沿到来的时候,取锁存值的下一位输出, C2 g0 }% ~3 v" R' S9 W
  85.         idx++;
    $ T- ^4 o: f& H$ z( T( B" T$ i
  86.         DATA = key & mask[idx];7 _+ a4 l: G5 C- m: K+ m) k
  87.         // 如果已经完成7次移位,则一轮读取完成5 a* t/ }) i$ l. y2 P6 a  y/ N
  88.         if(idx >= 7)6 i; V/ X/ t/ F' t# ~! C
  89.                 isReady = 0;: w/ q# L. F' r
  90. }
    3 S; q) I4 X* o- D

  91.   u/ E6 W* [4 _1 e# ?0 n
  92. static void INT1_Isr() interrupt 2{
    3 @! w$ k( j( o. m
  93.         // 读当前引脚电平,如果是低电平则说明是下降沿,此时直接忽略该中断" L" t# U' S  ]$ [) W3 ^9 O$ r; d6 Y
  94.         if(LATCH == 0)
    . D* S9 g( `6 s+ V
  95.                 return;
      c& R7 `. Y& b/ a! l" `( Y
  96.         // 当LATCH上升沿到来的时候,锁存所有按键状态,同时把键值A输出到DATA
    5 Q% R" Z, f, q4 j6 P( M
  97.         key = bufReady;
    ( }* }  O" ~& @+ q
  98.         DATA = key & 0x80;//mask[0];        // 为了加速运算,直接取表中的值而不是读表
    * Q7 N+ W/ t. n& d
  99.         idx = 0;
    4 p" j3 i8 m- Q) b  U/ K
  100.         // 允许CLK进行移位% [* p) ]7 z0 a
  101.         isReady = 1;' E4 ^6 ~' Z+ t* ^
  102. }
    ; f" L6 D$ F8 h. f4 P
  103. ' {" c' V# o% I% b7 B
  104. void main(){1 x* p, ]7 L8 O+ z3 R. Q2 d4 G0 y& e
  105.         GPIO_Init();9 n. {& y/ n) y8 C# b3 P9 ]4 P, N
  106.         Interrupt_Init();; ~8 M/ U4 F9 L- t9 A
  107.        
    ! L% P* T" b0 \, o! t, @
  108.         while(1){4 Q4 n9 @1 p5 c5 }
  109.                 //PCON |= 0x01;        // 进入省电模式
    2 c/ D% w; q7 G' P0 N
  110.                 //_nop_();  I5 H9 j$ {$ \1 B
  111.                 //_nop_();
    % U/ c5 }$ X8 D' o* _! E1 A
  112.                 //_nop_();: D4 Z7 k, @$ R4 U8 b9 S$ K/ X
  113.                 //_nop_();' m# S4 [$ [2 j
  114.                 buf = ~((P1 & 0x3F) | ((P5 << 2) & 0xC0));* v: W0 n5 }  m+ y4 F, r
  115.                 bufReady = buf;
    ' l4 A" H5 `% ^7 a$ \
  116.         }2 y  Z1 P" d6 {, n- [
  117. }' B) Q6 U8 y  f& h. A5 V; F
复制代码

2 N, j$ Z" r) d硬件参数配置无特殊要求,晶振频率选择12M即可。
9 C' w& _& A1 \' [& a! w/ _  ?7 K! i
这是编译好的固件。

本帖子中包含更多资源

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

×

评分

参与人数 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
0 }9 w" \; m2 r4 o1 a" F" N/ t不错的设计,想问一下楼主,FC的15针公头怎么解决?普通的公头太短了,插不进去FC的扩展接口。 ...
# e8 H- r' r7 N9 n- f+ i* M
坛友的改造方案
回复

使用道具 举报

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

使用道具 举报

发表于 2019-5-25 12:07:18 | 显示全部楼层
精彩,楼主动手强,也写得很详细。
9 b$ o6 q% Z+ J6 \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. s7 Q, p, z" S8 g# E
精彩,楼主动手强,也写得很详细。
4 c+ k1 Z2 b1 d! R3 s! s: m2.4G方案是目前无线的最低延迟吗?

) ?: t  u' S; z  B% `6 v我没用过其他无线手柄,所以实在不知道我自己做的这个手柄到底是不是最低延迟。1 o: ?8 G* P. {  M+ k9 Q
不过根据网上的说法,延迟高低主要是由通信协议的复杂程度,以及数据传输速率决定的。这个模块虽然是2.4G无线模块,但由于协议很简单,所以延迟比较低。
/ t& l1 g8 w  e" B我用这个手柄玩一些ACT游戏,比如超级马里奥、忍者龙剑传、热血系列,完全感觉不到延迟,和游戏机自带的手柄没有任何区别。唯一的区别就是这个手柄是用火花山寨手柄改造的,外壳是垃圾回收塑料,粗糙+脆弱,导电橡胶弹性不佳,手感不是一般的差。
$ s! G2 t7 N6 s7 s, U我手里还有十几张板子,等我有空了我再做一套,到时候买一个好一点的手柄改造。
回复

使用道具 举报

 楼主| 发表于 2019-5-29 16:56:14 | 显示全部楼层
ppad 发表于 2019-5-28 17:27
1 u  i2 U8 I  R6 ~3 z给技术帝赞一个,有半成品发布吗,自己焊接改造就可以,编程实在不会啊 ...

% w; y9 H- ~% k很可惜,我手里没有多余的单片机了,LDO也找不到了,锂电池以及充电模块更是没有了。反正就是该用到的元件基本都没了,所以没法发布半成品。8 w% M# L# M* i2 J6 f' T
两个板子倒是有十几张剩余。
# k3 @9 X( Z% S  w你要是有USB转TTL串口板,完全可以自己买这两种单片机,然后我给你编译好的固件,你自己用串口板下载到单片机里面就行了。两个2.4G无线模块也得通过串口板用AT命令设置参数,不过好在我在设计电路的时候就已经预留好了串口,可以直接在线下载和在线设置参数。总的来说并不麻烦。
回复

使用道具 举报

 楼主| 发表于 2019-5-29 17:00:34 | 显示全部楼层
孙大师 发表于 2019-5-28 18:55
) K0 Q0 O+ p( ~3 o0 E8 F/ m  T; [非常好,楼主是技术帝,到目前我都还没开发fc的无线套件,等空了,开发一套套件,等玩家自己组装。 ...

4 c3 G- p; U- r3 }8 P( p& s能得到孙大师的赞誉,不胜荣幸!. U3 k  |% H. L' X% t& ]0 R- b
不如开发一个多功能手柄,比如用SFC手柄改造,L/R键配合其他组合键可以用来切换2P~4P、调节连发速度、软重启等各种功能。接收端插到15PIN扩展口。
回复

使用道具 举报

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

本版积分规则

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

GMT+8, 2026-9-15 13:08 , Processed in 0.096028 second(s), 14 queries .

Powered by Discuz! X3.5

© 2001-2025 Discuz! Team.

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