找回密码
 注册

QQ登录

只需一步,快速开始

查看: 25491|回复: 32

自制FC无线手柄

  [复制链接]
发表于 2019-5-22 14:16:45 | 显示全部楼层 |阅读模式
本帖最后由 雷精灵2046 于 2019-6-14 09:28 编辑 6 b6 x6 @: j* G2 }9 T) ^1 S* T+ j

6 t0 H2 |1 U, l2 g1 E; R( ^没有用复杂的分立元件搭建发射接收电路,直接用的现成的2.4G无线模块jdy-40。
( s  Q$ f, {, l% L$ U4 \
8 W! @+ _2 W' K( d! \6 ~- n( ^# {9 C, P1 d1 h, p5 I! D
发射端靠3.7V锂电池供电,用了一片SOP8封装的STC单片机,负责产生连发脉冲,同时负责检测电池电量,电压低于3V左右的时候触发低压中断,低压指示LED就会亮起来告知该充电了。平时发射模块和单片机均处于睡眠状态,有按键按下才会唤醒,从而实现省电。实测睡眠状态下整机电流约1~2uA。板子洗了一下稍微干净了一点。因为对于微功耗设备来说,焊接残余的助焊剂可能会增加漏电流。
  G3 [, L  q' _! e( N& y+ b
9 k9 P8 F9 L( H% _买了一个火花的FC山寨手柄,去掉里面的牛屎板子,并修正一下塑料挡板,把锂电池和充电模块装进去。5 |: C3 }) A' I7 N/ o) H
为了减少体积,充电模块裁剪得十分小,并且更换了充电电阻使之适应这个小小的锂电池。这么小容量的电池,也不需要多么大的充电电流是吧?0 Y7 C& E2 ~+ P( f% _- S
然后统统用热熔胶粘上。充电电流比较小,所以发热很少,不会熔化热熔胶。
9 y) ?, W2 M5 k6 W- t3 V/ V1 n+ F+ x8 ^

/ R, E- _- N, y$ q; N! ~0 |" Z. G
3 A, i' T+ m! h8 g0 e! ^6 z最后把按键、导电橡胶和电路板装上去。5 V# e' k& m4 L& L
精心裁剪了电路板,正好扣上,不会阻碍其他元件,也不会影响后盖和拧螺丝。
7 k& b$ f; J! A( {: h) b9 H/ S6 O6 D5 _6 M

3 y4 [# h6 d. p完工!
# p2 D% i  S8 p2 D6 G- _; x' X: Z5 p& o' g

* w# p+ v# M; `这是充电的MicroUSB插座。旁边的小孔用于透出低压报警LED的光线。
4 g8 h4 K+ j' L4 u9 P1 I5 r* C2 G9 p
6 Z) S% B  X, V
接收端用一片DIP16封装的STC单片机模拟CD4021。为啥要用单片机模拟而不是直接用CD4021?因为jdy-40模块接收端在有按键按下的时候输出高电平,无按键按下输出低电平,和普通手柄正好相反。当然我也可以用两片74HC00或者74HC04之类的逻辑门进行反相,但那就增加了芯片的数量。对于FC手柄这种工作频率并不高的设备来说,STC单片机完全可以胜任模拟工作。# d: v3 d& O, _- c/ Y7 j
- S' m+ R7 Y* g+ d9 J) H$ \1 D

( q# S1 i0 o8 \7 H% Q) D; g1 K5 g. f/ E+ f
电路设计有点小小的错误,所以有几根飞线。原本设计使用低压差LDO是XC6206,结果在做这个接收模块的时候,买的LDO居然找不到了!无奈只好用了AMS1117。幸好对于接收模块来说是5V降到3.3V,1117可以胜任。要是发射端手柄的话,3.7V降到3.3V,那就非得用6206不可了。
9 o/ r& S6 E+ O( L
: `+ j& y$ v3 z. W5 F, s- N实测十分灵敏,延迟极小几乎感觉不出来。可惜这山寨手柄的手感并不佳,尤其是方向键,软塌塌的。看来我得买个剪线手柄改装。2 F/ o! N$ T- O1 U% Q. R3 L
, H2 U  r$ W6 I! B; ~
这是电路图,有兴趣的朋友可以参考。9 @3 j( l& \* |
, j7 B: j+ u$ [( z6 T0 ]2 a
3 r( u9 c+ v9 e& n; K
我信奉开源主义,十分痛恨把技术藏着掖着。好东西大家分享嘛!所以两个单片机的源代码大公开!0 E* h, y$ r; x
编译器:Keil 51。
& x9 n8 o, v% J. v- t/ R7 T  {$ K
; A5 w& l' o. C9 T发射端:# C+ h+ i0 _7 M- U
  1. #include <INTRINS.H>
    7 e' f5 S8 E0 K; Q% p$ U1 T7 q
  2. #include "STC15W.h"
    % h/ ?! N) A/ |* O

  3. 1 @* }% z" ~; K

  4. 2 B! C) o, f& ~5 w9 N
  5. /*# A$ F: x# u2 {# H7 r
  6. --------------------------
    ) ]0 D. \/ y0 }9 C0 i: I5 H$ Q
  7. |1 (OUT)        \__/   (INT1) 8|
    ! U  v* K# i2 S3 M* s( r- J; \
  8. |                                                   |0 W8 `% U; R! h) c
  9. |2 (VCC)                   (INT0) 7|  W7 J( v+ i; M8 M3 h' O" |8 t
  10. |                 STC15W204S                   |( q0 S! {8 L) R5 o$ P
  11. |3 (LED)                         (TXD) 6|; G: G1 B& i' M" @3 O# k
  12. |                                                   |
      s" J" n& p6 k3 g; o
  13. |4 (GND)                         (RXD) 5|
    ) H4 M& u0 g6 d5 w' m
  14. --------------------------
    - ~" t3 R# ]7 S5 m! q" K7 B7 s# ]

  15. 5 K; E0 D" l* Y1 [! I4 O. l  _
  16. LED ---|<|---[===]--- VCC
    + x4 f$ X) I" m6 I& v
  17.            Red          330& o2 I* x% L, N$ f
  18. : h7 o% C) d0 y7 A
  19. Fosc = 6MHz9 ?& a- t2 J' a+ R% n$ ]3 g+ K
  20. */: A8 x, |. R  Z" S4 |  n
  21. 2 }/ }- W. D8 S

  22. . @+ y1 N) X( C
  23. // 矩形波输出脚5 h; B+ |& z7 p, `4 D" A* z" @8 T
  24. sbit OUT = P5^4;5 m% \. b+ n! Y. H' ^8 O. o
  25. // 低压指示灯引脚
    & `  l- D6 j  e; ^( H5 ~
  26. sbit LED = P5^5;
    : B" a: j# E6 r! E' G% `6 |

  27. ( N8 L( H1 X3 H9 W# O
  28. // 停机标志位
    " S7 g; j7 h" G0 ^# h& @9 _
  29. bit isReadyToHalt = 0;
    * b* Z0 I, G% N, V- h0 n  _
  30. ! G5 I% R! b7 H' ?% U! [/ s; ]& s: E
  31. // 矩形波次数累计
    1 q6 o6 N) a- H$ r/ E; c8 B  V
  32. static volatile unsigned char count = 0;+ M, B) D8 ^4 g- ?
  33. ( U. l2 c; k, n) s& {

  34. + u; X  o( X7 [4 t' M5 V) M
  35. static void GPIO_Init(){' I- d' H  w7 y
  36.         // P3口设置为准双向,默认靠内部弱上拉输出高电平1 z9 Z: C5 U/ w5 {( ^8 X8 D: ^
  37.         P3M0 = 0;* k$ W$ V5 D/ |/ w0 |# W
  38.         P3M1 = 0;
    3 t& ~; A& f. ?8 V! e
  39.         P3 = 0xFF;
    3 b' A, L% S! s/ G6 c  W8 _
  40.         // P5口设置为准双向,默认靠内部弱上拉输出高电平
    7 u% k( M$ x, F" u
  41.         P5M0 = 0;
    0 I# [4 u9 ?6 Q) t4 |* B, I+ j
  42.         P5M1 = 0;& N) L4 g' n8 O3 l
  43.         P5 = 0xFF;
    ) B# D7 r2 T/ i+ ]$ H- H
  44. }) W3 n6 }7 M  k7 `, U

  45. 0 Q5 f* K6 g  I* d6 i
  46. static void Timer0_Init(){; B0 V/ G+ [: N  T
  47.         // 16毫秒@6.000MHz
    + B6 [# N8 P4 N
  48.         AUXR &= 0x7F;        // 定时器时钟12T模式
    8 h: `3 Y) O) a! M
  49.         TMOD &= 0xF0;        // 设置定时器模式
    2 g5 e' Y* T, o1 L- ?8 B) {
  50.         TL0 = 0xC0;                // 设置定时初值/ y& I, A8 @: G1 z+ Z, m2 r2 x* L
  51.         TH0 = 0xE0;                // 设置定时初值  J7 l) z5 D- u( S
  52.         TF0 = 0;                // 清除TF0标志! S- i' M% ?/ u" F
  53.         TR0 = 1;                // 定时器0开始计时# M; O, J- u. {
  54. }( \( a% f3 {, E% Q" C) a5 n

  55. ( d# w5 I' Z7 A' Z, h5 {0 c: q" {
  56. static void Interrupt_Init(){
    : ~0 x6 J( p- ^3 k9 W% x) t
  57.         // INT0中断触发类型为下降沿触发9 z: d9 T) \, N0 o* m( e! e, s
  58.         IT0 = 1;# Y8 l, S# f: t% h
  59.         // 允许INT0中断
    / X6 b) p% o4 N6 W8 L- `9 E- x
  60.         EX0 = 1;
    + T/ b1 \/ ?7 o9 ]8 J  o
  61.         // INT1中断触发类型为下降沿触发
    * X. H# T2 @, _% c6 X
  62.         IT1 = 1;8 f  ~5 h: Q: y+ u
  63.         // 允许INT1中断! }+ W, `/ T8 `
  64.         EX1 = 1;
    " ~2 _0 S. F+ F: `; z% H+ \4 m
  65.         // 允许定时器0中断
    2 E( M4 I* [9 r+ c3 h) z# o) ?# B
  66.         ET0 = 1;
    ) k# Z, E) F5 I& Q: d  ?' w
  67.         // 允许全局中断: K* Q5 q- @3 U- q
  68.         EA = 1;: c- q( ]3 }6 R
  69. }
    3 |7 ~/ l* \" T2 M. \2 C

  70. , K* X* j. d9 V2 M( D4 x
  71. static void INT0_Isr() interrupt 0{
    . ^) s7 e4 p- H& E
  72.         // 矩形波次数累计归零
    7 c$ Y8 m0 ^' _5 D
  73.         count = 0;$ h/ c) ~6 U, n8 G: q+ @5 ]
  74.         // 重开定时器0中断# z/ z( H5 C8 k6 w
  75.         ET0 = 1;
    7 @! ?2 I6 [& E
  76. }' B0 d7 s1 s, e$ {# a+ @7 d( ~4 ~
  77. * j4 y+ p, b: [) ~8 ^* I9 Y
  78. static void Timer0_Isr() interrupt 1{8 T2 B: z+ m) E4 \
  79.         // 输出矩形波
    $ w- l% y: [3 j6 |6 s  H
  80.         OUT = ~OUT;" U; T% V' C/ L& b3 {8 A
  81.         // 累计矩形波次数
    . j2 B5 O5 e0 U
  82.         count++;
    ! G7 V  ?1 {- U# {+ X3 T5 @/ G# R
  83.         // 超过250个矩形波,准备停机
    - J+ `* p7 o4 i
  84.         if(count > 250){
    ' d4 |( E7 N8 e
  85.                 count = 0;, v6 V: [+ A4 A' ]8 w/ \) J1 A
  86.                 isReadyToHalt = 1;
      k9 ?3 j8 K" b* O2 U; \7 r
  87.         }1 L0 x3 J4 g, t
  88. }5 p' j4 {" [. G8 ~' Y

  89. & X, }: ?6 _' @6 Q$ a' _6 j) i/ G; X; M0 P
  90. static void INT1_Isr() interrupt 2{
    # Q- R, ~' _* t: [5 T3 a
  91.         // 矩形波次数累计归零
    / L* F) Z) y# O9 f" M1 B2 e
  92.         count = 0;! d+ D/ U$ ]9 t+ {! [
  93.         // 重开定时器0中断
    & [+ {2 Y4 m: O, E
  94.         ET0 = 1;0 q& w" }6 R3 n3 ?, x
  95. }. a9 r" T% q$ e5 S$ r; J5 _. X
  96. ; }5 |" D# m# r1 M* M
  97. 7 h* G! F9 \: t5 w4 U% \0 x
  98. void main(){, ?8 O4 b' j$ Q+ [& m
  99.         // 初始化P3和P5口. x1 f' e# Z1 t3 Z
  100.         GPIO_Init();
    , R8 l6 I# J& z. o2 f" ^% V- A5 F  ^
  101.         // 初始化定时器0  [5 H9 q/ h# \9 _0 g2 e+ p% K
  102.         Timer0_Init();) v7 ^1 B* U" \- s+ @
  103.         // 初始化中断$ \3 l! m! r) R9 i9 n  y  I( N$ z
  104.         Interrupt_Init();5 S" t9 T8 M( O
  105.        
    / C3 P" [% R) \2 g! j6 s
  106.         while(1){
    1 M: ?9 Z8 l" D  x
  107.                 // 检测电量
      F9 y! J  Y: C! ]( U; r$ b' i! A
  108.                 if(PCON & (1 << 5)){
    ' I" {$ w% Y0 n+ A
  109.                         // 如果电量低,低压指示灯亮
    * M7 k) q, i) I5 F! ]5 x3 D! h
  110.                         LED = 0;3 R; m. n7 s9 H( @+ l$ b
  111.                         // 清电量检测硬件标志位
    $ c9 f- d, `! S* P0 b1 b
  112.                         PCON &= ~(1 << 5);1 }8 `# f4 b  Z  R
  113.                 }else{1 x' {: E0 d. {* o+ ?. d7 s
  114.                         // 电量正常,低压指示灯灭
    + Z2 d! [& m3 J. |1 h2 A( W5 ]
  115.                         LED = 1;* k& ?$ V1 l% V" x
  116.                 }$ v' ~8 N9 f5 ?+ S
  117. 1 _1 V" z: c: S% t* h( ?
  118.                 // 检测到停机标志
    % F6 o& M- V: ]  f: @, I
  119.                 if(isReadyToHalt == 1){: ?9 J# Y& M5 [
  120.                         // 暂时关闭定时器0中断
    2 m  O/ h8 h: k2 @; s* {: ^
  121.                         ET0 = 0;$ ~4 @2 R$ u) l: I/ p, [
  122.                         // 停机之前先把矩形波输出脚置低电平,以方便INT0和INT1唤醒CPU% k# d; R8 O, ^" `+ k/ o( s
  123.                         OUT = 0;- i# K! O- w, K# [) `5 E
  124.                         // 停机之前先把低压指示灯灭掉,以省电0 F  A+ E# r+ [0 n# N7 ~, Q, m
  125.                         LED = 1;
    * J( v" x3 m' _) c. g! c
  126.                         // 进入停机模式
    ( L  ]6 q+ g& q& ]: _" E+ ^2 K
  127.                         PCON |= 0x02;
    8 g8 e. C0 [) A3 i& z# }& b
  128.                         _nop_();
    : W5 |3 G: V5 `0 X) _, V
  129.                         _nop_();% o1 L+ {) `1 D) \
  130.                         _nop_();
    7 C; t' Q! I& p% z$ P$ Z/ ]" t( d
  131.                         _nop_();) ?+ [3 J4 s8 K; _
  132.                         // 唤醒,清标志位
    1 p% C; w3 t. \8 \$ F7 @, H. z, F
  133.                         isReadyToHalt = 0;
    : o/ C( n. t+ A$ R2 H9 |* R. ?
  134.                         // 重开定时器0中断
    $ [& e; y. L' @3 B8 }
  135.                         ET0 = 1;
    1 z* n- P4 R+ E- k
  136.                 }# U3 A% l, F9 M) f$ b7 U/ M% S
  137.         }+ V# b( I, h, H7 [
  138. }
    + [. Y8 W. R. p/ Z
复制代码

# c2 r" ?. p2 v$ c) o6 @硬件参数配置:
3 G* S& E8 ?7 I
* Y7 v" j7 I0 _$ K7 n' p$ [2 t& F
接收端:/ S! Z' w4 g6 k: K# |! L
  1. #include <INTRINS.H>
    9 w3 e( ~* y7 w
  2. #include "STC15W.h"& C1 W7 W' Z3 t2 j, H. _, J7 `% V

  3. + b* P$ }$ i) ]1 m2 u; l

  4. ! d. u+ D8 k5 H' R0 A
  5. /*
    " M5 n& K! f! |! @

  6. 2 @$ K! c( O3 n* ?$ @* N
  7. *---------------------------*
    2 N# @% q0 r: S% Z
  8. |1 (GPIO2)         \__/  (GPIO1)16|
    , f" W# O4 A! H) I. n3 E0 H( `
  9. |                                                        |, X# }+ k% k+ n8 _- B! m
  10. |2 (GPIO3)                   (GPIO0)15|
    % l- e: c5 B5 Z) }4 T
  11. |                                                        |
    " V8 E0 C: b  I4 X( k
  12. |3 (GPIO4)                                  14|
      r" E9 A& p3 J% m8 N, C
  13. |                                                        |
    6 t  ]* Y9 a/ ~# ]9 k' o* i
  14. |4 (GPIO5)                        (DATA)13|7 H: q7 R: H8 t, e
  15. |                  STC15W204S                |
    $ e& {# G9 v6 U2 G' d4 K+ @
  16. |5 (GPIO6)                   (LATCH)12|3 s7 ?. x& {( F3 J! C
  17. |                                                        |
    7 [; ]3 G" N7 _! s. _; R
  18. |6 (VCC)                         (CLK)11|
    ' Y6 t6 a. Y* r, x; c; G
  19. |                                                          |
    * X, ~1 m% h+ h5 J# v
  20. |7 (GPIO7)                         (TXD)10|, N7 g2 `' m  c0 T. N
  21. |                                                        |
    % |: B) \& c8 _+ E- o
  22. |8 (GND)                         (RXD) 9|- q& ?7 X  u# V4 o
  23. *---------------------------*- @( K3 @* U* i: R
  24. Fosc = 12MHz- x: }& ]1 [7 ]; Y& ]3 r$ _
  25. 9 P5 t1 R- M" T8 |, F
  26. P1.0 -> 上
    0 z' C9 N- m1 Z3 n; _
  27. P1.1 -> 左
    6 ~' i/ L* a9 R4 v  e1 ~; p2 v" r+ K
  28. P1.2 -> 下
    - ?6 S7 H0 d0 L: f, S* d
  29. P1.3 -> 右
    : Q0 v" d% R  J  R4 q/ P# R6 I
  30. P1.4 -> SEL. b/ f% H0 t3 @( p! c
  31. P1.5 -> STA1 G8 o& j+ }5 Y8 x
  32. P5.4 -> B
    / E$ ^3 \& Q5 S
  33. P5.5 -> A1 l9 e# S8 [7 w7 O. ?) ^
  34. * q6 q# x& v  O: O: g& `7 n' Q
  35. */# m& r) i' ^- E) l
  36. % e4 @( p% |3 V4 w% i. m9 v( o

  37. 7 D9 H2 M% J! K& D! w- i( p
  38. sbit CLK        = P3^2;3 Q% T- c+ o" Q  M+ H1 |
  39. sbit LATCH        = P3^3;
    - \2 P* R6 I# P- p( _) [
  40. sbit DATA        = P3^6;
    - L3 B) M/ y: ]* @

  41. 0 G4 }" v' H9 Y, ^2 W
  42. bit isReady = 0;0 a3 w! j7 n) f* i( @+ Z
  43. static unsigned char key = 0;
    8 w  b% X4 }6 |* q( U" v/ s
  44. static unsigned char buf = 0;        // 双缓冲。这个缓冲区保存从P1和P5组合而来的键值
    9 Z% B8 o6 q3 D
  45. static unsigned char bufReady = 0;        // 双缓冲。这个缓冲区保存上面那个缓冲区的备份# ?* P8 f8 T% J4 f
  46. static const unsigned char data mask[] = {0x80, 0x40, 0x10, 0x20, 0x01, 0x04, 0x02, 0x08};        // A B SELECT START UP DOWN LEFT RIGHT。为提升速度,这个表放到RAM中- t: F% f- s$ F8 v& }# G6 r  M
  47. static unsigned char idx = 0;
    3 z* I3 N; l$ s3 c
  48. $ x3 N, B* T8 d3 @( T* \. Y5 G3 Y

  49. 2 I$ Q6 j$ W' y  p  _; A+ q& O" T# A
  50. static void GPIO_Init(){
    7 q9 I+ u! p# t2 ^+ p
  51.         // P1口和P5口用于接收并行信号,全部初始化为准双向,依靠内部弱上拉输出高电平
    ' _& |3 p  S& x) B8 g( ~0 n
  52.         P1M0 = 0;
    4 ^* a5 m, T1 w; r- s- a
  53.         P1M1 = 0;6 P) M2 Z" ^; P  N8 @& N
  54.         P1= 0xFF;
    0 Q3 u- m2 J5 Z. N$ B$ w' F! \7 u
  55.         P5M0 = 0;/ r6 O9 S; R4 m8 Z4 X9 }$ \% N
  56.         P5M1 = 0;
    # o7 \4 G$ J/ T* Y" F  `
  57.         P5= 0xFF;3 n% x3 r' G* L! m& J, N
  58.         // P3口初始化为准双向) t2 B8 {: x+ r" T) Z
  59.         P3M0 = 0;% R7 b) J, k$ z: H
  60.         P3M1 = 0;1 |' T9 \% I! p! W0 M
  61.         P3 = 0xFF;
    - Y% t. K; o8 M) q8 F( C! S
  62. }# `/ }5 S! u4 ^+ `& z: f3 P: b

  63. $ V9 R4 U5 k+ d4 ^' J+ s
  64. static void Interrupt_Init(){/ y4 P. d1 b- X. X" k% R
  65.         // INT0中断(CLK)触发类型为上升沿+下降沿3 Y0 L6 q1 K9 C! n
  66.         IT0 = 0;
    7 i2 `/ T' |# ~7 m
  67.         // 允许INT0中断
    $ b7 E  X. O! }* o5 H9 z6 n9 r
  68.         EX0 = 1;& S  a3 m, l& h2 r% h% X2 r' O
  69.         // INT1中断(LATCH)触发类型为上升沿+下降沿" |) V) H; R) d! X$ O- H
  70.         IT1 = 0;7 c) {- F, P- G4 [1 v/ m4 e( ?$ E5 s
  71.         // 允许INT1中断
    ' `% a5 n+ a  e6 t5 w, u
  72.         EX1 = 1;
    5 c1 F9 F4 H+ R6 ]8 |
  73.         // 开启全局中断
    4 y& d- U1 l5 X# a0 D0 T0 [2 v
  74.         EA = 1;" F0 \9 u: l* k5 h. Y  v4 }
  75. }# d) ~: I; _% n/ p2 X8 ?. F

  76. - I: Q5 d9 q0 I; w* V5 [1 P  ]. Y5 b
  77. static void INT0_Isr() interrupt 0{
    - A+ E" s$ s8 ^8 [, Z/ S' W
  78.         // 只有已经成功锁存才允许CLK移位
    & X) y1 \+ J' ?* A) i
  79.         if(isReady == 0)
    $ K$ t6 s; u1 Z; g: u
  80.                 return;
    8 D/ {4 T" ~3 [% Q! X
  81.         // 读当前引脚电平,如果是低电平则说明是下降沿,此时直接忽略该中断" w1 Z- ?. S8 J3 l- }8 N* k, U
  82.         if(CLK == 0)/ _+ o; k. H6 q) V. Q
  83.                 return;
    : T! @% a9 o# l- F/ ]6 v. d% }; X
  84.         // CLK上升沿到来的时候,取锁存值的下一位输出
    4 _) j$ P8 e  t3 |
  85.         idx++;
    9 b& [' G3 X; A" C6 y/ V* u9 v
  86.         DATA = key & mask[idx];
    4 j; l6 R- o$ w* |
  87.         // 如果已经完成7次移位,则一轮读取完成
    1 B( c3 i1 m. V
  88.         if(idx >= 7), ?7 c8 e: w# c: ^
  89.                 isReady = 0;
    # x- C/ t+ ~' b5 B) G  K6 l% C
  90. }; @  c) J( g# Z+ k

  91. 1 I6 [3 n. E, z: g* s
  92. static void INT1_Isr() interrupt 2{' O% S. r3 V" @- Z# S
  93.         // 读当前引脚电平,如果是低电平则说明是下降沿,此时直接忽略该中断
    ! C1 q0 @5 ]1 e7 F9 T  |2 u
  94.         if(LATCH == 0)
    * a' Y/ d* x6 g( q+ x
  95.                 return;5 F4 ]- m$ S* ]  [; D4 t
  96.         // 当LATCH上升沿到来的时候,锁存所有按键状态,同时把键值A输出到DATA
    , f! v+ D# w0 ~4 _; J% O' b
  97.         key = bufReady;
    ( A. h4 z3 F: ?
  98.         DATA = key & 0x80;//mask[0];        // 为了加速运算,直接取表中的值而不是读表
    ! m0 m/ U% c6 o8 p  I9 F
  99.         idx = 0;
    7 V4 E5 m- g1 y& O
  100.         // 允许CLK进行移位; P8 U* F6 E; J7 P+ l  E
  101.         isReady = 1;
    ; M/ t; l* `; I' E
  102. }5 M$ r! K- g3 k$ j* O
  103. 0 Z* o3 a- r/ S3 y4 s
  104. void main(){
    2 b2 R, B# y0 U' y; E5 L6 |
  105.         GPIO_Init();
    ' Z! F# R" }  ]2 Y/ j
  106.         Interrupt_Init();+ m: V& X8 O0 @, Y
  107.         + }# w7 j6 Z4 B) I. D/ `8 Z
  108.         while(1){
    , L1 q" y1 I2 n, v0 s
  109.                 //PCON |= 0x01;        // 进入省电模式' m/ A- R# F1 q" X, I! X, P
  110.                 //_nop_();) Y1 u7 F* ^* W3 o7 O
  111.                 //_nop_();
    # O0 j7 W) t5 H$ A) v5 r3 \
  112.                 //_nop_();5 n! j  {0 O( g; A2 B$ Z% \6 m
  113.                 //_nop_();( o! q' U$ x; n4 Z' X8 h% }- s
  114.                 buf = ~((P1 & 0x3F) | ((P5 << 2) & 0xC0));
    + t  y; d4 d4 o
  115.                 bufReady = buf;, _2 Z, R4 ~2 r$ k: T8 ~% J
  116.         }2 r! Y+ H/ L9 z5 m5 h, w2 T
  117. }
    # g. r# U' p' p, T
复制代码
) r2 V. q& Z. f: H. v9 T. R' c' u7 X% a
硬件参数配置无特殊要求,晶振频率选择12M即可。- c. r1 C# J) K7 C
# g7 f( O! ^: @; p; [* O# a
这是编译好的固件。

本帖子中包含更多资源

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

×

评分

参与人数 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
  H* e  l% Z3 g# w/ C不错的设计,想问一下楼主,FC的15针公头怎么解决?普通的公头太短了,插不进去FC的扩展接口。 ...

4 s, F3 m2 o5 Z坛友的改造方案
回复

使用道具 举报

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

使用道具 举报

发表于 2019-5-25 12:07:18 | 显示全部楼层
精彩,楼主动手强,也写得很详细。
2 h1 @, `! J& B5 \6 @6 F5 a2.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
% l$ ?5 v- G" r7 B# \6 T; S3 v- ?/ Y精彩,楼主动手强,也写得很详细。
3 w4 y+ r2 m, W, S& _! |2.4G方案是目前无线的最低延迟吗?
- ^# x$ e3 @2 e
我没用过其他无线手柄,所以实在不知道我自己做的这个手柄到底是不是最低延迟。+ T2 J7 i, C* b5 I3 e
不过根据网上的说法,延迟高低主要是由通信协议的复杂程度,以及数据传输速率决定的。这个模块虽然是2.4G无线模块,但由于协议很简单,所以延迟比较低。. o0 Y- C8 `1 a5 ?! K  u
我用这个手柄玩一些ACT游戏,比如超级马里奥、忍者龙剑传、热血系列,完全感觉不到延迟,和游戏机自带的手柄没有任何区别。唯一的区别就是这个手柄是用火花山寨手柄改造的,外壳是垃圾回收塑料,粗糙+脆弱,导电橡胶弹性不佳,手感不是一般的差。2 F( [* e/ `* B, R# C  A
我手里还有十几张板子,等我有空了我再做一套,到时候买一个好一点的手柄改造。
回复

使用道具 举报

 楼主| 发表于 2019-5-29 16:56:14 | 显示全部楼层
ppad 发表于 2019-5-28 17:27
1 k( @, R) u* m3 E. Q* h给技术帝赞一个,有半成品发布吗,自己焊接改造就可以,编程实在不会啊 ...

- L" R% q% S  j% j6 q7 `, V- ^很可惜,我手里没有多余的单片机了,LDO也找不到了,锂电池以及充电模块更是没有了。反正就是该用到的元件基本都没了,所以没法发布半成品。' M' Z" Y, X6 Q
两个板子倒是有十几张剩余。
+ E& N9 A6 ]# `5 \5 n. P+ f你要是有USB转TTL串口板,完全可以自己买这两种单片机,然后我给你编译好的固件,你自己用串口板下载到单片机里面就行了。两个2.4G无线模块也得通过串口板用AT命令设置参数,不过好在我在设计电路的时候就已经预留好了串口,可以直接在线下载和在线设置参数。总的来说并不麻烦。
回复

使用道具 举报

 楼主| 发表于 2019-5-29 17:00:34 | 显示全部楼层
孙大师 发表于 2019-5-28 18:55
0 B, o+ L$ b. I- B非常好,楼主是技术帝,到目前我都还没开发fc的无线套件,等空了,开发一套套件,等玩家自己组装。 ...
0 S  G% K% K4 k, T  E3 o! q7 |
能得到孙大师的赞誉,不胜荣幸!3 [$ U  f% Q3 {( P
不如开发一个多功能手柄,比如用SFC手柄改造,L/R键配合其他组合键可以用来切换2P~4P、调节连发速度、软重启等各种功能。接收端插到15PIN扩展口。
回复

使用道具 举报

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

本版积分规则

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

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

Powered by Discuz! X3.5

© 2001-2025 Discuz! Team.

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