找回密码
 注册

QQ登录

只需一步,快速开始

查看: 25934|回复: 32

自制FC无线手柄

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

& \: B/ ~/ _8 v0 x- u& j$ n& e0 {! {. ^3 ]. v# M
最后把按键、导电橡胶和电路板装上去。( }6 @1 F. H% O3 e, Q9 Z' N& A% o
精心裁剪了电路板,正好扣上,不会阻碍其他元件,也不会影响后盖和拧螺丝。
1 `) Z) ^) k" P6 G9 c8 n& w/ _2 |+ [0 j, ?( g5 n  \

4 m: M2 t- o4 v( c完工!
+ H4 W# R; T0 j6 `* l2 O$ _! ]5 \8 P* J4 X" @: D& p' C3 q8 G' X
7 g" `* `2 U0 Q0 d  n
这是充电的MicroUSB插座。旁边的小孔用于透出低压报警LED的光线。* d, b# E2 R. F0 y
  G* |4 ]# i' A

0 z& S* f3 L8 s: i$ Q接收端用一片DIP16封装的STC单片机模拟CD4021。为啥要用单片机模拟而不是直接用CD4021?因为jdy-40模块接收端在有按键按下的时候输出高电平,无按键按下输出低电平,和普通手柄正好相反。当然我也可以用两片74HC00或者74HC04之类的逻辑门进行反相,但那就增加了芯片的数量。对于FC手柄这种工作频率并不高的设备来说,STC单片机完全可以胜任模拟工作。
! Q+ d) _- ?2 |" i- f$ _' U! R* q2 i, i: K
* E  t, b( t& t% K7 \5 r: h5 ]
/ K) ^* |. ]& }: o! [: c; ?6 v
电路设计有点小小的错误,所以有几根飞线。原本设计使用低压差LDO是XC6206,结果在做这个接收模块的时候,买的LDO居然找不到了!无奈只好用了AMS1117。幸好对于接收模块来说是5V降到3.3V,1117可以胜任。要是发射端手柄的话,3.7V降到3.3V,那就非得用6206不可了。. |9 I1 g( q  u2 U" L3 P4 R
5 c7 f7 q, ?/ K, X% a" Z
实测十分灵敏,延迟极小几乎感觉不出来。可惜这山寨手柄的手感并不佳,尤其是方向键,软塌塌的。看来我得买个剪线手柄改装。# X. }0 t! c  c9 D+ x- Z

0 n& L- ]6 l+ f* j* T( S这是电路图,有兴趣的朋友可以参考。8 M2 Y9 B" L( l4 N& C

0 q: {5 i% r2 f; f
; ^& E/ L: x+ [3 c我信奉开源主义,十分痛恨把技术藏着掖着。好东西大家分享嘛!所以两个单片机的源代码大公开!, P& L$ S, S- v
编译器:Keil 51。( m9 E# I) i! I& S  @
5 V4 K6 Y$ v  F8 ]% f
发射端:
  _7 T5 f' A1 J* M+ N& {& [; j
  1. #include <INTRINS.H>5 Q' j7 [% ?' m# S/ T
  2. #include "STC15W.h"' @7 v5 R9 o+ S6 B( Z

  3. - e( ?) A# E( t- E8 d+ P4 E% M
  4. . C+ M: L* C& M' f# S
  5. /*
    # |$ X( ?3 w- s6 r) J7 w: [
  6. --------------------------$ p) q* [% }2 {& ?6 K$ v
  7. |1 (OUT)        \__/   (INT1) 8|
    0 k. v2 W. A4 a1 L/ y0 u7 r( A0 W) d
  8. |                                                   |
    + e; ?/ Z) w" l9 O0 B
  9. |2 (VCC)                   (INT0) 7|0 `# q+ Y& P$ C
  10. |                 STC15W204S                   |
    ! E8 Q( x# m( {9 \8 M
  11. |3 (LED)                         (TXD) 6|
    5 m: F! {6 D4 C
  12. |                                                   |
    2 [  j  W1 z8 e+ [" d; z. W4 s
  13. |4 (GND)                         (RXD) 5|2 s$ e6 x/ V/ g0 E
  14. --------------------------8 I# _8 G' e( Q; e
  15. ) @# r  h8 K; s7 q8 Y
  16. LED ---|<|---[===]--- VCC6 U, h# C: B2 e- c4 V8 J" C
  17.            Red          330% W4 L$ y3 R% R( P- k

  18. 6 L! Y4 Q9 D& h* \" r
  19. Fosc = 6MHz2 B9 b, r1 K0 }
  20. */
    3 g) Z- ^& F- @! `+ V

  21. ( Q" Q$ _0 C- q
  22. ) `* T$ A' P# |5 U* y. I
  23. // 矩形波输出脚9 R6 f( [& s. p. W1 c
  24. sbit OUT = P5^4;3 R2 A' \5 t1 T" X9 B; H
  25. // 低压指示灯引脚
    3 V, a. [& z9 S" z" u
  26. sbit LED = P5^5;1 ]6 t1 x! m* Q7 _. C3 @; D8 l

  27. # R8 X: G3 b5 F
  28. // 停机标志位
    ; F" `5 k0 q7 {% n
  29. bit isReadyToHalt = 0;' \, }2 V6 P- V2 a! ]% J% n

  30. , W% k0 h( q, n/ o) i2 y
  31. // 矩形波次数累计9 n9 N- g; }  u0 ]9 z4 V3 g
  32. static volatile unsigned char count = 0;# c4 v: z3 ]2 `4 A/ Y- M
  33. 0 y% k: m5 w) j/ E+ [  `/ l

  34. 1 D" x) D! k/ d  g
  35. static void GPIO_Init(){
    8 K2 {* |% ?6 Y, X* l" L6 H+ f
  36.         // P3口设置为准双向,默认靠内部弱上拉输出高电平
    2 p; a6 j; F7 x! h& L* {
  37.         P3M0 = 0;
    2 q9 G; [( F8 f: U0 n4 ?
  38.         P3M1 = 0;
    8 u9 ~; _2 o4 l  _4 O
  39.         P3 = 0xFF;" j6 _+ G8 U8 G$ @
  40.         // P5口设置为准双向,默认靠内部弱上拉输出高电平
    ' o2 E- n  Q4 g/ X
  41.         P5M0 = 0;
    6 v0 x; M% ~7 G8 ]
  42.         P5M1 = 0;% O2 T7 S7 @/ m8 E7 ^- s  Q- l
  43.         P5 = 0xFF;
    " o* o7 V% g- Q' p0 t1 h
  44. }- t0 b  t* j) g! w/ ?) J
  45. / [, w! S! S6 }; ~: I1 A  `
  46. static void Timer0_Init(){7 I" Q2 U" d" F) [# U: D
  47.         // 16毫秒@6.000MHz
    ( ^% [% ~( O: f) V6 U
  48.         AUXR &= 0x7F;        // 定时器时钟12T模式1 I5 d' S+ i$ _6 m9 z
  49.         TMOD &= 0xF0;        // 设置定时器模式
    ' T4 ]9 l! F- u" \
  50.         TL0 = 0xC0;                // 设置定时初值" B2 Q9 D8 d9 d# Z8 b
  51.         TH0 = 0xE0;                // 设置定时初值
    5 f4 G, C8 f4 o. I+ y( U8 M
  52.         TF0 = 0;                // 清除TF0标志" V2 p( {" `7 q* P
  53.         TR0 = 1;                // 定时器0开始计时. F1 E6 B7 z9 ]; ]! u
  54. }3 o. w7 ~- l, q3 S$ L& e* O

  55.   I6 ^4 V0 L8 }: Q) _
  56. static void Interrupt_Init(){
    1 [1 c4 J! ]8 ^5 a, [
  57.         // INT0中断触发类型为下降沿触发/ G' S: x9 ]2 w. q; _
  58.         IT0 = 1;
    / n+ P  B: O  J# }& J4 n
  59.         // 允许INT0中断
    6 m, [- r0 R! M8 \# Z
  60.         EX0 = 1;
    0 M8 ]6 Z: C! c2 x: g
  61.         // INT1中断触发类型为下降沿触发
    ! g6 a0 Z2 Z; X+ G5 {. v5 `
  62.         IT1 = 1;6 ?" `) o' U5 Q' e
  63.         // 允许INT1中断( i5 ~  D! V4 D* V, j
  64.         EX1 = 1;
    , z/ B9 q, h2 Z4 {0 J# ]
  65.         // 允许定时器0中断
    + W1 `: {' f9 @+ L" s5 f3 c! B
  66.         ET0 = 1;
    ) U+ m/ u7 |3 E
  67.         // 允许全局中断) r' g. c$ c2 Q$ F
  68.         EA = 1;2 ?9 B, K+ z5 M" h% R+ m; ?
  69. }* S& [5 h' h, k3 F+ z

  70. ! W' o% o- U/ F8 P0 `' w
  71. static void INT0_Isr() interrupt 0{
    , Q( \( O3 O) @& T0 I+ p0 d
  72.         // 矩形波次数累计归零( G1 a( P7 Z* M+ A9 t1 n9 s2 m
  73.         count = 0;% ]& d% U0 H+ `$ ]$ q* J- R: I* Z
  74.         // 重开定时器0中断2 u+ j& o$ q4 u* b
  75.         ET0 = 1;+ R; p  K8 j6 C
  76. }
    4 P/ @" e5 f- \; f2 ?( |) T7 h
  77. ) A4 E- _( O9 c+ f
  78. static void Timer0_Isr() interrupt 1{
    7 u. ~) x7 q$ g5 d+ x4 J/ W6 n$ Z3 i
  79.         // 输出矩形波
    2 R$ Q7 B- t: S4 |& a
  80.         OUT = ~OUT;* O9 X( i0 M1 p) g
  81.         // 累计矩形波次数6 N& _# Y5 k! @+ b7 E
  82.         count++;
    6 j: d/ i0 l8 z' L8 J# |1 |: T. F( k
  83.         // 超过250个矩形波,准备停机
    ( b2 h: S. X+ v, ~% }# I/ y/ I
  84.         if(count > 250){  j/ R7 [5 K% B, d
  85.                 count = 0;
    3 g+ t% l9 j% ~  x5 M
  86.                 isReadyToHalt = 1;
    0 L3 k9 |8 D; `6 k/ V( D
  87.         }
    7 O4 n; G6 _! @  R
  88. }* W, T8 m' [$ G- e6 Y/ M& `
  89. ' I0 s5 |( [5 K# r4 G& X: }& m' E
  90. static void INT1_Isr() interrupt 2{1 X5 ]# f2 g7 w
  91.         // 矩形波次数累计归零, C: Q& C; _: [0 L
  92.         count = 0;
    3 i# G! @' [9 c  H
  93.         // 重开定时器0中断) V; Z: p, k5 v3 l! F2 s  H4 h
  94.         ET0 = 1;& c: p% l5 ?: C0 d& w
  95. }; f( q+ h& K6 |# p7 H$ `

  96.   X' d( H+ h* l; Q/ P* z$ E

  97. $ L% e) V2 r2 m# |  Y
  98. void main(){% a8 l* s6 |- q+ x
  99.         // 初始化P3和P5口& ^: x  h& l$ `6 A/ u6 {/ J0 p1 D9 ~
  100.         GPIO_Init();
    0 q) M7 Y( u, z. A6 B, Z9 F
  101.         // 初始化定时器04 @3 x! K# d4 g  R' t1 i: O
  102.         Timer0_Init();
    9 J4 b4 F% p0 K% M% s# E1 n
  103.         // 初始化中断
    ! [( J/ }4 d6 z0 x+ d
  104.         Interrupt_Init();/ S: x+ R8 O# t# N  h
  105.         ' e0 M9 Y7 }8 N: @
  106.         while(1){3 I8 S( H% G* @+ E0 t
  107.                 // 检测电量
    % i' N% ?; Z7 C1 {  A
  108.                 if(PCON & (1 << 5)){
    9 q" g, M/ w+ @: U' X9 U7 o
  109.                         // 如果电量低,低压指示灯亮# z3 N1 d7 j$ F
  110.                         LED = 0;2 d& a: W7 m: l- E  A
  111.                         // 清电量检测硬件标志位. m+ R3 G' ~! L# m
  112.                         PCON &= ~(1 << 5);( y9 x6 Z4 ]# s/ h; i; `, d0 x# f  u, @9 ?
  113.                 }else{/ l* i/ ?- X# m8 W  b
  114.                         // 电量正常,低压指示灯灭% Q+ o* A7 E* i% }7 a+ D/ B& i& @) ]
  115.                         LED = 1;
      P8 n7 m- @8 L
  116.                 }7 D3 V) O/ h0 g* W
  117. ; P0 v" H0 }- |* S
  118.                 // 检测到停机标志$ i* l; \/ Z. n
  119.                 if(isReadyToHalt == 1){' ^# H: i" K; _
  120.                         // 暂时关闭定时器0中断' ]9 E# M0 U8 F9 k' n0 g# p
  121.                         ET0 = 0;
    2 k6 ]/ X" \) V& r/ ^# {
  122.                         // 停机之前先把矩形波输出脚置低电平,以方便INT0和INT1唤醒CPU+ v" F6 q  E2 ]7 q
  123.                         OUT = 0;0 q* K" P1 A5 k
  124.                         // 停机之前先把低压指示灯灭掉,以省电4 Q* o) I$ U- l1 b  `: D# D8 M
  125.                         LED = 1;
    2 a& I6 F; S+ u* u/ {; m( m. b
  126.                         // 进入停机模式
    4 U9 `3 S# g& H
  127.                         PCON |= 0x02;
    0 E( [* `, g% u2 `/ @
  128.                         _nop_();
    0 W, n  b' Z, D0 k1 D+ O; @
  129.                         _nop_();% K5 ~1 q3 e/ S2 a4 y8 |, P# e
  130.                         _nop_();& ~# ~( L2 ~6 S. `
  131.                         _nop_();4 t0 R) F6 \, N2 W1 A; T8 k1 p+ Q
  132.                         // 唤醒,清标志位$ O% d( c9 r5 f: Y( y9 G$ E
  133.                         isReadyToHalt = 0;
    5 i" R" o% J! w7 |
  134.                         // 重开定时器0中断
      l2 O* k0 J' }& |* T
  135.                         ET0 = 1;1 |, a+ P8 @/ d$ F% K" s
  136.                 }
    3 g! Z' G8 F. g
  137.         }
    # B* R& z9 ]% Q# Y, [3 [' p6 ]* m
  138. }
    1 y) |4 }4 |( k1 \7 y; u! }
复制代码

8 z1 N3 ]; Z1 E4 G硬件参数配置:
# n7 _0 c+ P) E* c) `2 |. A/ D& v1 Y9 c6 P, f1 i
# S) G3 d2 Z2 Q+ l9 U
接收端:8 q' p/ P6 S  Z, B
  1. #include <INTRINS.H>
    - f/ Q7 a$ ^* Y0 r4 w
  2. #include "STC15W.h"+ l, K( _$ K) y% [+ O
  3. 1 k" I: c% Q! X/ S

  4. 8 j/ ^. p& L1 ^6 L3 D6 q
  5. /*
    $ Z; y( W( {- w7 |6 o! ^

  6. 6 ^' i* M  I* L% [; \
  7. *---------------------------*% a3 w) T7 u& _% w/ {
  8. |1 (GPIO2)         \__/  (GPIO1)16|, f8 t; W4 S9 C/ _! W
  9. |                                                        |
      E( h7 D& [" [1 o, K. K4 s% U) j
  10. |2 (GPIO3)                   (GPIO0)15|
    ; p: a2 u# y" }7 y& @
  11. |                                                        |/ n# `5 }( f: g- d# q/ J
  12. |3 (GPIO4)                                  14|$ T1 m% g! V2 b; |
  13. |                                                        |7 p8 ~* Q1 X9 Y5 l/ F' o
  14. |4 (GPIO5)                        (DATA)13|3 r8 B( z, l) y: Y0 ^: G7 i
  15. |                  STC15W204S                |
    1 P/ J$ ]: `" j) L- o. _# \
  16. |5 (GPIO6)                   (LATCH)12|3 f' o+ b* I, o) M& F* g9 H8 e
  17. |                                                        |
    ' b% @& h3 x. {5 w. b9 J
  18. |6 (VCC)                         (CLK)11|3 z! G7 T8 I5 w& B
  19. |                                                          |/ b3 P  Y! A6 e4 E7 R
  20. |7 (GPIO7)                         (TXD)10|
      b& S% v, n# Z, i/ T# A
  21. |                                                        |+ ]' @' F3 [8 G7 r( v& U1 C" f- t; x
  22. |8 (GND)                         (RXD) 9|; ^  ]. y, n2 I$ o
  23. *---------------------------*
    ' @" q4 ^+ w4 U5 E8 b- ^% Z6 o
  24. Fosc = 12MHz
    : {- G. X& W9 w5 f

  25. : I, |) ~% g. F3 O) v+ o( a# w
  26. P1.0 -> 上
    , c' V/ y, [8 c& e; |# s& I
  27. P1.1 -> 左
    7 f3 Z) |. c! a4 l, x9 _
  28. P1.2 -> 下1 k8 @2 G4 p' p8 T' Q5 h# f+ T2 O% _+ E
  29. P1.3 -> 右
    ; g8 \! ^2 m6 i+ h& T
  30. P1.4 -> SEL
    # n" q7 w5 n8 I, z- t" G& `9 U
  31. P1.5 -> STA4 {. i2 T# B% s+ l
  32. P5.4 -> B4 m6 q% ^. e% F% F8 ~
  33. P5.5 -> A; c6 Y4 t* T" E& N
  34. ( t6 |; u7 s1 D* g' v
  35. */2 b6 g4 n) C2 A! ]: B
  36. , a& ^! z# A7 R' F( `2 z. I% B
  37. * }& c) _/ I# F: @8 i! {
  38. sbit CLK        = P3^2;
    2 ~  }/ X. t2 e7 i1 p; T
  39. sbit LATCH        = P3^3;
    : f8 F) n$ m2 }% m& _. G
  40. sbit DATA        = P3^6;
    7 f8 [" K5 w! ~) t9 j
  41. + Q& \' b4 M9 i, R
  42. bit isReady = 0;: F2 [4 s7 ^) {9 B9 l. r. [+ W1 I
  43. static unsigned char key = 0;
    # U* e0 _8 x+ o7 g2 }% A4 s
  44. static unsigned char buf = 0;        // 双缓冲。这个缓冲区保存从P1和P5组合而来的键值
    - F6 e8 k- b7 ?0 j8 V' ~3 y" }* w
  45. static unsigned char bufReady = 0;        // 双缓冲。这个缓冲区保存上面那个缓冲区的备份& A5 a# D  v; s6 \/ T4 |7 i7 l3 m" `
  46. static const unsigned char data mask[] = {0x80, 0x40, 0x10, 0x20, 0x01, 0x04, 0x02, 0x08};        // A B SELECT START UP DOWN LEFT RIGHT。为提升速度,这个表放到RAM中, k+ {. j0 h0 S( m( {+ E; F
  47. static unsigned char idx = 0;
    1 x# C- L9 }% \* P# t! `3 ^* G

  48. 2 R+ I1 Z. N+ I; J8 A; |$ E
  49. / C- L2 [* M& ^
  50. static void GPIO_Init(){
    3 |: l$ d1 g4 H& s1 v+ I" H
  51.         // P1口和P5口用于接收并行信号,全部初始化为准双向,依靠内部弱上拉输出高电平
    # Q3 D0 _! l. V; Z, Z# t& o4 n) ^
  52.         P1M0 = 0;
    1 Y$ f( p" F+ @6 p6 M. r
  53.         P1M1 = 0;
    % B1 |; M; [; R6 }& A/ L
  54.         P1= 0xFF;% p& A, z1 I4 @. q
  55.         P5M0 = 0;
    ! _0 N/ v8 D9 }( @" A+ ]5 Z' o$ q
  56.         P5M1 = 0;
    8 }. H4 [' B0 ^& @0 p* H
  57.         P5= 0xFF;4 b" i2 p- _+ ^! F4 B' L. p
  58.         // P3口初始化为准双向
    , y/ p% }  I7 \3 f# A& Z6 x
  59.         P3M0 = 0;$ K' i, [4 @& W: C
  60.         P3M1 = 0;
    * e4 o; @! j9 c9 X5 l
  61.         P3 = 0xFF;
    / V: H, r) R* A5 O8 L% M
  62. }- {' P/ [1 d4 P) D; Z9 u  M, a- l

  63. ! d* K2 L% w  I. ]# G' d
  64. static void Interrupt_Init(){. u4 [% G; |* ^) Y+ \
  65.         // INT0中断(CLK)触发类型为上升沿+下降沿
    , O" b( b) Y  G4 f
  66.         IT0 = 0;8 F8 s) a  g- n
  67.         // 允许INT0中断" q; X  e& Z, G& s+ s
  68.         EX0 = 1;
    $ m; W! W& C' l& P
  69.         // INT1中断(LATCH)触发类型为上升沿+下降沿& h7 K3 ]$ J# v
  70.         IT1 = 0;
    5 X; w# ]) ?2 D# K3 V
  71.         // 允许INT1中断
    6 e5 o( P% l0 J! J
  72.         EX1 = 1;
      H+ q& r- I8 l4 M% C2 s, o3 H4 d
  73.         // 开启全局中断
    1 d7 S+ G8 N0 `% `
  74.         EA = 1;9 q$ f" [! y! Q$ k* x5 |: t
  75. }
    , Z  ^! p2 ~. g0 S2 k2 B

  76. " V; H% [7 S8 M/ Z% D5 \' ]& k
  77. static void INT0_Isr() interrupt 0{6 _- V% e7 u' K! @9 z" T, ^: E+ x! S8 y
  78.         // 只有已经成功锁存才允许CLK移位
    8 I; `% l7 w6 d1 d
  79.         if(isReady == 0)' y+ n. g3 a& a9 m
  80.                 return;/ C0 C2 I/ r5 D. {' |/ ~
  81.         // 读当前引脚电平,如果是低电平则说明是下降沿,此时直接忽略该中断' ]" c  x& }* j8 C/ F/ H$ L/ {
  82.         if(CLK == 0)( r! Z" Z7 e" h6 d! d
  83.                 return;
    & g! ~: c9 R2 b3 m
  84.         // CLK上升沿到来的时候,取锁存值的下一位输出
    - H+ l& o) J! o  V5 |0 `/ G5 u
  85.         idx++;
    " e1 d& j. u: ]* q
  86.         DATA = key & mask[idx];
    9 ]8 N/ Q% X7 t! A& J
  87.         // 如果已经完成7次移位,则一轮读取完成  L/ f5 `/ q1 {4 I4 |. Y
  88.         if(idx >= 7)
    8 d. o* H' ?$ m
  89.                 isReady = 0;
    1 d  u' h8 X3 h3 }4 P0 V, U6 z$ z7 e
  90. }2 i, K4 @( j' h6 S" u0 q. B' _
  91. + X8 X9 x3 p) s  c# b& r; t
  92. static void INT1_Isr() interrupt 2{; e; {  Z! e' r" F1 b
  93.         // 读当前引脚电平,如果是低电平则说明是下降沿,此时直接忽略该中断4 J8 {/ o$ W8 I/ ~/ ?% z
  94.         if(LATCH == 0); j. D7 L0 m) c# I3 y" W* [: i
  95.                 return;
    9 i$ f5 ~, h1 U: d! v) d; m$ @
  96.         // 当LATCH上升沿到来的时候,锁存所有按键状态,同时把键值A输出到DATA
    5 H% N: g- f' W; R" j( B3 O
  97.         key = bufReady;, B& S9 {- @. C% U' o8 f
  98.         DATA = key & 0x80;//mask[0];        // 为了加速运算,直接取表中的值而不是读表/ w# [! a: W. @% `, S) R4 i: [$ c1 H4 e
  99.         idx = 0;9 N: S/ Q- d+ i/ o2 z/ a  g
  100.         // 允许CLK进行移位% `, `0 S. J3 I; r1 S+ S6 ]; \
  101.         isReady = 1;1 f7 n/ }  j, O- Z/ k
  102. }$ a( q- b" x, ~8 k" N

  103. 4 G8 y( o" N* N( N. e
  104. void main(){: T( S" `& E. x' c* e% f/ L
  105.         GPIO_Init();
    . P1 B, S- O9 M$ Y: J( n
  106.         Interrupt_Init();
    + y# J  C9 Q4 O  l% Z. ~
  107.         ' [  g! b; D( E0 s
  108.         while(1){- O& n, g1 y4 Z! w/ F
  109.                 //PCON |= 0x01;        // 进入省电模式
    ! R6 m6 T1 p0 }& V# H2 k( U+ m7 F( r
  110.                 //_nop_();) p6 a/ ?% o' B
  111.                 //_nop_();
    & k0 S, W) c( A; B; D( s( \3 p
  112.                 //_nop_();6 }' [) E5 F* R8 S# T
  113.                 //_nop_();
    8 j6 D/ K- q* L
  114.                 buf = ~((P1 & 0x3F) | ((P5 << 2) & 0xC0));
    ) N" A: i/ H0 ], M1 q- g
  115.                 bufReady = buf;& j9 z. u+ y9 \6 t7 U4 N! O
  116.         }& [+ D5 D; S+ W& X8 R4 ^( N
  117. }
    ' ]6 B$ P+ Z& ]: h. r  m
复制代码

, C' w" m+ I0 Y8 d2 @硬件参数配置无特殊要求,晶振频率选择12M即可。7 F. J* Z/ c2 Q8 W/ R% M2 o) p! d# K

5 p1 E1 s# E, N9 U/ J" D这是编译好的固件。

本帖子中包含更多资源

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

×

评分

参与人数 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:052 `$ Y# E% F/ t1 ?% {
不错的设计,想问一下楼主,FC的15针公头怎么解决?普通的公头太短了,插不进去FC的扩展接口。 ...

  x4 O- x: r( n# w坛友的改造方案
回复

使用道具 举报

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

使用道具 举报

发表于 2019-5-25 12:07:18 | 显示全部楼层
精彩,楼主动手强,也写得很详细。! e' w) C+ b5 g; E
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:074 D( z1 }- P! f
精彩,楼主动手强,也写得很详细。
2 R$ S6 X+ ^, X( L6 q2.4G方案是目前无线的最低延迟吗?
: Q+ c0 z+ z5 [+ E) p4 Z! Q
我没用过其他无线手柄,所以实在不知道我自己做的这个手柄到底是不是最低延迟。
6 T! l; D' n$ J$ M5 T不过根据网上的说法,延迟高低主要是由通信协议的复杂程度,以及数据传输速率决定的。这个模块虽然是2.4G无线模块,但由于协议很简单,所以延迟比较低。( e* F- p( V7 A' L
我用这个手柄玩一些ACT游戏,比如超级马里奥、忍者龙剑传、热血系列,完全感觉不到延迟,和游戏机自带的手柄没有任何区别。唯一的区别就是这个手柄是用火花山寨手柄改造的,外壳是垃圾回收塑料,粗糙+脆弱,导电橡胶弹性不佳,手感不是一般的差。
$ h! w  ]( ~6 L; N: M# O我手里还有十几张板子,等我有空了我再做一套,到时候买一个好一点的手柄改造。
回复

使用道具 举报

 楼主| 发表于 2019-5-29 16:56:14 | 显示全部楼层
ppad 发表于 2019-5-28 17:27
7 V3 P4 Y6 M2 }% k2 P. h给技术帝赞一个,有半成品发布吗,自己焊接改造就可以,编程实在不会啊 ...
' V5 b& M/ p/ i- a
很可惜,我手里没有多余的单片机了,LDO也找不到了,锂电池以及充电模块更是没有了。反正就是该用到的元件基本都没了,所以没法发布半成品。2 U2 D) ^+ t; N8 Y
两个板子倒是有十几张剩余。7 q1 d* O3 o6 T0 c2 p
你要是有USB转TTL串口板,完全可以自己买这两种单片机,然后我给你编译好的固件,你自己用串口板下载到单片机里面就行了。两个2.4G无线模块也得通过串口板用AT命令设置参数,不过好在我在设计电路的时候就已经预留好了串口,可以直接在线下载和在线设置参数。总的来说并不麻烦。
回复

使用道具 举报

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

使用道具 举报

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

本版积分规则

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

GMT+8, 2026-7-15 06:06 , Processed in 0.108373 second(s), 14 queries .

Powered by Discuz! X3.5

© 2001-2025 Discuz! Team.

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