找回密码
 注册

QQ登录

只需一步,快速开始

查看: 25493|回复: 32

自制FC无线手柄

  [复制链接]
发表于 2019-5-22 14:16:45 | 显示全部楼层 |阅读模式
本帖最后由 雷精灵2046 于 2019-6-14 09:28 编辑 1 l9 U9 S' l7 M3 b! u. P

) x1 G8 T7 V, i/ ^9 f4 E# _没有用复杂的分立元件搭建发射接收电路,直接用的现成的2.4G无线模块jdy-40。
3 F& ~! c) ?$ |) q6 g1 t
% A8 p, o% M( c7 m' A+ o7 b# y+ d7 {* A. v# N. }1 ?+ J
发射端靠3.7V锂电池供电,用了一片SOP8封装的STC单片机,负责产生连发脉冲,同时负责检测电池电量,电压低于3V左右的时候触发低压中断,低压指示LED就会亮起来告知该充电了。平时发射模块和单片机均处于睡眠状态,有按键按下才会唤醒,从而实现省电。实测睡眠状态下整机电流约1~2uA。板子洗了一下稍微干净了一点。因为对于微功耗设备来说,焊接残余的助焊剂可能会增加漏电流。
% G5 i! N' ?+ O$ C  Z! u. k" w4 G0 F3 g% t. Y4 I1 k
买了一个火花的FC山寨手柄,去掉里面的牛屎板子,并修正一下塑料挡板,把锂电池和充电模块装进去。
2 C4 K$ T: _, @0 L0 t& n- a为了减少体积,充电模块裁剪得十分小,并且更换了充电电阻使之适应这个小小的锂电池。这么小容量的电池,也不需要多么大的充电电流是吧?
  K& h3 W- F1 l6 ~$ ]然后统统用热熔胶粘上。充电电流比较小,所以发热很少,不会熔化热熔胶。
2 e; T8 X, M, G! d, S" e. K; p% U8 N7 Q  C5 v; y0 L% h  A

/ N, _: z( K( ]& ]4 @
, h5 i5 I. T, v9 n3 [# o; |1 u最后把按键、导电橡胶和电路板装上去。$ ?5 i$ P4 T: N' o: T) n% V
精心裁剪了电路板,正好扣上,不会阻碍其他元件,也不会影响后盖和拧螺丝。, w8 M1 J4 G  y9 @+ c: f+ T

0 z" p8 C" l3 n4 N7 f7 L( t6 w* s$ p/ m! U6 S: I
完工!9 h2 F/ o( }1 T" B) {% n, o" j  q
- S- `: y; J2 P- A6 H$ w
' s; K/ I$ {( ^2 z5 H0 L& \8 k+ D
这是充电的MicroUSB插座。旁边的小孔用于透出低压报警LED的光线。' m/ U4 U6 w2 v, o! s

  D; m- P) L4 D9 l  q; c6 m# E  c
4 r: F/ G, f  C: c8 `! v- [接收端用一片DIP16封装的STC单片机模拟CD4021。为啥要用单片机模拟而不是直接用CD4021?因为jdy-40模块接收端在有按键按下的时候输出高电平,无按键按下输出低电平,和普通手柄正好相反。当然我也可以用两片74HC00或者74HC04之类的逻辑门进行反相,但那就增加了芯片的数量。对于FC手柄这种工作频率并不高的设备来说,STC单片机完全可以胜任模拟工作。
) c( s* D2 z, U: Y6 a. \0 z* C9 u- F! q0 f& X% q. O

* m5 o& O- q. ?/ w  c  O' Q& t9 B+ u1 t& M5 o; ]' m
电路设计有点小小的错误,所以有几根飞线。原本设计使用低压差LDO是XC6206,结果在做这个接收模块的时候,买的LDO居然找不到了!无奈只好用了AMS1117。幸好对于接收模块来说是5V降到3.3V,1117可以胜任。要是发射端手柄的话,3.7V降到3.3V,那就非得用6206不可了。: b+ x  ?9 }5 D- E2 h+ l
, [; E9 R( ?& \
实测十分灵敏,延迟极小几乎感觉不出来。可惜这山寨手柄的手感并不佳,尤其是方向键,软塌塌的。看来我得买个剪线手柄改装。' M2 L5 N! m) W
) o! p  R. K2 Q- X0 J
这是电路图,有兴趣的朋友可以参考。" @. a" z9 Y. r  }
* }  o6 j" t; h% p! R
3 k5 K0 T) T+ A# |! s0 `$ q) G
我信奉开源主义,十分痛恨把技术藏着掖着。好东西大家分享嘛!所以两个单片机的源代码大公开!
: W0 |& c5 c+ h+ Y5 L编译器:Keil 51。3 w9 K' E4 q4 _6 O2 _

$ c" ?: f8 w* F7 P1 G: K发射端:
/ y3 f- T; ]( X8 B3 d8 p) U
  1. #include <INTRINS.H># ?, w( a- _: ~
  2. #include "STC15W.h"
    . w" X: N/ q/ B( \$ ?  p8 P& o; L

  3. 9 b& q" E8 j- G) f4 ^8 p

  4. 0 Y/ }% E$ @* f4 K
  5. /*
    8 r% g2 p, s; e% C
  6. --------------------------4 V3 [$ Z5 [; h- Y# @* U
  7. |1 (OUT)        \__/   (INT1) 8|& T0 v) n6 d: w* V' z  ~* W0 G
  8. |                                                   |
    * o0 w' p- @7 K5 X
  9. |2 (VCC)                   (INT0) 7|: d! |1 M8 G; U$ B- N
  10. |                 STC15W204S                   |
    , p  V# P3 Q! S) l# d+ M
  11. |3 (LED)                         (TXD) 6|9 N) S4 j% K3 m
  12. |                                                   |# O6 r. M7 ?* J; _
  13. |4 (GND)                         (RXD) 5|
    0 S& T. I3 M( D+ g$ Z
  14. --------------------------
    * r* U! [3 J7 @! L1 G
  15. 7 S. _( O  X% F* e  R
  16. LED ---|<|---[===]--- VCC
    ' w7 |. y' e5 a" K
  17.            Red          330
    # z. j% K$ I4 a, D# q/ Z
  18. 2 i" e' e% u/ v3 Y
  19. Fosc = 6MHz
    7 l! x+ t7 m  _9 g
  20. */2 i, w. b) E9 k. b  R( E
  21. 5 Y. q; G8 I. l. c$ k' Z/ p. D

  22. + F$ H$ e8 L0 A+ v. d+ X# t
  23. // 矩形波输出脚) v- R) h/ C" t* m/ u* m# v
  24. sbit OUT = P5^4;& G6 @6 g5 x+ v4 B" ?7 x% z( w$ }
  25. // 低压指示灯引脚* m! c) J$ A: J3 L: f
  26. sbit LED = P5^5;8 L& C. z( q$ Q, R) A( ]; Z7 \

  27. / x8 W4 w% M  |- |9 \+ x/ a* ?
  28. // 停机标志位
    $ D/ r6 L- s3 P# ]
  29. bit isReadyToHalt = 0;
    4 ?$ T( Y5 u9 Y4 t

  30. : H5 O( s2 @% f: a% J- A$ A
  31. // 矩形波次数累计, b5 l0 X, G* P2 T/ C" I
  32. static volatile unsigned char count = 0;
    # n9 L: E, l9 Z& u3 k; G* @

  33. ; P4 e+ K8 f8 o, y/ m+ B* F% R' x) ~# }
  34. 1 G& K! E5 v5 _* e2 @% W/ r
  35. static void GPIO_Init(){
    8 d9 f# V% L8 P9 z
  36.         // P3口设置为准双向,默认靠内部弱上拉输出高电平& u9 _1 ~$ V' w: Z/ Q3 W
  37.         P3M0 = 0;1 d3 y' i/ o6 N: b8 Q7 V
  38.         P3M1 = 0;
    & B2 A3 s3 d! U/ ?8 j( v* O$ I
  39.         P3 = 0xFF;
    1 u" ^# t9 h4 ~. `( G+ N. f4 c
  40.         // P5口设置为准双向,默认靠内部弱上拉输出高电平( W& R3 l; @& H1 g1 @/ h4 P
  41.         P5M0 = 0;, c% B- j. J4 k
  42.         P5M1 = 0;! Q( p7 }. {. P$ S1 f
  43.         P5 = 0xFF;  ^! J2 l/ M0 m$ p/ }1 x
  44. }
    + x7 @" T( ~4 W- R& g; s# D( ~

  45.   I4 C2 ]4 T9 ?: J- q- [5 U
  46. static void Timer0_Init(){
      n  T! z6 _$ l" Q
  47.         // 16毫秒@6.000MHz, C$ l5 n, y* s+ E
  48.         AUXR &= 0x7F;        // 定时器时钟12T模式3 P6 d, R% c! F7 S
  49.         TMOD &= 0xF0;        // 设置定时器模式
    7 F# W5 Z! c0 H* z  ~5 A% T0 }
  50.         TL0 = 0xC0;                // 设置定时初值3 Y/ n4 l' B2 O
  51.         TH0 = 0xE0;                // 设置定时初值) l2 {+ r) w3 @( x5 R' o$ L
  52.         TF0 = 0;                // 清除TF0标志, P/ ?# s+ q' O. }0 {2 y/ K  w* P& ^
  53.         TR0 = 1;                // 定时器0开始计时! d/ f& ?( b" q# C" E3 M. w
  54. }0 r# |, q( B1 `( C& M
  55. 8 t) _0 t+ o) X/ D
  56. static void Interrupt_Init(){1 |, h: d, Q7 |1 d
  57.         // INT0中断触发类型为下降沿触发2 K* K; z2 |* j
  58.         IT0 = 1;; y6 L( p( Y. I
  59.         // 允许INT0中断# P1 O0 ~( O; b! _& c2 D
  60.         EX0 = 1;
    9 {8 F* F, p& O# Z! E
  61.         // INT1中断触发类型为下降沿触发0 q) z! x1 H5 n4 X" Y2 r5 c: n3 m
  62.         IT1 = 1;
    5 V3 S, E- g+ a4 y7 h
  63.         // 允许INT1中断
      G4 i0 N8 p6 G& F3 I* j6 ~8 ]* W
  64.         EX1 = 1;) X: M: K9 r7 ~' R
  65.         // 允许定时器0中断
    2 z! J+ R# z8 i: \
  66.         ET0 = 1;1 e( J8 S8 f4 q
  67.         // 允许全局中断
    ' v# h, g: V' X: K
  68.         EA = 1;( W, r9 U9 u7 i4 P4 j1 @- j
  69. }3 p* p( r* b/ G* U0 E/ R) ]
  70. * i9 i- I3 ?8 v, T1 l1 \
  71. static void INT0_Isr() interrupt 0{
    ' U0 }+ w  E5 y$ J
  72.         // 矩形波次数累计归零2 c8 N+ n8 H/ Z& P* j4 c
  73.         count = 0;
    ) @. z( ]0 U2 q/ }/ t$ v
  74.         // 重开定时器0中断
    ( }; h7 ?7 c9 `$ n4 @, m: b
  75.         ET0 = 1;: O4 Q, r4 a% k0 i
  76. }- m5 H& C0 `9 \* M% p9 }& {3 {7 z  [

  77.   b! P1 T5 j( N/ v" ^
  78. static void Timer0_Isr() interrupt 1{8 c- @" l2 l, E* h* q
  79.         // 输出矩形波/ S5 K( M. |- Y9 |, ?" T
  80.         OUT = ~OUT;
    $ Q: U' j/ x2 }& c& o2 t
  81.         // 累计矩形波次数/ l# Z9 }" }/ {. A: A
  82.         count++;
    ; a* B$ L& [/ d; Z6 S* k  q
  83.         // 超过250个矩形波,准备停机9 g0 Q" R2 b6 K# W2 d: ^" I
  84.         if(count > 250){& |1 y2 u" s: A9 [
  85.                 count = 0;
    # y. M3 ]) G% v" Y- v3 S9 b' R
  86.                 isReadyToHalt = 1;, h8 M8 U9 T. q0 }" J; j  u* w
  87.         }9 S  W+ F* c/ A% K# q5 ]6 P1 v+ e
  88. }
    6 a2 D  O2 [: r# z- {$ i
  89. . Y5 `' Q  v. z& t
  90. static void INT1_Isr() interrupt 2{8 O1 |) S& M# Q; T  h; i+ q
  91.         // 矩形波次数累计归零* d1 {. C) o1 q! g. |( g1 K
  92.         count = 0;" ]+ G% G1 z4 e  `7 o" E2 P
  93.         // 重开定时器0中断
    - ^3 z+ {5 x8 N! N5 ~2 z
  94.         ET0 = 1;3 v4 n( m9 ]5 {( M
  95. }7 g# Q/ A6 ]8 M/ u' N, d6 f
  96. + z7 ]7 w: I3 e' R5 E$ p
  97. # t7 i" b+ ^, `' _7 n
  98. void main(){
    : j9 [' ~: h% U3 o  J
  99.         // 初始化P3和P5口8 ^: A/ n" {" O* ]# K% B
  100.         GPIO_Init();5 i% G1 L8 ?3 d
  101.         // 初始化定时器0! n- n: i% @6 a5 t6 |0 Z
  102.         Timer0_Init();) d5 a  q+ D0 O4 \( r
  103.         // 初始化中断
    5 p, F, |( m, B/ N& ?, E
  104.         Interrupt_Init();
    ! U4 F* F( t5 w+ D+ w* i, c% y8 ?
  105.         $ o. U! J# @  ]
  106.         while(1){0 `% @6 l1 G' T/ z# j8 ]
  107.                 // 检测电量
    / o2 ~, C% m3 T6 n
  108.                 if(PCON & (1 << 5)){
    9 K8 N* Q- f: q+ @% q4 e
  109.                         // 如果电量低,低压指示灯亮
    & j* |7 I) V% W- u9 q" m: k) L
  110.                         LED = 0;
    0 {2 E& E# T, J
  111.                         // 清电量检测硬件标志位: o; l1 l  }! q* G! k
  112.                         PCON &= ~(1 << 5);8 @: }8 v4 \! v
  113.                 }else{6 Y' K: I0 I5 W8 g
  114.                         // 电量正常,低压指示灯灭
    3 g6 W, h- H( U
  115.                         LED = 1;
    3 A2 [+ T3 r/ O& X/ L
  116.                 }
    6 r  S& x! a- A
  117. / ?$ L- u( d; G, @: X* j. ]
  118.                 // 检测到停机标志8 ]" U1 d' y3 d9 ^
  119.                 if(isReadyToHalt == 1){0 N+ U7 Q, Z! ?5 K5 p
  120.                         // 暂时关闭定时器0中断
    " h" o3 |* g& H, D4 s
  121.                         ET0 = 0;
    & A; Y7 ?/ z- N" Z, g6 R
  122.                         // 停机之前先把矩形波输出脚置低电平,以方便INT0和INT1唤醒CPU
    " F7 G: M# x* r( ?
  123.                         OUT = 0;
    2 W- n2 @. J( Y" {9 e+ j
  124.                         // 停机之前先把低压指示灯灭掉,以省电
    + y3 X& N8 O/ R* ?
  125.                         LED = 1;
    : n: @9 C5 c8 }/ X+ Q
  126.                         // 进入停机模式
    2 k9 [# B3 Z, B2 M. C9 q# \2 J) S2 \
  127.                         PCON |= 0x02;3 w* [* r+ f4 x8 ]5 r% j7 d
  128.                         _nop_();1 b! ?' ?. C+ X8 u4 q; [4 U& o
  129.                         _nop_();: I" Y5 E  i2 W
  130.                         _nop_();
    ' ]( C! C/ a+ I5 v/ M, S
  131.                         _nop_();
    " d1 a; @" o: U) |  J
  132.                         // 唤醒,清标志位, x0 P( X! s8 e. Z
  133.                         isReadyToHalt = 0;& G. l3 F* F" w. T
  134.                         // 重开定时器0中断
    - n0 U/ w& a2 _7 i) }& i5 e' h
  135.                         ET0 = 1;: A( b2 F* Y# i) |# M; N8 G9 Q& I
  136.                 }
    $ `: o) M% `; l3 o/ ~
  137.         }
    $ O+ z  S- p; J' m
  138. }/ V0 ^1 ?0 v' W6 |0 r& |
复制代码
7 O) u/ F; P4 x6 h( q8 h
硬件参数配置:( R/ S- q! @2 A! F. F* R) _

) @! m( d) v0 z9 T" b; q/ v  Q9 f6 D1 n# G; Z4 d
接收端:7 ~# U: U9 ~% l' Q2 L4 @
  1. #include <INTRINS.H>
    3 X9 N9 j* c0 p. |) w
  2. #include "STC15W.h"
    2 {" b: n. \; A! C1 `

  3. , x; h1 _) s" Q

  4. : @, K: _( \0 V
  5. /*/ G, G: h5 p7 z; o8 n) U

  6. 0 t, G- _% _3 N- n+ e9 _+ I/ X
  7. *---------------------------*: a& t3 Z" C2 n
  8. |1 (GPIO2)         \__/  (GPIO1)16|
    ; m8 ~0 H. V, E% F" g& W8 E( O2 i
  9. |                                                        |
    + ^8 i6 J! J7 \# c! h
  10. |2 (GPIO3)                   (GPIO0)15|
    : ^4 E3 |% m  w; c
  11. |                                                        |
    ) v3 Y( W0 f; c
  12. |3 (GPIO4)                                  14|
    ' z% K7 e% T( J! W
  13. |                                                        |0 f* u8 L/ Y0 r4 W; F! N. {
  14. |4 (GPIO5)                        (DATA)13|9 u: ~/ L- U+ p* _. J, M. J" P9 R
  15. |                  STC15W204S                |
    . ^7 ]6 a, ]5 f0 T
  16. |5 (GPIO6)                   (LATCH)12|5 ]- W2 g! |( S. p' M
  17. |                                                        |
    1 ], T% V5 Z( a& Z4 X& |* x" s/ S4 h
  18. |6 (VCC)                         (CLK)11|# n: B, w0 }5 M4 _
  19. |                                                          |% ]; v/ L2 H& h6 _
  20. |7 (GPIO7)                         (TXD)10|
    7 g1 k6 h1 M, ]  P
  21. |                                                        |
    3 t2 t- Y5 R( E& b" \% U% b7 l
  22. |8 (GND)                         (RXD) 9|
    ' M2 J  [  d, {9 e- S( I( f
  23. *---------------------------*: C! \  z5 O7 G+ k
  24. Fosc = 12MHz$ z$ [- n! c- H$ |6 s/ q; T$ W
  25. 0 H$ O3 i0 _  E
  26. P1.0 -> 上
    3 O$ W3 A& X( `
  27. P1.1 -> 左# _: x+ X" c. a, f( H) ~
  28. P1.2 -> 下; f9 k1 B- d6 H7 ?! q
  29. P1.3 -> 右
    2 c. K7 U; _0 G; x9 q; Z
  30. P1.4 -> SEL
    * L9 k  p  \5 {0 C
  31. P1.5 -> STA
    0 a3 M  D9 i0 N" T1 v$ c2 x- q: z
  32. P5.4 -> B
    + J# L' X0 x3 \
  33. P5.5 -> A; m, u7 q" o# l- w; e7 x& n

  34. " G1 |" z; k& F% ~! L
  35. */0 ~! ~3 c# v8 r2 i3 m

  36. & k8 k' ?: h3 m3 N; L
  37. . c" v3 P2 {; K5 z" a6 [& m6 y
  38. sbit CLK        = P3^2;
    0 t# S) B& T$ T' f+ g! {( Q( L% e
  39. sbit LATCH        = P3^3;# \8 Q- v  {9 A  ^) _
  40. sbit DATA        = P3^6;$ V% l+ a2 n7 M3 J, `
  41. 3 [+ b1 O) z4 |9 v% a: B0 {
  42. bit isReady = 0;
    8 |# c6 [7 e+ Q: J3 {; @2 U
  43. static unsigned char key = 0;+ p* o/ Z& L) d3 y$ O' F
  44. static unsigned char buf = 0;        // 双缓冲。这个缓冲区保存从P1和P5组合而来的键值9 x0 W3 m9 ~; C6 h) y! J
  45. static unsigned char bufReady = 0;        // 双缓冲。这个缓冲区保存上面那个缓冲区的备份. E0 ?# [2 g* ?/ k: `2 i' x9 B
  46. static const unsigned char data mask[] = {0x80, 0x40, 0x10, 0x20, 0x01, 0x04, 0x02, 0x08};        // A B SELECT START UP DOWN LEFT RIGHT。为提升速度,这个表放到RAM中% R5 X: U5 Q$ S$ J1 ~; N* X4 J
  47. static unsigned char idx = 0;
    ' P; s' h% o$ l. `
  48. * j& `; t1 |9 t' I
  49. ! o# G. o. S3 i" X% S3 X
  50. static void GPIO_Init(){
    4 F; K) p$ D! i7 z" h$ m! T
  51.         // P1口和P5口用于接收并行信号,全部初始化为准双向,依靠内部弱上拉输出高电平* S$ ^6 R" [% `8 G  R7 Y
  52.         P1M0 = 0;
    7 g# `) e, U' e! o( w) [
  53.         P1M1 = 0;
    8 H# s. F$ H& T: c
  54.         P1= 0xFF;6 m/ _6 O# y! `1 A
  55.         P5M0 = 0;
    0 g6 f! [) Q" f$ o+ D+ y
  56.         P5M1 = 0;6 A6 B, Q# j: W" |' q  P: _
  57.         P5= 0xFF;
    / F+ J8 g- |$ [' ?$ s# W
  58.         // P3口初始化为准双向
    5 @  }8 \) c: \2 v. S! h
  59.         P3M0 = 0;
    . T  f. [& G& D" \
  60.         P3M1 = 0;
    : v- q' e5 d, ^, k3 X: ]8 V9 ?. b, b
  61.         P3 = 0xFF;6 x6 l4 z; M  m0 B+ g2 \+ K, k/ r
  62. }% l: v4 R8 t6 @' K

  63. - z/ R* X; \9 _
  64. static void Interrupt_Init(){0 i( L; y$ D& `; W+ V
  65.         // INT0中断(CLK)触发类型为上升沿+下降沿0 Z  K, m1 `, j% R) a2 M* K
  66.         IT0 = 0;3 W& O; i3 ~1 G' V2 \8 c
  67.         // 允许INT0中断( }8 U2 ^( i  C5 x1 j4 ]: ^
  68.         EX0 = 1;
    1 N8 H3 X2 z6 J+ \+ E
  69.         // INT1中断(LATCH)触发类型为上升沿+下降沿
    * T& M0 {; ~) U) |1 {7 i
  70.         IT1 = 0;' Z0 j% l" b* Y
  71.         // 允许INT1中断. U1 ]8 c5 V/ U1 _) Q2 ~$ A" M
  72.         EX1 = 1;( Q, `! H3 o: H: H1 [- _
  73.         // 开启全局中断0 G) p5 q6 G! N# [
  74.         EA = 1;
    - N" l1 b! Y( `- G
  75. }
    9 \" W4 f* r0 ?1 y' h6 d4 E( r
  76. ' H0 v$ I, n+ k, n! M( v
  77. static void INT0_Isr() interrupt 0{# M9 s( G2 {: V0 W) W7 L
  78.         // 只有已经成功锁存才允许CLK移位
    % b' [+ f7 I/ W9 V: v6 ~; Y  i
  79.         if(isReady == 0)
    $ i" k% M7 R8 Q2 i9 ]: H2 C0 @
  80.                 return;/ d6 R  W5 m( d
  81.         // 读当前引脚电平,如果是低电平则说明是下降沿,此时直接忽略该中断
    ) Z7 ~. u$ Z8 n; Z+ w( `
  82.         if(CLK == 0)4 v3 l; O3 K/ z+ c5 m" b
  83.                 return;" `( X5 u; s1 L; {" ]* b' x! x
  84.         // CLK上升沿到来的时候,取锁存值的下一位输出
    1 s5 [  U8 _; }; Q1 Y
  85.         idx++;
    2 a9 w" B8 w# S! S/ v7 j
  86.         DATA = key & mask[idx];6 i; A5 h% _! V9 |
  87.         // 如果已经完成7次移位,则一轮读取完成2 u0 p4 \- s2 U8 ~% ]. e# l  g5 K5 `' N
  88.         if(idx >= 7)
    6 l8 y& ~" a$ i) y3 `3 _* f
  89.                 isReady = 0;
    / V* y* I; D! r
  90. }
    5 V5 W3 c1 o5 A3 w
  91. : z) e. l* |" U
  92. static void INT1_Isr() interrupt 2{! J8 j3 P# \! {! S# ?
  93.         // 读当前引脚电平,如果是低电平则说明是下降沿,此时直接忽略该中断1 J' x* P% d! m' r4 |$ R
  94.         if(LATCH == 0)' B& u' O8 v- J& O
  95.                 return;
    * x- Y# ^; L4 A% u5 s! V
  96.         // 当LATCH上升沿到来的时候,锁存所有按键状态,同时把键值A输出到DATA4 i3 B$ k( K- r; i1 Z5 U
  97.         key = bufReady;
    7 y% q0 Q2 M9 |: e0 U5 \
  98.         DATA = key & 0x80;//mask[0];        // 为了加速运算,直接取表中的值而不是读表
    3 U9 t9 J; C  E" R; b( v
  99.         idx = 0;- Q- f' o$ l% B, y! n, a
  100.         // 允许CLK进行移位  _8 p! t, F" v7 P* _
  101.         isReady = 1;" M5 Z7 w2 P; E3 Y( h$ C
  102. }9 q: ]7 N% y$ n  O3 M) \9 E

  103. 5 k) f4 v' m! _/ z$ p- K3 M8 p
  104. void main(){
    2 Z; D  V6 N! U
  105.         GPIO_Init();" ~. ?. t7 b, w$ f
  106.         Interrupt_Init();4 G; v# d% M. X/ t
  107.        
    9 Q: V9 p) q) U  k# C
  108.         while(1){
    ( y" f; ], m+ P) |3 W' x. s7 q
  109.                 //PCON |= 0x01;        // 进入省电模式
    " ?+ ^4 {# ~3 f5 u1 |
  110.                 //_nop_();
    % Y  R- i6 P  D
  111.                 //_nop_();
    " B$ R. R, U: S: D* F% s1 l: }
  112.                 //_nop_();- W+ {) `: h! n; e
  113.                 //_nop_();
    7 W# n6 {8 ~& |" i* k
  114.                 buf = ~((P1 & 0x3F) | ((P5 << 2) & 0xC0));: a8 I: ~* i$ @9 U7 b
  115.                 bufReady = buf;
    - J. `: p* q2 `& o
  116.         }8 ^( ]7 I0 Q( D! `3 Z
  117. }% A  n0 I; _2 K- [" S" b+ U1 P- q
复制代码
& w2 H: Z5 n( P! j! c0 X
硬件参数配置无特殊要求,晶振频率选择12M即可。+ k# }! U0 O( W. p- O
7 N, L0 F4 H' Y, U! 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
4 D0 f9 A! |* j9 \不错的设计,想问一下楼主,FC的15针公头怎么解决?普通的公头太短了,插不进去FC的扩展接口。 ...

5 h! {+ m8 T6 W坛友的改造方案
回复

使用道具 举报

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

使用道具 举报

发表于 2019-5-25 12:07:18 | 显示全部楼层
精彩,楼主动手强,也写得很详细。: Q$ m1 _! ?+ n5 S: n
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
4 w: C+ j8 E4 m. x精彩,楼主动手强,也写得很详细。
5 `* b- {5 @8 [( q/ i2.4G方案是目前无线的最低延迟吗?
. }* m* K: `) `) g9 m" i7 B# `
我没用过其他无线手柄,所以实在不知道我自己做的这个手柄到底是不是最低延迟。
3 S, g8 `/ u) Y4 T不过根据网上的说法,延迟高低主要是由通信协议的复杂程度,以及数据传输速率决定的。这个模块虽然是2.4G无线模块,但由于协议很简单,所以延迟比较低。
8 M3 ]5 L( k/ d4 [* v0 z我用这个手柄玩一些ACT游戏,比如超级马里奥、忍者龙剑传、热血系列,完全感觉不到延迟,和游戏机自带的手柄没有任何区别。唯一的区别就是这个手柄是用火花山寨手柄改造的,外壳是垃圾回收塑料,粗糙+脆弱,导电橡胶弹性不佳,手感不是一般的差。- a- l! p* a% E4 K
我手里还有十几张板子,等我有空了我再做一套,到时候买一个好一点的手柄改造。
回复

使用道具 举报

 楼主| 发表于 2019-5-29 16:56:14 | 显示全部楼层
ppad 发表于 2019-5-28 17:27% B0 k; A& {5 v2 u# b- d' ?0 D
给技术帝赞一个,有半成品发布吗,自己焊接改造就可以,编程实在不会啊 ...

+ }& T8 R! M" p6 S- N5 y6 T( P0 h很可惜,我手里没有多余的单片机了,LDO也找不到了,锂电池以及充电模块更是没有了。反正就是该用到的元件基本都没了,所以没法发布半成品。; n& b! o: {. e
两个板子倒是有十几张剩余。
2 i6 ]- G  M" L5 L; D你要是有USB转TTL串口板,完全可以自己买这两种单片机,然后我给你编译好的固件,你自己用串口板下载到单片机里面就行了。两个2.4G无线模块也得通过串口板用AT命令设置参数,不过好在我在设计电路的时候就已经预留好了串口,可以直接在线下载和在线设置参数。总的来说并不麻烦。
回复

使用道具 举报

 楼主| 发表于 2019-5-29 17:00:34 | 显示全部楼层
孙大师 发表于 2019-5-28 18:55
, b( H  t* a/ R3 d- n: [7 n. V非常好,楼主是技术帝,到目前我都还没开发fc的无线套件,等空了,开发一套套件,等玩家自己组装。 ...
: _0 j! _! i' j) d
能得到孙大师的赞誉,不胜荣幸!2 t3 ^! v$ Q; K
不如开发一个多功能手柄,比如用SFC手柄改造,L/R键配合其他组合键可以用来切换2P~4P、调节连发速度、软重启等各种功能。接收端插到15PIN扩展口。
回复

使用道具 举报

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

本版积分规则

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

GMT+8, 2026-6-21 11:31 , Processed in 0.103872 second(s), 15 queries .

Powered by Discuz! X3.5

© 2001-2025 Discuz! Team.

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