找回密码
 注册

QQ登录

只需一步,快速开始

查看: 26717|回复: 33

自制FC无线手柄

  [复制链接]
发表于 2019-5-22 14:16:45 | 显示全部楼层 |阅读模式
本帖最后由 雷精灵2046 于 2019-6-14 09:28 编辑 9 b$ [" H5 n9 B, d+ D5 a( g  U( P& H: c
1 K2 h0 O: B6 O( g- ~% x
没有用复杂的分立元件搭建发射接收电路,直接用的现成的2.4G无线模块jdy-40。: i2 h' V/ v9 _! [; D

( U/ s1 i" s' u# y0 Q8 s
4 A! E8 `! t4 V发射端靠3.7V锂电池供电,用了一片SOP8封装的STC单片机,负责产生连发脉冲,同时负责检测电池电量,电压低于3V左右的时候触发低压中断,低压指示LED就会亮起来告知该充电了。平时发射模块和单片机均处于睡眠状态,有按键按下才会唤醒,从而实现省电。实测睡眠状态下整机电流约1~2uA。板子洗了一下稍微干净了一点。因为对于微功耗设备来说,焊接残余的助焊剂可能会增加漏电流。
1 O. I4 x% @+ M* @; d; e. Y! |$ z3 }0 K' N
买了一个火花的FC山寨手柄,去掉里面的牛屎板子,并修正一下塑料挡板,把锂电池和充电模块装进去。3 {8 z" v1 R, o+ `& E+ s
为了减少体积,充电模块裁剪得十分小,并且更换了充电电阻使之适应这个小小的锂电池。这么小容量的电池,也不需要多么大的充电电流是吧?/ [: {. J& ?2 S! R
然后统统用热熔胶粘上。充电电流比较小,所以发热很少,不会熔化热熔胶。  q1 j) {" G9 N, t4 E# t! Q

! _% g) }5 ^' E$ D* \1 d+ f( ?2 i- q, U6 u" X6 ?* P

& \: i  \$ S$ B( `& B; G最后把按键、导电橡胶和电路板装上去。
/ G' P6 ^+ U9 x3 r/ h. R6 E精心裁剪了电路板,正好扣上,不会阻碍其他元件,也不会影响后盖和拧螺丝。
6 y& ~4 o2 N! o! D6 Z8 h, P% S4 s! {! b1 L- ]

3 `8 X1 z6 p1 u0 J: ]( t! s完工!6 c3 V! i! A9 U4 x. i! w

6 {. y; |/ Q! {( W# r$ Q
# H0 T( }/ D+ s! w( o0 ?这是充电的MicroUSB插座。旁边的小孔用于透出低压报警LED的光线。5 Q# c, E0 Z1 R- A7 ~) C

9 R' b4 c' J) [; s4 s7 g' F3 y. v- F6 }
1 t: S) Q- r1 W* c4 M/ c# s+ c% ^接收端用一片DIP16封装的STC单片机模拟CD4021。为啥要用单片机模拟而不是直接用CD4021?因为jdy-40模块接收端在有按键按下的时候输出高电平,无按键按下输出低电平,和普通手柄正好相反。当然我也可以用两片74HC00或者74HC04之类的逻辑门进行反相,但那就增加了芯片的数量。对于FC手柄这种工作频率并不高的设备来说,STC单片机完全可以胜任模拟工作。  I& h6 `9 e7 c( ^

$ s4 }# A1 k) u+ j" V5 H" {4 ^4 b0 D: x! j& X8 T

# C" H# I8 R( t, J电路设计有点小小的错误,所以有几根飞线。原本设计使用低压差LDO是XC6206,结果在做这个接收模块的时候,买的LDO居然找不到了!无奈只好用了AMS1117。幸好对于接收模块来说是5V降到3.3V,1117可以胜任。要是发射端手柄的话,3.7V降到3.3V,那就非得用6206不可了。9 T) L5 I! F2 a' t! v  ^) g/ N

3 l( @5 Z: t6 \* t实测十分灵敏,延迟极小几乎感觉不出来。可惜这山寨手柄的手感并不佳,尤其是方向键,软塌塌的。看来我得买个剪线手柄改装。1 w8 k+ I' D, z7 N7 _0 u0 @

( {3 x* `; Z+ A, r! {  x+ a$ k9 k这是电路图,有兴趣的朋友可以参考。5 n0 v! N7 b+ A% B* ^  x

. X; |8 \# O( E9 f, l
( J4 o- d: C+ M6 n  m+ }. k我信奉开源主义,十分痛恨把技术藏着掖着。好东西大家分享嘛!所以两个单片机的源代码大公开!( }. A' [9 A' x' _; B9 H& {
编译器:Keil 51。
2 j: }$ J9 c2 Z( p
9 Y9 X$ ?9 T, r5 K" @% q发射端:
# L: c( C" r* V& G" g
  1. #include <INTRINS.H>
    : K- V: V9 z" E2 X" m) x$ k
  2. #include "STC15W.h"4 q7 Y1 g. \0 X+ U. O
  3. 8 a2 `, k0 @- [7 V3 e" z8 }0 P
  4. 9 H7 ?9 {1 e, H) U
  5. /*! J! |- O* Q; f; e8 j% a
  6. --------------------------
    9 t$ d" k) g$ L7 b
  7. |1 (OUT)        \__/   (INT1) 8|1 B/ |; @) k5 D: N; q) m( b
  8. |                                                   |
    ) m$ J& L* @! M- T( `3 k1 F9 I4 Y, H
  9. |2 (VCC)                   (INT0) 7|
    4 k  p3 I& |, W( l* C8 M
  10. |                 STC15W204S                   |" P7 V0 L  {- l" b/ E- c# d5 v
  11. |3 (LED)                         (TXD) 6|' i) e* d  I: e. q. [& T
  12. |                                                   |
    # V. R9 o& L, Y
  13. |4 (GND)                         (RXD) 5|+ O# ~' Y/ t- i0 E. i2 p3 w
  14. --------------------------" X0 t8 }+ k2 v5 ^: E
  15. " Q9 `0 B# A7 A: R! }
  16. LED ---|<|---[===]--- VCC. |) a4 V- x  C: S; @+ j9 P
  17.            Red          330
    ) V/ |( k) `7 Z5 `( O2 l

  18. 6 X' [( V7 A7 w" M& e$ s" D- G* i" W! Y
  19. Fosc = 6MHz2 J3 r7 K0 {8 d* z- \2 S
  20. */; f( `, o5 W; {1 v
  21.   i: T# w0 P( l& t4 H. U: O. X

  22. ( A2 e% V: ?& E* F9 p( o
  23. // 矩形波输出脚* D" ?5 d4 K  m$ ?8 V1 q
  24. sbit OUT = P5^4;( p" O. k1 C. F, [9 p6 L: n
  25. // 低压指示灯引脚; o0 }# t* m/ n! H- M
  26. sbit LED = P5^5;9 G% e$ |; l4 g+ ~9 V

  27. 8 d# i+ b  i( }, t
  28. // 停机标志位
    5 P# {# u4 M, G/ q! ?% d3 ]
  29. bit isReadyToHalt = 0;
    % w4 V6 R& f6 m. T4 i
  30. 2 t, n6 u- j" H" o
  31. // 矩形波次数累计. }! O% V/ b! F- }9 p8 M9 i
  32. static volatile unsigned char count = 0;
    6 }- @; C7 `# a0 Q

  33. 9 y6 F. t+ ]) t9 C- u5 g1 r
  34. % q' w4 T  V" h" M) I) w8 m+ N
  35. static void GPIO_Init(){
    + P" @* W7 v/ V3 N/ U$ V8 |  Y" Y
  36.         // P3口设置为准双向,默认靠内部弱上拉输出高电平
    6 P3 o& s  n+ V* A# o
  37.         P3M0 = 0;* Y2 w! `9 y7 o
  38.         P3M1 = 0;) [3 d! o* I: t
  39.         P3 = 0xFF;
    & z1 h; Z4 I0 }: J3 u
  40.         // P5口设置为准双向,默认靠内部弱上拉输出高电平
    * r* I: `9 w$ A, Q8 p) s
  41.         P5M0 = 0;- \- `7 y- ~! P* A
  42.         P5M1 = 0;% D$ E1 A; L) m. f! O
  43.         P5 = 0xFF;  Q8 B+ g7 D; e* N' R$ b
  44. }- A4 S3 C$ H5 }- n

  45. # D2 d! U! }* W
  46. static void Timer0_Init(){7 ~/ O8 c/ i/ p! T" {
  47.         // 16毫秒@6.000MHz' ]9 @# s5 [% Y& l
  48.         AUXR &= 0x7F;        // 定时器时钟12T模式
    8 w- R, G% w( ~
  49.         TMOD &= 0xF0;        // 设置定时器模式
    5 Y5 T$ U4 U. b; z" N
  50.         TL0 = 0xC0;                // 设置定时初值
    4 ~6 O9 R4 e  s" b* ~, G$ m  u
  51.         TH0 = 0xE0;                // 设置定时初值
    - F9 U- P; f  x! U) G
  52.         TF0 = 0;                // 清除TF0标志" W7 m) R6 K7 e
  53.         TR0 = 1;                // 定时器0开始计时4 Q" L" |9 s# F# E
  54. }6 k3 |# q5 r  M4 Z* W% K, \: q  n

  55. 1 E* [$ ~9 e9 ]
  56. static void Interrupt_Init(){7 m' S4 f' T2 |" K
  57.         // INT0中断触发类型为下降沿触发. O5 _/ N$ @$ Z' ^/ G4 d7 G! w( t
  58.         IT0 = 1;5 }- ?. J2 t2 a% J$ a
  59.         // 允许INT0中断. n7 V' x2 ~8 {
  60.         EX0 = 1;5 Z  c; O1 i* k6 G1 {. `
  61.         // INT1中断触发类型为下降沿触发
    # y+ A" W0 d! H2 M
  62.         IT1 = 1;
    ' m/ M- |" w% t. L9 z$ w, h
  63.         // 允许INT1中断" ]; M, p8 _3 v9 N" m9 o. ^; x* p
  64.         EX1 = 1;
    2 f' C; F. h7 r% u+ T
  65.         // 允许定时器0中断
    ' @. C( E# Z( O9 ^1 m( N# {. L
  66.         ET0 = 1;
    & I* I$ R. j) ~" W: G
  67.         // 允许全局中断
    7 I' f% v0 A1 Z
  68.         EA = 1;
    2 T5 C0 l% m0 I2 y$ K9 X1 E) E
  69. }
    * X1 I0 l8 [% y/ O: K, @

  70. 6 E2 |0 c0 p  L+ `- |! r
  71. static void INT0_Isr() interrupt 0{! b/ s5 S8 c1 @2 c) ?0 a% V( b
  72.         // 矩形波次数累计归零' C# u0 I, U4 J# L$ \0 |
  73.         count = 0;- [/ o8 J  C# W. B2 D7 h" m
  74.         // 重开定时器0中断
    ! k6 I' S. _- P5 P! h
  75.         ET0 = 1;
    . L/ m( T" g! y2 f8 ?* V% G/ W
  76. }
    & n) k2 L: I4 {) z0 Y

  77. / q& A9 @+ s7 t; a& D
  78. static void Timer0_Isr() interrupt 1{
    # \% c, ?8 q  M' w/ \
  79.         // 输出矩形波
    / t, J& z" x) b. E) c
  80.         OUT = ~OUT;
    % M- Q  }$ s8 M$ T
  81.         // 累计矩形波次数
    , M  ~9 r/ _$ I9 A9 ]& }* ~& _
  82.         count++;7 |/ q0 F5 o1 s* V- Q/ A
  83.         // 超过250个矩形波,准备停机% j& V4 e8 Q; q; h7 B7 `
  84.         if(count > 250){
    ( p5 {* R. }7 q. P3 A1 Y
  85.                 count = 0;
    & J. a2 e3 S; H7 W1 W- ~
  86.                 isReadyToHalt = 1;! Z' [# f, w9 x9 j0 e' n3 e
  87.         }
    / e* _0 K" j) C
  88. }$ q& ]5 p4 d: n3 J- |0 i4 ]
  89. 8 l2 G0 E$ Q; h) `* k
  90. static void INT1_Isr() interrupt 2{, t5 I6 g8 f5 H% x* ~
  91.         // 矩形波次数累计归零
    - V& E2 ~; y) }% [9 n7 C# e  e
  92.         count = 0;
    ! x0 R. N' {: T; K2 \
  93.         // 重开定时器0中断4 A7 z) X5 X" `- j% n: f$ k5 n' D% h9 J
  94.         ET0 = 1;1 l  c  V( c, Q% N# f. A3 n* T
  95. }- A- o0 E4 T2 N. W7 B/ Y# ^9 E" j; ~

  96. 8 I* y+ s+ t6 i" G0 p

  97. : U3 \1 |7 f: X0 i% K
  98. void main(){
    0 L3 B( @- y6 d; N! D, \: {
  99.         // 初始化P3和P5口
    4 w. ~; g4 z" d) c
  100.         GPIO_Init();
    2 V0 o4 \5 J; [9 D
  101.         // 初始化定时器0
    ! s. X& l" s/ o4 {" \8 }) j/ Q& U
  102.         Timer0_Init();
    ! t8 T, a9 \, A* d, `7 ?
  103.         // 初始化中断
    ; m) h3 f' j1 \" D4 u- t
  104.         Interrupt_Init();
    6 [: I. g2 o  r1 C& d. z4 g
  105.         / I' n" ]2 c8 z
  106.         while(1){1 N8 y3 E5 ^9 l; J, Z
  107.                 // 检测电量
    + `: {6 c6 a( @9 \- \5 e. n$ F5 ~
  108.                 if(PCON & (1 << 5)){
      @" \0 @$ {! ~" `2 n/ w: I
  109.                         // 如果电量低,低压指示灯亮
    & Y, r6 K) S5 R9 C7 W
  110.                         LED = 0;
    " g' f  l. @- i9 B' U6 X+ E
  111.                         // 清电量检测硬件标志位0 G6 x5 i& ]7 L- W, r+ Y
  112.                         PCON &= ~(1 << 5);- ~# b* U7 S. P* y
  113.                 }else{
    . ~* D0 @, s. U7 g/ m4 a- |% ~
  114.                         // 电量正常,低压指示灯灭+ V& s% @7 z4 A6 ~' e
  115.                         LED = 1;) X" }( h; v! b0 I. {4 V5 e" P% Y
  116.                 }" F& U6 J/ v8 B5 E+ z
  117. 1 c9 {* h- D- ^5 g) B5 F
  118.                 // 检测到停机标志2 M7 X# S+ L* x6 h! n
  119.                 if(isReadyToHalt == 1){- {! d! d6 H# \& S/ @
  120.                         // 暂时关闭定时器0中断
    ' |/ b+ Z  c$ Y& Q3 l
  121.                         ET0 = 0;0 _! w0 S, i) z7 @5 e
  122.                         // 停机之前先把矩形波输出脚置低电平,以方便INT0和INT1唤醒CPU
    " Q. |/ ^7 j0 G  `) R
  123.                         OUT = 0;
    : Y) z- E. R  E$ M" \5 h
  124.                         // 停机之前先把低压指示灯灭掉,以省电: y% `! B0 x+ e- p
  125.                         LED = 1;
    / u( d4 g0 q: C* K' n( L
  126.                         // 进入停机模式: v. _9 F$ k: I5 q1 L# S4 A: @
  127.                         PCON |= 0x02;8 L" f  h* ~: w4 V. Q) ?2 [. w" k8 I
  128.                         _nop_();9 A$ M0 {  j. S& |" X4 E- ^" q
  129.                         _nop_();
      G# Z% k6 R5 ?7 A
  130.                         _nop_();7 M5 {/ @1 [  q3 u3 b8 ~: `2 \' w$ i
  131.                         _nop_();
    6 y1 R7 G8 a  o2 n0 b% Q% N; M
  132.                         // 唤醒,清标志位
    6 \* X0 i, f# ^' u/ O
  133.                         isReadyToHalt = 0;+ c( W! c3 i% d" z
  134.                         // 重开定时器0中断
    2 s  Q+ }9 X1 Z4 x1 ~5 V
  135.                         ET0 = 1;
    & e8 b- D8 q1 Y7 K" V9 {" F: y, `# ^
  136.                 }' d) l- n$ E0 J8 R$ N
  137.         }3 X/ L' `/ I6 {8 ]* w0 K
  138. }
    ( r! O- y+ h/ d  y9 A0 ^0 i! J
复制代码
1 L( g8 c9 \9 f
硬件参数配置:  D! k) H2 L& d9 z9 D' |* ^1 b
+ x- r" a  W- [: Y' V4 o

# \* F1 M. [. R+ U) F接收端:2 F  `7 o* l/ A/ N/ a5 C
  1. #include <INTRINS.H>  f0 H5 p+ V& Z" T1 u3 f2 y# d! E
  2. #include "STC15W.h"$ B( n7 l  {) s2 u* g/ F9 A2 W" E+ V
  3. ! p) w& V1 I0 v4 `; P

  4. $ i4 o4 o: Q( k/ S' r" i0 l, y
  5. /*( m2 Q  D& E5 N, `% B2 H* N7 V

  6. ' J# G$ A% v3 R) i* V, v
  7. *---------------------------*% |0 B" Z9 R9 Q9 j' L$ v
  8. |1 (GPIO2)         \__/  (GPIO1)16|
    ! O: G# w1 d8 f4 M
  9. |                                                        |4 {# ?2 ?# }: d9 Y
  10. |2 (GPIO3)                   (GPIO0)15|
    8 ]* |1 C% [0 e5 B
  11. |                                                        |
    + a" E7 x( ?* [: k
  12. |3 (GPIO4)                                  14|7 Q; h3 c* j: X# q  ^  ^, U
  13. |                                                        |
    6 ^5 q& \3 o& ~* a
  14. |4 (GPIO5)                        (DATA)13|( @( [( D' f0 n4 o/ J. t
  15. |                  STC15W204S                |
    6 \0 m! a, `: I* c- r
  16. |5 (GPIO6)                   (LATCH)12|
    & X+ M& W' T3 O: T4 Q
  17. |                                                        |/ w4 @$ k! T6 n# e' T7 k
  18. |6 (VCC)                         (CLK)11|) \% Q+ P0 v! E& `" z9 j
  19. |                                                          |* c% H7 A- n$ n# g: ~
  20. |7 (GPIO7)                         (TXD)10|8 W$ x7 a' h+ [1 }" i
  21. |                                                        |
    7 ~8 t1 S4 c# v% Y4 O5 p! k
  22. |8 (GND)                         (RXD) 9|' L5 b/ l$ \8 \, i! ?* s
  23. *---------------------------*
    5 J. r3 Z# ~8 H9 G$ Y7 Q
  24. Fosc = 12MHz
    ( t9 Z0 g, V2 y+ H7 ?. f  y
  25. & H4 V9 O& }' }7 b/ `( x
  26. P1.0 -> 上- d' e/ p- J# V5 u2 ]
  27. P1.1 -> 左: B, q* H. w" c
  28. P1.2 -> 下
    $ H* Y9 s6 ?  Y( A2 [) t( G  @
  29. P1.3 -> 右
    & P; l# o5 Y/ U. N
  30. P1.4 -> SEL1 e* Q( b- }& k' c3 w8 B5 k" P
  31. P1.5 -> STA4 g: H$ I3 J5 x) h: o
  32. P5.4 -> B$ N9 ~; z7 V9 e! k! r
  33. P5.5 -> A
    4 N1 K2 Y* o3 a, y, ^0 O

  34. 8 T* @5 ]6 D0 m! k" W
  35. */9 j( Q+ J4 [. S4 c+ ]+ q/ B
  36. 1 g! u3 Z. V: \0 h( D
  37. ' K; Q7 B# O+ v( F6 k& \: R
  38. sbit CLK        = P3^2;+ C. f. b$ ^+ \! A
  39. sbit LATCH        = P3^3;
    ) T" a) S! ~4 _( G$ f; v
  40. sbit DATA        = P3^6;" D+ s: _; s1 |2 ~9 V6 o

  41. ' f. w6 \/ w. B  u
  42. bit isReady = 0;  t1 o* h) N+ G/ n
  43. static unsigned char key = 0;
    , O5 E8 ~( c- W* `( w5 E
  44. static unsigned char buf = 0;        // 双缓冲。这个缓冲区保存从P1和P5组合而来的键值+ ~* m7 @7 g; C4 A- q% }  ]* R
  45. static unsigned char bufReady = 0;        // 双缓冲。这个缓冲区保存上面那个缓冲区的备份
    / Y* f+ y$ \( A7 n5 ^( o. y# C
  46. static const unsigned char data mask[] = {0x80, 0x40, 0x10, 0x20, 0x01, 0x04, 0x02, 0x08};        // A B SELECT START UP DOWN LEFT RIGHT。为提升速度,这个表放到RAM中
    . V8 I; a3 W( v/ i. ~* m
  47. static unsigned char idx = 0;2 r2 ^3 V8 P7 e
  48. 8 j9 q0 G2 o6 s* s! _4 d
  49. 9 N0 g  h5 C* Z' Z5 @; M
  50. static void GPIO_Init(){+ F! |' Y4 A+ ]7 o; K6 n
  51.         // P1口和P5口用于接收并行信号,全部初始化为准双向,依靠内部弱上拉输出高电平
    / m+ j2 E) S% m; I9 N
  52.         P1M0 = 0;  e9 c% O. {( Q' e+ K
  53.         P1M1 = 0;# E6 _# q+ t9 b5 u4 {
  54.         P1= 0xFF;, T0 v1 j/ i* }
  55.         P5M0 = 0;6 w( ?" B/ O5 ^# x* S. [* U; e
  56.         P5M1 = 0;
    - c8 M# Q& v# S" z/ s
  57.         P5= 0xFF;- e$ M% q& I2 B7 k
  58.         // P3口初始化为准双向
    % r$ Y! ~, F. c8 m, c
  59.         P3M0 = 0;
    * S& Q% ?% v' `0 j7 e/ g
  60.         P3M1 = 0;( o' Q$ ~" B, b+ c3 Q# v! e9 T( c; K
  61.         P3 = 0xFF;
      T* b2 s2 j2 I8 l
  62. }
    ( b; l9 W/ f- ^' @/ q' _' R
  63. 6 v3 d+ _; m* W$ y
  64. static void Interrupt_Init(){" }1 C0 ^! ?! p3 c, n5 ]; \
  65.         // INT0中断(CLK)触发类型为上升沿+下降沿
    . r& l; L& v3 C% q! W, y
  66.         IT0 = 0;3 t& u/ u( T8 |! |! Z( j8 k+ k
  67.         // 允许INT0中断
    ! @4 f* ]2 e8 x; E8 O* {$ i2 C: n
  68.         EX0 = 1;+ b) M( R0 s$ K* T' `- d
  69.         // INT1中断(LATCH)触发类型为上升沿+下降沿
    5 M' y8 E. ]2 V$ H/ C
  70.         IT1 = 0;1 x; h; v* q: ^5 G
  71.         // 允许INT1中断! D0 K# o7 m) ]$ V. u
  72.         EX1 = 1;
    + d* U( f$ S3 |$ O# @
  73.         // 开启全局中断! g2 a. B, |. ^+ [- N
  74.         EA = 1;% c0 ]( m* y) N7 H6 t6 q
  75. }
    0 T  L& U  _* \8 {
  76. - {7 {! D0 o$ y- _6 K; X
  77. static void INT0_Isr() interrupt 0{
    ( b7 ?# G' J: l. h
  78.         // 只有已经成功锁存才允许CLK移位1 h% Q$ j/ z4 I9 z# d0 N
  79.         if(isReady == 0)
    6 @" }8 H- L6 A" X# ?
  80.                 return;# ~2 B6 e5 r- s, C) H
  81.         // 读当前引脚电平,如果是低电平则说明是下降沿,此时直接忽略该中断
      g; U" J- D! u, m2 T( [
  82.         if(CLK == 0)
    / j: w7 x9 s& E8 I7 ]
  83.                 return;
    . C7 H1 n7 c5 l) }5 Z. i; t! P
  84.         // CLK上升沿到来的时候,取锁存值的下一位输出( Z. n( b6 q) ?, V+ P; e- s; I
  85.         idx++;, Y5 m# g- f# a) A4 z# R
  86.         DATA = key & mask[idx];: |3 ~2 Z8 |3 m% M/ ~2 G9 p! D
  87.         // 如果已经完成7次移位,则一轮读取完成
    & n7 z, w0 z* C$ e
  88.         if(idx >= 7)
    $ a7 n" I2 `4 y& N) _" Y
  89.                 isReady = 0;
    , u2 Q1 {3 G9 o- u) s3 ~+ U0 C
  90. }5 P* b. o) y  D) F' B( [

  91. 9 }9 U. F& y; i: X2 A8 Z
  92. static void INT1_Isr() interrupt 2{! S; B0 {7 d- K7 C7 B! N$ I
  93.         // 读当前引脚电平,如果是低电平则说明是下降沿,此时直接忽略该中断
    7 |! z& W# z& @: E0 _
  94.         if(LATCH == 0)8 e/ P. `7 {* g5 `; b/ o. z
  95.                 return;
    4 W$ S$ `  B" T/ G0 }
  96.         // 当LATCH上升沿到来的时候,锁存所有按键状态,同时把键值A输出到DATA
    9 Y& b0 k* D1 z8 k2 Z( J2 O
  97.         key = bufReady;
    ! l8 \- J- n9 U: M9 R/ B
  98.         DATA = key & 0x80;//mask[0];        // 为了加速运算,直接取表中的值而不是读表0 j% Q( Z( k$ c2 S" P/ L
  99.         idx = 0;
    4 J- S# z1 c  w$ G3 c
  100.         // 允许CLK进行移位
    4 R; S- K2 ?! s% V. ]6 [8 t
  101.         isReady = 1;
      Q: b6 y. A7 m. W  t7 ?' Y  @1 ~
  102. }
    ; z/ L; {& J0 ]. S5 a4 o* S
  103. " O6 E# I8 f' c! L8 o5 Q
  104. void main(){9 R5 }3 i6 V, }: r9 o! \6 ^
  105.         GPIO_Init();
    ' r6 A1 J( |9 R6 R2 c; K4 _1 Z6 q% F
  106.         Interrupt_Init();* M+ K5 x* v2 r8 V
  107.        
    4 G6 Z* W( o* q" X) h: l# a
  108.         while(1){
    " w; M( B9 i: O2 o* g7 T$ n" C
  109.                 //PCON |= 0x01;        // 进入省电模式2 Q" ~: E6 Z  I$ V' z: c
  110.                 //_nop_();
    : R% `+ N$ a. ]  j6 L
  111.                 //_nop_();4 \. Z% t4 V4 U( k4 e
  112.                 //_nop_();
    / M5 A8 D8 A! W$ G
  113.                 //_nop_();
    ( A: q" v5 I2 R) w, E" R7 v3 h3 e
  114.                 buf = ~((P1 & 0x3F) | ((P5 << 2) & 0xC0));; n2 O# Q4 @5 D" F
  115.                 bufReady = buf;! a  P) S" [7 D+ m
  116.         }
    2 ?. C; {! N- b! n7 C: |$ k9 ?
  117. }
    . ^: n' I9 J( h& E8 Q' n
复制代码
4 P+ w" Y% O/ Y& D& o  A
硬件参数配置无特殊要求,晶振频率选择12M即可。
( O+ z5 [# q; [) D/ G' I0 D
8 F. ~- |, ^; x7 }, }' j2 S这是编译好的固件。

本帖子中包含更多资源

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

×

评分

参与人数 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
# t; i+ Q. t# M8 G不错的设计,想问一下楼主,FC的15针公头怎么解决?普通的公头太短了,插不进去FC的扩展接口。 ...
& V8 y: g; s% s7 X
坛友的改造方案
回复

使用道具 举报

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

使用道具 举报

发表于 2019-5-25 12:07:18 | 显示全部楼层
精彩,楼主动手强,也写得很详细。1 M( {: u  u: C9 ~3 j; R# Z
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 F9 m3 v( e; x6 |" ^6 k精彩,楼主动手强,也写得很详细。8 D6 m5 x! O% e$ v
2.4G方案是目前无线的最低延迟吗?
! @2 X, v5 O; f/ U
我没用过其他无线手柄,所以实在不知道我自己做的这个手柄到底是不是最低延迟。
! x  a5 Y9 Q! \+ H2 F! m9 f* s不过根据网上的说法,延迟高低主要是由通信协议的复杂程度,以及数据传输速率决定的。这个模块虽然是2.4G无线模块,但由于协议很简单,所以延迟比较低。
9 E/ c6 [" P8 e! m我用这个手柄玩一些ACT游戏,比如超级马里奥、忍者龙剑传、热血系列,完全感觉不到延迟,和游戏机自带的手柄没有任何区别。唯一的区别就是这个手柄是用火花山寨手柄改造的,外壳是垃圾回收塑料,粗糙+脆弱,导电橡胶弹性不佳,手感不是一般的差。
6 ~6 \: Y! t3 \1 L我手里还有十几张板子,等我有空了我再做一套,到时候买一个好一点的手柄改造。
回复

使用道具 举报

 楼主| 发表于 2019-5-29 16:56:14 | 显示全部楼层
ppad 发表于 2019-5-28 17:27
5 \9 }; v# H' _- L给技术帝赞一个,有半成品发布吗,自己焊接改造就可以,编程实在不会啊 ...
7 e, ~  v8 w1 Q
很可惜,我手里没有多余的单片机了,LDO也找不到了,锂电池以及充电模块更是没有了。反正就是该用到的元件基本都没了,所以没法发布半成品。3 [( b3 I7 r2 }8 \2 R" f6 W; f" r
两个板子倒是有十几张剩余。
: B0 X6 F5 |. d# j) n' ~你要是有USB转TTL串口板,完全可以自己买这两种单片机,然后我给你编译好的固件,你自己用串口板下载到单片机里面就行了。两个2.4G无线模块也得通过串口板用AT命令设置参数,不过好在我在设计电路的时候就已经预留好了串口,可以直接在线下载和在线设置参数。总的来说并不麻烦。
回复

使用道具 举报

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

使用道具 举报

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

本版积分规则

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

GMT+8, 2026-9-15 14:02 , Processed in 0.536794 second(s), 14 queries .

Powered by Discuz! X3.5

© 2001-2025 Discuz! Team.

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