找回密码
 注册

QQ登录

只需一步,快速开始

查看: 21566|回复: 27

自制FC无线手柄

  [复制链接]
发表于 2019-5-22 14:16:45 | 显示全部楼层 |阅读模式
本帖最后由 雷精灵2046 于 2019-6-14 09:28 编辑
2 b! |. c* M* [( W4 L
) n! d- r6 V1 Q' n4 Q! Q$ K' y没有用复杂的分立元件搭建发射接收电路,直接用的现成的2.4G无线模块jdy-40。
- u4 g' H% j- v
7 A( g# f! z% p7 x3 T! m
( z9 J9 q% H5 O# [* p( W发射端靠3.7V锂电池供电,用了一片SOP8封装的STC单片机,负责产生连发脉冲,同时负责检测电池电量,电压低于3V左右的时候触发低压中断,低压指示LED就会亮起来告知该充电了。平时发射模块和单片机均处于睡眠状态,有按键按下才会唤醒,从而实现省电。实测睡眠状态下整机电流约1~2uA。板子洗了一下稍微干净了一点。因为对于微功耗设备来说,焊接残余的助焊剂可能会增加漏电流。5 f" B9 i6 b; g
& _7 \4 ^) C# a* t3 H4 A' L
买了一个火花的FC山寨手柄,去掉里面的牛屎板子,并修正一下塑料挡板,把锂电池和充电模块装进去。
& Q. Q. P* r! n' w( S' j% |为了减少体积,充电模块裁剪得十分小,并且更换了充电电阻使之适应这个小小的锂电池。这么小容量的电池,也不需要多么大的充电电流是吧?% r; \& V( R+ p4 y- S- X
然后统统用热熔胶粘上。充电电流比较小,所以发热很少,不会熔化热熔胶。# _) u2 @% m9 t4 B, g; j) e8 ^

8 y* m7 ~; H% {- @! i4 n) ~. }1 m* d) N7 c$ M5 z7 _
9 f- q& r3 ~0 f- P' F1 q  a
最后把按键、导电橡胶和电路板装上去。
& V7 Z# R1 N+ c- k3 S) K精心裁剪了电路板,正好扣上,不会阻碍其他元件,也不会影响后盖和拧螺丝。, i$ ~0 G! B' k6 P* [% A- Z8 b
$ W  M4 {" d1 F

  |% m, N1 E7 G, r完工!
% i; k* R0 W; i$ x
, w" v+ p, S8 n  E. ~$ H/ c. d5 y" j. p) k1 Z2 }
这是充电的MicroUSB插座。旁边的小孔用于透出低压报警LED的光线。
  I9 ?4 t+ `2 {& e: i% c; g, W; \1 X* A) H

5 G) Q. \+ d3 h5 @/ `接收端用一片DIP16封装的STC单片机模拟CD4021。为啥要用单片机模拟而不是直接用CD4021?因为jdy-40模块接收端在有按键按下的时候输出高电平,无按键按下输出低电平,和普通手柄正好相反。当然我也可以用两片74HC00或者74HC04之类的逻辑门进行反相,但那就增加了芯片的数量。对于FC手柄这种工作频率并不高的设备来说,STC单片机完全可以胜任模拟工作。, @) l7 B5 W, \0 c& Y0 v

2 j% R5 _' }; \+ d
/ W4 V2 T) V0 G% c. U: \+ B+ _/ @: J/ ]/ w; J. Z
电路设计有点小小的错误,所以有几根飞线。原本设计使用低压差LDO是XC6206,结果在做这个接收模块的时候,买的LDO居然找不到了!无奈只好用了AMS1117。幸好对于接收模块来说是5V降到3.3V,1117可以胜任。要是发射端手柄的话,3.7V降到3.3V,那就非得用6206不可了。% E; J* k9 ~5 k7 \
5 V/ \7 b' t& p7 V
实测十分灵敏,延迟极小几乎感觉不出来。可惜这山寨手柄的手感并不佳,尤其是方向键,软塌塌的。看来我得买个剪线手柄改装。
' Z7 t- J1 |8 m8 A$ R6 ~" M$ Z2 a
, N0 }# W) i" T! ~这是电路图,有兴趣的朋友可以参考。
: |, O$ t5 c9 J8 o
  X* [& f) ~$ {
- W. }2 K/ X1 O我信奉开源主义,十分痛恨把技术藏着掖着。好东西大家分享嘛!所以两个单片机的源代码大公开!  H2 @( t  D! i7 P5 q, A8 Y
编译器:Keil 51。% A; _6 P4 q# p0 ?+ T, L

& I; Y) C9 K+ c/ M发射端:
1 ]7 c- C+ v4 d9 @
  1. #include <INTRINS.H>
      r# o  f9 O8 r% O
  2. #include "STC15W.h"
    - c) X/ J9 k4 L1 ?3 H5 p

  3. 3 o# g9 p, U2 i2 s  \

  4. 7 j, R; u! z: i
  5. /*. V. S8 k8 k$ b+ L
  6. --------------------------8 R! r/ [) H  \% U! G1 k
  7. |1 (OUT)        \__/   (INT1) 8|7 e4 X/ _, ]& O! c  @- y
  8. |                                                   |
    " g, y0 g: M3 J" S
  9. |2 (VCC)                   (INT0) 7|! j4 s- n% V# V! f. O5 I
  10. |                 STC15W204S                   |( g+ Z" I+ x3 I" R  v" h* _
  11. |3 (LED)                         (TXD) 6|. J2 Y1 F. l9 N/ Y2 d/ T, Y& b
  12. |                                                   |
    : _* R/ S2 C; J/ X6 X
  13. |4 (GND)                         (RXD) 5|7 P7 C6 x: A* X7 V
  14. --------------------------$ P6 ?5 D5 c& Q: ?+ s7 Z
  15. 3 h. E: B5 [1 j& h- q2 [
  16. LED ---|<|---[===]--- VCC
    0 q" ?. {: W3 O1 V4 d5 E: s9 ~
  17.            Red          330
    / v( a% B( @9 S

  18. * P1 S& _% |1 Q1 q3 ?7 I% O
  19. Fosc = 6MHz4 X5 [" x) }: Y* ?3 T7 j' T
  20. */5 p0 |5 W' n  x% x  i1 ~
  21.   J- V: b2 o1 R3 e$ _  E; k8 @
  22. ; X" |7 R% S* N1 p' c; Q
  23. // 矩形波输出脚5 G* a) y% }8 M# I# j+ j
  24. sbit OUT = P5^4;
    # O  [( [, H* x) b$ }% \
  25. // 低压指示灯引脚
    - n3 }' w7 w* w- x
  26. sbit LED = P5^5;
    8 @; G/ V& O- C2 A. c
  27. 1 e+ V. ^$ m8 i* M
  28. // 停机标志位1 V  u  }* r& k0 @. V: G
  29. bit isReadyToHalt = 0;, A+ G9 V# O  f
  30. ! C( s* N8 v7 A1 U) g5 I- {1 _1 w
  31. // 矩形波次数累计
    # ~1 q. y+ u$ ~" ^# N1 g0 V. d2 k7 ^
  32. static volatile unsigned char count = 0;
      M2 f' R9 C& Y0 [' P1 w: C; k0 N; F/ `

  33. / |  Q0 X; Z0 C& \) P! R
  34. % p* q6 K# ~9 z8 |" c2 i  f
  35. static void GPIO_Init(){
    . S; F3 v+ y' ]5 Q5 b+ R; J* _
  36.         // P3口设置为准双向,默认靠内部弱上拉输出高电平; B' |8 q8 p1 f& e4 ^
  37.         P3M0 = 0;8 m6 b! ?/ Z, q. Z5 E; J
  38.         P3M1 = 0;
    " s# i0 y4 l' _( C1 M% p: n- h0 e6 A8 n
  39.         P3 = 0xFF;; \* z# v) |$ X# I) W
  40.         // P5口设置为准双向,默认靠内部弱上拉输出高电平
    0 [( H8 P1 ^) y0 q: g
  41.         P5M0 = 0;
    5 b: ^9 |/ U6 \* M$ ]$ K; k' p
  42.         P5M1 = 0;, V( |: w1 H% E8 M
  43.         P5 = 0xFF;
    0 L: G& T2 ?1 B" k
  44. }, h. ^; X: e5 I9 d& X

  45. 9 M' f: A& d) R& j; s& x! r* U
  46. static void Timer0_Init(){
    6 I1 `5 N* q% D- ?8 S$ j6 l
  47.         // 16毫秒@6.000MHz
    - y4 J( ?6 a0 W# A$ F% \, o
  48.         AUXR &= 0x7F;        // 定时器时钟12T模式
    " U7 i% {  ^; j0 w3 }' r+ h% [
  49.         TMOD &= 0xF0;        // 设置定时器模式% Q, w% o+ O& l. t! }) d; ~! h
  50.         TL0 = 0xC0;                // 设置定时初值* \) o2 v" a3 ?! @1 B& J6 ^
  51.         TH0 = 0xE0;                // 设置定时初值$ ~/ s: d: Q3 {& A, d  [7 Q
  52.         TF0 = 0;                // 清除TF0标志
    2 |3 C$ e$ e& z8 S3 t1 I( h: V* |$ f
  53.         TR0 = 1;                // 定时器0开始计时
    ; |$ P8 _3 ^8 ~1 R
  54. }. v$ s: s8 o8 c

  55. ! t+ B; I8 [1 m
  56. static void Interrupt_Init(){* D+ Z4 i- V; m: K( g- ]
  57.         // INT0中断触发类型为下降沿触发
    ! ^' v- j/ }: s) p
  58.         IT0 = 1;
    $ W3 y4 t* A# w* a' R, X
  59.         // 允许INT0中断
    " d0 J  f- T8 ~5 A& v6 Z
  60.         EX0 = 1;7 b0 {- J& l5 Y1 v0 `+ }# U; O
  61.         // INT1中断触发类型为下降沿触发
    ) v9 K! n( }6 P: o
  62.         IT1 = 1;0 n3 o7 l! J; ?  B& u
  63.         // 允许INT1中断1 k7 `3 d+ j6 Q" o$ N* a
  64.         EX1 = 1;
    * P3 w) J" I: v1 x
  65.         // 允许定时器0中断4 ~) ~8 J: B9 G1 y% y
  66.         ET0 = 1;
    / {7 x( {! Y5 _# \4 m4 L! b. \2 v
  67.         // 允许全局中断
    8 f' l* S& D/ ^
  68.         EA = 1;4 i; x) P' I7 c) ], q# z8 T9 Z: b
  69. }6 G) m: v4 D. Q) T

  70. 3 Z: G3 A6 H3 D. S/ O
  71. static void INT0_Isr() interrupt 0{
    ! @/ T( ~6 G' _$ m
  72.         // 矩形波次数累计归零
    % U7 `/ V: w! E+ s
  73.         count = 0;) F# Q* B8 ~7 }; B' @# p3 G
  74.         // 重开定时器0中断
    " A) m. K; Y* s4 z+ V
  75.         ET0 = 1;
    2 L$ z; ]0 |, T* R$ g
  76. }
    0 z( b. r5 u, R: p6 R9 D

  77. 4 q3 ~8 F$ O. r+ P/ A* p+ w8 \
  78. static void Timer0_Isr() interrupt 1{
    ! U9 H0 p$ T+ A) p: e1 H" [$ y! j
  79.         // 输出矩形波
    6 ~- v, z3 ?" g& l1 D) l6 L/ ?
  80.         OUT = ~OUT;
    7 z! A; q0 t5 \! P, P3 e
  81.         // 累计矩形波次数
    ) t( O. F( L* Q4 i; R% M' L- m
  82.         count++;- |! M1 j2 _+ v6 S% F# _' [5 O  v
  83.         // 超过250个矩形波,准备停机( @% |0 z7 ?4 Z; l- K6 w
  84.         if(count > 250){( I5 v4 b9 z2 I3 q! w
  85.                 count = 0;. P9 M* |1 W' F
  86.                 isReadyToHalt = 1;: @' c5 n7 P$ z" f8 a7 r! l
  87.         }
    ! f  P1 w. `( p$ Z" N
  88. }
    . T" U2 P; o- f

  89. 4 P: v! A- M; ?$ r1 [; y
  90. static void INT1_Isr() interrupt 2{' J9 }5 G6 ~% h* q0 B
  91.         // 矩形波次数累计归零
    & {: C+ t: _0 I+ Z' s! c
  92.         count = 0;  m# ~( v3 z# ?, K( _
  93.         // 重开定时器0中断
    0 o5 i* q( b2 M
  94.         ET0 = 1;
    . b- d5 g9 M. P, Q6 l
  95. }* t( P+ X8 J% }( s7 i" Y
  96.   N! @- b/ ]+ ?. j" F4 R
  97.   z7 W) z. |" c) `8 B1 W8 F
  98. void main(){
    ' L) k, |, x$ U  f: y  B
  99.         // 初始化P3和P5口& H2 z% z! k0 k9 ]$ ]/ |
  100.         GPIO_Init();
    , S9 V: l. g# y7 I3 F* h' ~
  101.         // 初始化定时器0
    ) w5 C( m& X7 a, H& Z7 V
  102.         Timer0_Init();# z0 E4 Z# t6 f; G% f! U
  103.         // 初始化中断
    # P$ d1 g. P( ^* L2 V" {
  104.         Interrupt_Init();6 n$ |* i' _& M3 a4 s' K
  105.        
    + v  U4 c6 w. Q( G
  106.         while(1){
    3 F0 L( w! I  a- T2 Z
  107.                 // 检测电量( P9 e, _7 y* Z6 t! c% ?3 ?
  108.                 if(PCON & (1 << 5)){
    " l% Q7 X: N  V3 L" ?
  109.                         // 如果电量低,低压指示灯亮
    8 M4 P+ h. {) n% M8 K
  110.                         LED = 0;2 _9 n, h8 C. T, B
  111.                         // 清电量检测硬件标志位
    ) c, Q0 D% v: b+ B% e  @5 {
  112.                         PCON &= ~(1 << 5);# v- `) K) `' ?9 i
  113.                 }else{
    , c6 [. {9 e" B- c) e
  114.                         // 电量正常,低压指示灯灭
    0 {! b0 Q* b! j! }4 c1 a, c: M
  115.                         LED = 1;' ?6 t) e+ a# m) r. c
  116.                 }! I3 R. F2 P: c2 _- @. D. ^
  117. ! q4 ]9 F) k& \- R! X
  118.                 // 检测到停机标志2 _4 _/ ]. t+ r' ?8 }
  119.                 if(isReadyToHalt == 1){9 e% [% M" p! s$ w4 S3 m6 Q( Z* ~
  120.                         // 暂时关闭定时器0中断
    1 `: M0 g8 F" ~. c; d$ X
  121.                         ET0 = 0;- D* _0 G6 {- C
  122.                         // 停机之前先把矩形波输出脚置低电平,以方便INT0和INT1唤醒CPU; H3 M3 [; ~% e# N2 q' R/ P
  123.                         OUT = 0;7 Y5 y6 i* R$ H! Y+ Q
  124.                         // 停机之前先把低压指示灯灭掉,以省电
    % s/ _0 p; B9 K% _4 T
  125.                         LED = 1;
    1 y7 i( J, l  K! J  O  v' G2 ?, ~: r7 `
  126.                         // 进入停机模式7 z/ P/ Q+ ?  q6 {% v4 l+ F# j' C, ?
  127.                         PCON |= 0x02;0 r6 Q/ H  W0 r5 j
  128.                         _nop_();
    $ H: T' W' A" h4 q
  129.                         _nop_();& m! Y0 p. h% e% \+ S
  130.                         _nop_();5 J! `- m/ Z4 v  F3 O( Q8 K
  131.                         _nop_();
    & h% X) t/ q7 _( J4 y% X, |% n
  132.                         // 唤醒,清标志位! B+ J9 m- h2 q3 A* @' i  f& W
  133.                         isReadyToHalt = 0;
    8 [6 b. Q1 d, {" `0 e+ H
  134.                         // 重开定时器0中断
    # V( `! S" M$ R' t8 V( r
  135.                         ET0 = 1;: [* m- L; P! b1 |9 k0 x, F
  136.                 }! E- \/ L7 K, k$ _6 ]' V4 {
  137.         }
    + y% b8 n$ v7 k' \# ?' r
  138. }/ ~) o/ h9 J+ o- {9 h. B( v, ]
复制代码
" w8 Z2 k2 |& T6 r# q4 K
硬件参数配置:
5 ?4 P( d* k$ a- t: y3 ~9 l  l4 ^6 v3 G* m5 S; i

) D% L/ }$ s& R5 M: S7 q0 h接收端:7 O5 X% U# p+ u! E
  1. #include <INTRINS.H>+ p# L8 c+ H7 Y: n2 R
  2. #include "STC15W.h"+ V- o0 A2 L5 O& u
  3. # w. O( n6 X  I; p. a, J5 Y
  4. " B* c( j/ W8 A* `; {$ p! k, R
  5. /*
    7 N$ }  n' W$ h

  6. - ^" R; J+ g" h1 N
  7. *---------------------------*5 [' b/ v9 {* k- W% V1 \
  8. |1 (GPIO2)         \__/  (GPIO1)16|6 D' b9 C! b1 q3 T/ i$ h' j
  9. |                                                        |/ X1 m( W) P7 r4 E' Z! t0 T4 c, @
  10. |2 (GPIO3)                   (GPIO0)15|
    9 x1 t: B  p; C3 S. e/ G
  11. |                                                        |" w7 v$ Y- m8 X' c9 h2 @
  12. |3 (GPIO4)                                  14|
    7 M- j2 I1 o3 e. P+ }- k
  13. |                                                        |6 V; [9 W$ \, y6 `' b8 ^
  14. |4 (GPIO5)                        (DATA)13|
    6 H. V6 B+ m5 r; u8 s; f
  15. |                  STC15W204S                |
    4 w  u+ U" |. K9 n
  16. |5 (GPIO6)                   (LATCH)12|
    8 Y) ?! T; k# E9 X/ }0 ~9 l- y
  17. |                                                        |4 J1 c  \. z( e  B+ e3 C4 g
  18. |6 (VCC)                         (CLK)11|# \& k; p' I7 p6 x! f3 j7 F
  19. |                                                          |
    ( J# ]( y6 j8 M5 W4 w7 m9 O% ^
  20. |7 (GPIO7)                         (TXD)10|
    8 y3 T+ [4 n4 q" r+ y
  21. |                                                        |
    # a5 }" z  C- R8 R$ {  W6 `
  22. |8 (GND)                         (RXD) 9|( ~, @) I: A$ I; v* y$ a( e8 _- N. @
  23. *---------------------------*! n! O+ y% J' t( z
  24. Fosc = 12MHz  k4 F) s* p  [1 M6 m5 _

  25. , s! q  o* c, g- _2 W9 n
  26. P1.0 -> 上; F/ h6 {( e" E
  27. P1.1 -> 左4 V5 G1 I; O8 g8 {
  28. P1.2 -> 下
    - V/ d; ^- K& _, N. Y- u( }% ~/ d0 U
  29. P1.3 -> 右7 r: _% E" B* W0 d
  30. P1.4 -> SEL6 i+ ~8 h( c& y5 b
  31. P1.5 -> STA9 U$ s, _3 z) n
  32. P5.4 -> B
    2 P! C% L8 U  ^: T
  33. P5.5 -> A# g! K5 J% w+ D6 t( |# d+ v+ Z

  34. + |+ ^8 S- I$ U  h2 u! k7 F
  35. */( h1 R5 L6 x" u9 h1 J8 [7 l/ I
  36. . z% b  t0 _3 M# ]2 ~  `4 V

  37. + G9 k+ N+ R; d
  38. sbit CLK        = P3^2;7 N: k- Z+ v- l  h. i( S+ d, Q+ {
  39. sbit LATCH        = P3^3;& C0 @) ]9 S6 e1 u& v/ a
  40. sbit DATA        = P3^6;6 _7 y& W' k1 J; M1 L

  41. ( n1 h$ A* I, e, E& @
  42. bit isReady = 0;
      x4 F, {' Q8 z/ K% I) v
  43. static unsigned char key = 0;
    # B4 u8 @4 K' {9 g# K  ]
  44. static unsigned char buf = 0;        // 双缓冲。这个缓冲区保存从P1和P5组合而来的键值( n1 G! r% [4 O
  45. static unsigned char bufReady = 0;        // 双缓冲。这个缓冲区保存上面那个缓冲区的备份! p' i4 ~- F6 p6 j- @" t$ i0 A& L
  46. static const unsigned char data mask[] = {0x80, 0x40, 0x10, 0x20, 0x01, 0x04, 0x02, 0x08};        // A B SELECT START UP DOWN LEFT RIGHT。为提升速度,这个表放到RAM中
    ; o" p  t3 O/ S4 [- w
  47. static unsigned char idx = 0;
    * `/ S* k4 K  F  u

  48. 2 I2 c+ s# P2 g+ h( ^! ~
  49. ! u8 O) [/ T5 B" m. d0 Z
  50. static void GPIO_Init(){2 d, ]. @0 `8 ]% K; h
  51.         // P1口和P5口用于接收并行信号,全部初始化为准双向,依靠内部弱上拉输出高电平
    - b7 ^. @) y6 N; b
  52.         P1M0 = 0;
    4 {0 V6 B7 v$ N- P8 @0 e4 H
  53.         P1M1 = 0;
    5 l; n+ x3 v2 P3 b7 _
  54.         P1= 0xFF;
    + [  b; C- z' @. S8 n
  55.         P5M0 = 0;
    / Z! V0 }- _$ g* s# U# R8 @3 L/ R
  56.         P5M1 = 0;8 ~7 {; }6 P0 H( f6 `3 }
  57.         P5= 0xFF;
    $ v. p& [: Y7 M' ~8 P, V- M
  58.         // P3口初始化为准双向, a1 Y; N1 d/ ~
  59.         P3M0 = 0;' A; x. j: z  o- A4 b& ~# D8 l# [
  60.         P3M1 = 0;  h' P3 d& E& Z6 i: w
  61.         P3 = 0xFF;
    8 }$ p! a: p) R7 ~- D& g! x
  62. }" Y: n; k) v* J6 Y  I5 x4 a

  63. ' @4 [) h5 Q6 n. O4 D3 B* N, q5 p/ J
  64. static void Interrupt_Init(){8 U2 @9 G+ [3 U0 |, |" E
  65.         // INT0中断(CLK)触发类型为上升沿+下降沿
      j& t  v( s  o$ J7 h) F
  66.         IT0 = 0;
    0 i8 B2 W! w! \" ?( A5 Y; Y
  67.         // 允许INT0中断3 x; \( S; \/ }* V8 z; n& B8 B
  68.         EX0 = 1;
    7 p" t4 A( v- I1 s: [) b" c
  69.         // INT1中断(LATCH)触发类型为上升沿+下降沿: m! b' i5 W0 Q4 L- P
  70.         IT1 = 0;
      f# D  q. U( E
  71.         // 允许INT1中断
    / V3 F  L& Y9 v$ o) M
  72.         EX1 = 1;
    ; \9 C6 }) {# p, [% E! v
  73.         // 开启全局中断; Y# ?  L+ K# ?. @& M
  74.         EA = 1;
    - e$ p9 }4 A8 b' R
  75. }
    1 S: a8 I1 s% z4 O

  76. - P7 }0 a( i- X5 B
  77. static void INT0_Isr() interrupt 0{6 M. [6 k5 R2 d6 d7 n  A
  78.         // 只有已经成功锁存才允许CLK移位) }. q; J( g& V& R, V% ^- {' V
  79.         if(isReady == 0)5 Q# n9 V4 L# t3 F  A3 w
  80.                 return;8 R2 Z; G# R9 P! a9 l! O
  81.         // 读当前引脚电平,如果是低电平则说明是下降沿,此时直接忽略该中断
    . v3 s( @4 T; }' X
  82.         if(CLK == 0)
      l/ b! ?% @+ T1 e6 K$ L
  83.                 return;8 |( d* S7 R+ B5 o& c+ v" J
  84.         // CLK上升沿到来的时候,取锁存值的下一位输出
    9 l( ^8 G( D% F
  85.         idx++;/ p/ Q) A  V% U/ N( D
  86.         DATA = key & mask[idx];
    7 b* q- w  J* x" S# E  s
  87.         // 如果已经完成7次移位,则一轮读取完成1 _& I! U% x+ c
  88.         if(idx >= 7)% c1 H0 K$ O# p! y& y( |2 H* p$ c
  89.                 isReady = 0;! ~7 l4 U' [+ I! V. @9 `  z
  90. }7 ?5 A; O8 f% S* Y

  91. ' H: Q& V: Z1 h! \( C
  92. static void INT1_Isr() interrupt 2{
    ) B2 r: @1 i9 f: S- c( M
  93.         // 读当前引脚电平,如果是低电平则说明是下降沿,此时直接忽略该中断
    ; r/ f, \2 k2 Z) F
  94.         if(LATCH == 0)
    ' C0 i3 u  Y- |6 l: L# |$ d" t
  95.                 return;
    . _: |1 `$ N9 j( i4 ]! m9 x
  96.         // 当LATCH上升沿到来的时候,锁存所有按键状态,同时把键值A输出到DATA) o: g1 ~# g5 L1 p7 b; l. N
  97.         key = bufReady;
    & W2 J' a: U7 ?9 e  E6 d& G
  98.         DATA = key & 0x80;//mask[0];        // 为了加速运算,直接取表中的值而不是读表
    - V* T3 ^* ~9 O
  99.         idx = 0;) P8 f; J2 p8 C8 m" f3 O
  100.         // 允许CLK进行移位! O* A6 X) r$ {2 o" T5 c
  101.         isReady = 1;
    5 p5 o2 f/ u! i6 n* B! `
  102. }
    * ?, ]6 a$ T  r: W9 V" B5 u

  103. 3 u: I; @6 ~- j4 Y
  104. void main(){
    + _$ ~1 K0 g' S. \' ^6 l
  105.         GPIO_Init();
    * I4 V) I9 n# U: r( f6 v! x9 l  E
  106.         Interrupt_Init();
    ' x. u$ W7 Y# B$ d7 q) E. f
  107.        
    - c& j" @8 D3 t
  108.         while(1){
    : G0 v5 y* t) d/ U& I
  109.                 //PCON |= 0x01;        // 进入省电模式6 G- t/ H5 q* W1 @3 e1 d
  110.                 //_nop_();
    . s: j* ~) ^" s8 J
  111.                 //_nop_();# l# z+ `) c/ V# ~% F- f- H6 M4 Z
  112.                 //_nop_();
    $ @: U5 d$ ?! l# Z( G' f7 ]! `" z
  113.                 //_nop_();8 [" M. [& E  l) G. k  x
  114.                 buf = ~((P1 & 0x3F) | ((P5 << 2) & 0xC0));, v# X4 U% V4 G
  115.                 bufReady = buf;
    : S3 n/ G8 j' _; O
  116.         }8 @& L# E; O8 w$ B# t
  117. }2 c) g8 R) e+ V# E4 |/ T
复制代码
3 [, Z, ^) U; M1 e0 c% v
硬件参数配置无特殊要求,晶振频率选择12M即可。/ p8 E& ]/ L: U( a

. b- R, F1 G' G5 T% J- Q这是编译好的固件。

本帖子中包含更多资源

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

×

评分

参与人数 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) L/ F& @0 e! r' O0 V
不错的设计,想问一下楼主,FC的15针公头怎么解决?普通的公头太短了,插不进去FC的扩展接口。 ...

# |, D6 e* E6 @' h. A/ i( l9 a+ V+ u坛友的改造方案
回复

使用道具 举报

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

使用道具 举报

发表于 2019-5-25 12:07:18 | 显示全部楼层
精彩,楼主动手强,也写得很详细。
- S4 @$ V- Q' T& @& F2 m  \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, [- `. g" }3 w" G/ e
精彩,楼主动手强,也写得很详细。. H% k5 {6 |+ _6 v  T# D: J( O) a5 Z
2.4G方案是目前无线的最低延迟吗?
7 L4 O& {4 d  y% \6 b+ F! ~
我没用过其他无线手柄,所以实在不知道我自己做的这个手柄到底是不是最低延迟。
& c0 W( b9 j8 S3 Y) h( k不过根据网上的说法,延迟高低主要是由通信协议的复杂程度,以及数据传输速率决定的。这个模块虽然是2.4G无线模块,但由于协议很简单,所以延迟比较低。- Z8 Q) [- G. O* R3 ^9 e
我用这个手柄玩一些ACT游戏,比如超级马里奥、忍者龙剑传、热血系列,完全感觉不到延迟,和游戏机自带的手柄没有任何区别。唯一的区别就是这个手柄是用火花山寨手柄改造的,外壳是垃圾回收塑料,粗糙+脆弱,导电橡胶弹性不佳,手感不是一般的差。% W) y6 a: o0 u2 i1 I
我手里还有十几张板子,等我有空了我再做一套,到时候买一个好一点的手柄改造。
回复

使用道具 举报

 楼主| 发表于 2019-5-29 16:56:14 | 显示全部楼层
ppad 发表于 2019-5-28 17:27: `& T7 \( {# t% S* N' K  J
给技术帝赞一个,有半成品发布吗,自己焊接改造就可以,编程实在不会啊 ...
! b' _" ^8 c: b4 j# h
很可惜,我手里没有多余的单片机了,LDO也找不到了,锂电池以及充电模块更是没有了。反正就是该用到的元件基本都没了,所以没法发布半成品。% e3 l8 {" d4 G5 U2 a
两个板子倒是有十几张剩余。
1 R; e3 w7 w' m/ N你要是有USB转TTL串口板,完全可以自己买这两种单片机,然后我给你编译好的固件,你自己用串口板下载到单片机里面就行了。两个2.4G无线模块也得通过串口板用AT命令设置参数,不过好在我在设计电路的时候就已经预留好了串口,可以直接在线下载和在线设置参数。总的来说并不麻烦。
回复

使用道具 举报

 楼主| 发表于 2019-5-29 17:00:34 | 显示全部楼层
孙大师 发表于 2019-5-28 18:55
( `$ W8 [$ Q% y( U8 q) t- r8 Z+ V6 y非常好,楼主是技术帝,到目前我都还没开发fc的无线套件,等空了,开发一套套件,等玩家自己组装。 ...

; q  J( n- ~) M9 D, e3 t8 h% b5 `能得到孙大师的赞誉,不胜荣幸!
9 q) E8 U& K& B5 ^% c$ R( c不如开发一个多功能手柄,比如用SFC手柄改造,L/R键配合其他组合键可以用来切换2P~4P、调节连发速度、软重启等各种功能。接收端插到15PIN扩展口。
回复

使用道具 举报

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

本版积分规则

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

GMT+8, 2025-5-10 14:23 , Processed in 0.160116 second(s), 14 queries .

Powered by Discuz! X3.5

© 2001-2025 Discuz! Team.

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