找回密码
 注册

QQ登录

只需一步,快速开始

查看: 24328|回复: 32

自制FC无线手柄

  [复制链接]
发表于 2019-5-22 14:16:45 | 显示全部楼层 |阅读模式
本帖最后由 雷精灵2046 于 2019-6-14 09:28 编辑 : b% ^& X; u2 j

% t6 a. j8 n+ u1 g) i7 E没有用复杂的分立元件搭建发射接收电路,直接用的现成的2.4G无线模块jdy-40。
; o1 L5 J) {+ a
1 l$ ^' o3 I3 Y
: W  m& d' x7 d) f3 U9 k5 C7 @发射端靠3.7V锂电池供电,用了一片SOP8封装的STC单片机,负责产生连发脉冲,同时负责检测电池电量,电压低于3V左右的时候触发低压中断,低压指示LED就会亮起来告知该充电了。平时发射模块和单片机均处于睡眠状态,有按键按下才会唤醒,从而实现省电。实测睡眠状态下整机电流约1~2uA。板子洗了一下稍微干净了一点。因为对于微功耗设备来说,焊接残余的助焊剂可能会增加漏电流。
: O0 d/ N& H* @3 Y1 Q
, Q. x" `$ w+ U. K8 d- K5 G% z买了一个火花的FC山寨手柄,去掉里面的牛屎板子,并修正一下塑料挡板,把锂电池和充电模块装进去。
9 o/ F2 V( Y' E0 f2 e为了减少体积,充电模块裁剪得十分小,并且更换了充电电阻使之适应这个小小的锂电池。这么小容量的电池,也不需要多么大的充电电流是吧?
2 ]0 j: Z6 _, ?7 d然后统统用热熔胶粘上。充电电流比较小,所以发热很少,不会熔化热熔胶。
' v1 x( X% s, U2 [& U' b8 ~$ t; j5 Y) S( x; z
+ [1 S* M' H0 ^0 u% |) E) Z, U# J

2 ~: d* v" g+ V1 B( H最后把按键、导电橡胶和电路板装上去。! G' E- C& @0 j( f/ ~( Z( {0 Y
精心裁剪了电路板,正好扣上,不会阻碍其他元件,也不会影响后盖和拧螺丝。. |+ i2 H- [" X( t+ r4 R
. ~$ M  h: A& K
! [# z  b0 O9 p: m6 [. Q5 o) @& `
完工!
4 W% ^- D. N2 T" I+ O+ @. M" Q, f
# R; d) Y4 X! S! k0 X* [/ {" D9 F  w: \) Z2 |
这是充电的MicroUSB插座。旁边的小孔用于透出低压报警LED的光线。, s# q7 `% z, T; T# @- {
7 ^0 f/ Z+ J- q

7 ~1 G( F# q2 F9 Z接收端用一片DIP16封装的STC单片机模拟CD4021。为啥要用单片机模拟而不是直接用CD4021?因为jdy-40模块接收端在有按键按下的时候输出高电平,无按键按下输出低电平,和普通手柄正好相反。当然我也可以用两片74HC00或者74HC04之类的逻辑门进行反相,但那就增加了芯片的数量。对于FC手柄这种工作频率并不高的设备来说,STC单片机完全可以胜任模拟工作。
0 x3 J# H: W+ j' |- [' a
: [2 R  s$ W! v1 R9 l, m' S4 _8 t: t' Y7 l% i2 l! g! M& Z4 T

3 i- u0 b: {. D9 C! B+ ?电路设计有点小小的错误,所以有几根飞线。原本设计使用低压差LDO是XC6206,结果在做这个接收模块的时候,买的LDO居然找不到了!无奈只好用了AMS1117。幸好对于接收模块来说是5V降到3.3V,1117可以胜任。要是发射端手柄的话,3.7V降到3.3V,那就非得用6206不可了。6 t  x8 ?- n/ H

1 a% k' d; V  ?6 H& k7 ^实测十分灵敏,延迟极小几乎感觉不出来。可惜这山寨手柄的手感并不佳,尤其是方向键,软塌塌的。看来我得买个剪线手柄改装。8 v# x  E1 k/ y

) I$ p" c7 f8 E2 x4 {& q$ y3 [: a( G这是电路图,有兴趣的朋友可以参考。
: \. ?9 C: R5 s+ i: B6 W$ k/ U) z* `. W. l( V. m* c
- M$ M$ K8 a' `1 m* y- Y2 y2 J% c
我信奉开源主义,十分痛恨把技术藏着掖着。好东西大家分享嘛!所以两个单片机的源代码大公开!
& y/ h( ~4 {+ w! w  |8 X" h  q编译器:Keil 51。
& A6 G1 m( ~+ x+ o" G9 x+ f9 N. o8 T8 S, g. P( _2 x; ~( {4 G+ }3 {
发射端:
" r1 S' O% A" ]) {$ U
  1. #include <INTRINS.H>% t: h) Y, r% t+ \$ y& n- u; T* V% W" k
  2. #include "STC15W.h"
    0 K7 b4 T: Q- H

  3. : A- S7 N) K1 M8 Y
  4. , v/ h1 J% n  f# F8 n1 H! ?
  5. /*% V# q% D, t% l" V
  6. --------------------------
    0 A6 A) z; B- Z0 U* _
  7. |1 (OUT)        \__/   (INT1) 8|
    - f0 X2 ~0 ?1 m
  8. |                                                   |
    0 Q# w3 ^- `. ]5 L3 s) _- p+ s3 i' S
  9. |2 (VCC)                   (INT0) 7|
    ; H# n) T* i" t, Y1 W& }
  10. |                 STC15W204S                   |
    , R2 s5 L6 g  G! s
  11. |3 (LED)                         (TXD) 6|2 q3 P" z4 ]9 H% r+ m2 h& g
  12. |                                                   |+ Y7 Y2 n! u7 y/ q- g
  13. |4 (GND)                         (RXD) 5|3 |  z- e) u9 ^  q- m7 v! w
  14. --------------------------
    4 q+ G3 q6 P) x
  15. + M, I+ \% t" `- @9 ]
  16. LED ---|<|---[===]--- VCC$ `! Z9 y/ B4 b
  17.            Red          330
    ! Q6 g: m$ b, L$ a  ]* T
  18. 5 q' p6 i; H) T9 A) F1 k  P' f" m
  19. Fosc = 6MHz
    * d: R8 Z& X  j6 h/ n6 m) y+ q
  20. */& N8 m" R2 `6 J) |5 y% ?

  21. $ }2 X, P: W7 y6 u4 M' U

  22. . |) J% F1 G6 b2 Q2 A+ S
  23. // 矩形波输出脚
    / m0 C7 Y# {4 `
  24. sbit OUT = P5^4;
    # R5 u9 l1 u$ s+ O: c. E
  25. // 低压指示灯引脚
    5 J0 n0 J4 c9 T: q' y
  26. sbit LED = P5^5;
    & G3 H0 x$ m6 K
  27. " Q* a3 x5 g+ |2 Z! \2 c
  28. // 停机标志位
    ) t2 t" v: l8 }# x) k$ C1 L) b4 C
  29. bit isReadyToHalt = 0;, c. {, }. u1 ~
  30. ) ~2 f* _# n' O; w8 t
  31. // 矩形波次数累计
    & q6 u1 `  p' a
  32. static volatile unsigned char count = 0;
    + X/ T1 Y+ [' k+ ?. U
  33. 2 k' `3 l* q  F* X% g+ @& H

  34. " F% _0 `% l% w: b) W0 b
  35. static void GPIO_Init(){! A1 h" g5 k( z2 j9 y: z7 [
  36.         // P3口设置为准双向,默认靠内部弱上拉输出高电平5 o2 `/ p/ ~, z' V7 x' U
  37.         P3M0 = 0;( ~6 v2 b1 s- z4 u( k0 U  P$ C( f2 Z# K
  38.         P3M1 = 0;
    3 F$ y3 |% U5 P8 S/ t( f
  39.         P3 = 0xFF;! P0 o: H% ?, D6 j2 m
  40.         // P5口设置为准双向,默认靠内部弱上拉输出高电平% ]5 Y1 e0 x  U9 r
  41.         P5M0 = 0;
    : L. K, Q1 l# t/ E2 X/ Q0 O
  42.         P5M1 = 0;
    " q: |3 e5 n# X  m
  43.         P5 = 0xFF;" u. |0 U  A4 ^
  44. }
    # _2 r4 o0 x+ u7 V( W- ^3 {- c8 H
  45. 6 a. [* v; r+ W# u
  46. static void Timer0_Init(){: x1 a& S7 W" i9 i" j
  47.         // 16毫秒@6.000MHz- A" }3 h+ \+ e( A* S: w) Y+ P
  48.         AUXR &= 0x7F;        // 定时器时钟12T模式* Y: l$ ^# T" `! Z) g
  49.         TMOD &= 0xF0;        // 设置定时器模式
    9 F+ c! f- z3 O/ J4 Q" g2 q
  50.         TL0 = 0xC0;                // 设置定时初值) P& D6 w" `& Y& q
  51.         TH0 = 0xE0;                // 设置定时初值
    ) p  h+ u5 x, `) \  ~
  52.         TF0 = 0;                // 清除TF0标志
    3 J6 x' b( e+ D& l( ^& t9 C
  53.         TR0 = 1;                // 定时器0开始计时7 f- N6 W/ \* Z/ g! j
  54. }# ^1 u0 a8 W- q3 Z; ~: m
  55. 1 D9 n6 J; l# w- j: m$ \1 k
  56. static void Interrupt_Init(){% K) G4 C' _2 d( I
  57.         // INT0中断触发类型为下降沿触发+ Z  H6 Z& h+ l: j& |8 f
  58.         IT0 = 1;. N" k7 A: `! p2 t* I: c2 u7 V
  59.         // 允许INT0中断! \( V+ P" ~( i
  60.         EX0 = 1;' T1 G- @1 ?: [3 U6 f5 {6 v
  61.         // INT1中断触发类型为下降沿触发
    % S" i/ |4 s: _% @3 p
  62.         IT1 = 1;/ O/ f3 n+ H( K# S/ n" j1 m4 {
  63.         // 允许INT1中断+ n/ E9 C5 m! C& K1 w) Z' F$ \
  64.         EX1 = 1;
    1 F' a+ ~5 X7 p" b8 P: a
  65.         // 允许定时器0中断! i4 p1 ]8 n! i9 Z  [2 e- X
  66.         ET0 = 1;
    7 f! [# q  ^2 @" F/ S+ D
  67.         // 允许全局中断% l$ ?% x, V7 w" U  S- p
  68.         EA = 1;
    / w( p0 L# [7 \
  69. }
    5 r. r* H! G5 s7 x

  70. 3 j4 n! y* u  o. j. s  H6 C: Q8 g
  71. static void INT0_Isr() interrupt 0{/ h' ?+ b, V$ g- I& y
  72.         // 矩形波次数累计归零
      ^) C3 e- x/ l$ }7 p- M
  73.         count = 0;
    $ @2 X# }3 V1 J. A8 t
  74.         // 重开定时器0中断
    & L' ~+ w2 S* Y' \9 U% z) C7 P
  75.         ET0 = 1;
    ; K' D( s9 Q3 T. Y, m8 h7 b: |$ G
  76. }% ~3 [6 z8 I7 T' @
  77. + c' B. A& [, o: _% C
  78. static void Timer0_Isr() interrupt 1{& m# N$ T6 J' |- S- c
  79.         // 输出矩形波
    2 K. c% ~* Y4 K9 ?- a; M# C
  80.         OUT = ~OUT;: l6 z+ X/ W" r* v3 W
  81.         // 累计矩形波次数
    % v2 v( i9 S; Z2 P
  82.         count++;
    : ?5 X7 M" f/ h* W$ [
  83.         // 超过250个矩形波,准备停机! o; _7 E4 X7 x- X( V* q
  84.         if(count > 250){5 `  `9 [; N' {( q8 s( j. Z
  85.                 count = 0;
    8 y% K. k7 c1 y. l
  86.                 isReadyToHalt = 1;6 m! s7 T9 K- x% w
  87.         }
    2 B3 z, I, E! h# O; U
  88. }! O* |$ d7 b2 E" O& ~$ I9 X

  89. ) G, K" r4 w. v4 z7 g* a( K# @
  90. static void INT1_Isr() interrupt 2{7 N, U  H" B; d! L& J2 L- ?# K5 V' a
  91.         // 矩形波次数累计归零
    * Z( d0 F9 ?' Y4 t
  92.         count = 0;. t9 c$ [, v+ C2 Q" v
  93.         // 重开定时器0中断5 O! d5 I5 |1 Q
  94.         ET0 = 1;6 S+ n: y) J7 A+ `, H
  95. }
    : j+ X+ V5 y0 ?; |0 t+ `( I" Q

  96. 4 N, @+ R9 |9 ]; C
  97. , X: k, E9 s' L
  98. void main(){$ ]1 f+ _. R' H! H
  99.         // 初始化P3和P5口
    ' M1 Y; C% V( V( @. Y0 c! k
  100.         GPIO_Init();
    5 a& N# L9 f& r8 Y* m7 o& w8 x5 P
  101.         // 初始化定时器02 i% ], L: N3 ~( l& w& M2 l, q
  102.         Timer0_Init();4 K- i, g1 @- X+ h+ M' S! B
  103.         // 初始化中断
    : [( J# ^$ I+ J5 |, I7 R' H
  104.         Interrupt_Init();
    * c4 y! M6 [4 @0 h. K8 a/ g, O+ E6 @
  105.         $ i+ i8 K! {  ?* l' F( u
  106.         while(1){
    ) L6 h) q) p1 _* {* s- i4 z+ ]
  107.                 // 检测电量
    9 B2 n5 {8 G6 d6 U4 t5 {
  108.                 if(PCON & (1 << 5)){; T- p  x1 Y6 ?* p0 o% V* w; r5 R
  109.                         // 如果电量低,低压指示灯亮
    # _1 R4 @, N3 y2 g$ u3 M
  110.                         LED = 0;
    $ E% q4 S% ?3 M3 h+ H( W
  111.                         // 清电量检测硬件标志位
    ( c* p/ i$ h0 i
  112.                         PCON &= ~(1 << 5);! m* c* p4 D% t' ]. K6 j  m
  113.                 }else{3 U! R5 O1 r6 v8 p4 e& h
  114.                         // 电量正常,低压指示灯灭4 ]- t+ r. z$ M; ^
  115.                         LED = 1;) V2 o# @3 T4 X4 N
  116.                 }# u3 x7 B& \* B1 j5 d+ T- l! y

  117.   b$ Z) v) }% c$ q
  118.                 // 检测到停机标志7 R' @6 Q( X% y4 z9 f& T
  119.                 if(isReadyToHalt == 1){$ F/ G4 s, [6 p/ p$ H$ N
  120.                         // 暂时关闭定时器0中断
    " f( G$ r; ^" i- z* s3 P
  121.                         ET0 = 0;2 ~9 ^1 I3 `9 E0 u$ B, u% J) Q4 a
  122.                         // 停机之前先把矩形波输出脚置低电平,以方便INT0和INT1唤醒CPU
    % B0 E8 ?, n1 [
  123.                         OUT = 0;
    1 J, w; a  _1 N- m% I7 Q
  124.                         // 停机之前先把低压指示灯灭掉,以省电6 W2 w1 q* V5 m, ]6 u; k
  125.                         LED = 1;
    1 Y" i$ b( I8 e& |0 U1 N3 t8 i
  126.                         // 进入停机模式
    ) r1 U* l/ O; w: i. O7 H' u! ]! K0 `: N
  127.                         PCON |= 0x02;
    4 D! d3 h3 X  b& @
  128.                         _nop_();
    9 E6 j% z% y9 ^+ c( Z0 O
  129.                         _nop_();; ?* F5 C/ g, ]. i6 s6 a. H
  130.                         _nop_();
    ! |( ]- f% R% E1 [' E. s( n
  131.                         _nop_();3 D8 j( c3 u! G+ i: r
  132.                         // 唤醒,清标志位
    ) Q1 G* g% B6 O4 e
  133.                         isReadyToHalt = 0;" b" w; o$ T( W! W) _+ N$ o4 Z4 W% ?
  134.                         // 重开定时器0中断
    5 z3 M. S/ [3 I/ q& W
  135.                         ET0 = 1;
    ; |1 |$ ~$ M5 ]+ o# |0 }* z
  136.                 }+ T0 j0 U$ e9 T
  137.         }
    3 s' ?% g9 q/ g$ T( e4 R
  138. }
    - J+ T. ^) D6 x- z
复制代码
" v0 u# a. }$ z) z+ J9 g
硬件参数配置:* X2 K8 e0 }: M# P/ E

7 J; }9 \0 f( J. V0 G1 ~' _1 g
7 |( R( d4 g6 U0 H* J7 o接收端:
" ~* X" p9 s2 n" Q1 M% ?1 L" k
  1. #include <INTRINS.H>
    ; G* M! V# r4 r# u% V1 A
  2. #include "STC15W.h"7 T0 i* N3 a; u& |, q

  3. ' u) l8 [6 l- P9 A

  4. 2 Q( H6 o3 Y" d9 U0 _$ ^
  5. /*
    7 |$ m5 r3 i0 z6 s, n' X+ X

  6. & A, `) p% A4 v; h! `/ d3 ]+ S
  7. *---------------------------*9 E. w9 T# R) r7 I- y2 J, P( p
  8. |1 (GPIO2)         \__/  (GPIO1)16|
    ) p4 g3 I+ y$ t; L) }
  9. |                                                        |
    $ G7 s" N! ]7 }
  10. |2 (GPIO3)                   (GPIO0)15|& Z, q% h, o! \; X  ?; e. Z3 G" ^
  11. |                                                        |3 `7 X7 L% V& d9 H
  12. |3 (GPIO4)                                  14|
      I. b3 @8 O7 o
  13. |                                                        |& T1 h6 D: s) Z9 k6 [
  14. |4 (GPIO5)                        (DATA)13|+ B  z/ K( F- F& P9 `
  15. |                  STC15W204S                |
    5 r7 G1 f4 @; ?0 B
  16. |5 (GPIO6)                   (LATCH)12|
    ) v/ k! w% i/ W* x% I" G
  17. |                                                        |
      `3 V2 W& f+ n" S2 J  `: T% r
  18. |6 (VCC)                         (CLK)11|8 W- N7 J0 c4 {0 ^- A# G
  19. |                                                          |9 [" H+ O( s% Z3 Y
  20. |7 (GPIO7)                         (TXD)10|
    & _  `" f! b8 T
  21. |                                                        |& v9 s5 x/ a) Q. u9 a
  22. |8 (GND)                         (RXD) 9|+ A) G/ {5 s" C) A7 l& c/ n; I
  23. *---------------------------*0 M! B6 T/ g! }$ Z0 n. [/ N
  24. Fosc = 12MHz/ r' R5 d6 f, d( F
  25. 3 e! J% g: g2 x5 }' ], H
  26. P1.0 -> 上
    6 Z8 h$ \3 W7 A0 e2 _9 e$ L* r% Y
  27. P1.1 -> 左; \& k- q0 H9 Z: T
  28. P1.2 -> 下( X4 v% c5 }9 {1 y) N% d% z
  29. P1.3 -> 右
    5 J1 v# g; I, q, h  l, S
  30. P1.4 -> SEL+ z9 H. h9 M- Z9 B4 W3 c
  31. P1.5 -> STA& U6 ?' k. _2 p- S, y+ B
  32. P5.4 -> B! t$ V$ a! P( [  \' w& `
  33. P5.5 -> A
    / l3 ?( R" o  M$ u# F, A# P
  34. 8 l7 i( V/ k  X$ I, v  |% B
  35. */: w$ B% L* i. q/ {: Y  H7 K1 t
  36. 1 ?- P9 C5 S: z" e' L1 q
  37. / T8 M& O) U7 n/ e: M
  38. sbit CLK        = P3^2;1 p6 |( ?3 |0 X6 l- M
  39. sbit LATCH        = P3^3;
    - w$ K/ v2 i3 O+ C1 L  J
  40. sbit DATA        = P3^6;+ O- }% u3 _* m/ [

  41. . a: Y  I$ E( ], r4 n
  42. bit isReady = 0;
    # C# Y5 C" Z/ [7 ^2 M
  43. static unsigned char key = 0;
    5 }  b# A( D- O3 a
  44. static unsigned char buf = 0;        // 双缓冲。这个缓冲区保存从P1和P5组合而来的键值
    6 X( o% ^( N& g' K. t8 s
  45. static unsigned char bufReady = 0;        // 双缓冲。这个缓冲区保存上面那个缓冲区的备份
    & r) t, N. J: P: E
  46. static const unsigned char data mask[] = {0x80, 0x40, 0x10, 0x20, 0x01, 0x04, 0x02, 0x08};        // A B SELECT START UP DOWN LEFT RIGHT。为提升速度,这个表放到RAM中
    " D! p. [/ K% o& b6 p0 t6 }. y0 i! Y
  47. static unsigned char idx = 0;) [8 B7 h1 L* X" K- R% I
  48. 2 v# ~( t7 B* h% {1 n
  49. . I4 _9 |* _9 ?/ |% r
  50. static void GPIO_Init(){
    8 X; r4 k# ]4 ~3 B
  51.         // P1口和P5口用于接收并行信号,全部初始化为准双向,依靠内部弱上拉输出高电平
    3 U( T3 i  v% y! ^
  52.         P1M0 = 0;
    . b0 Q# ?% X' G
  53.         P1M1 = 0;# k  e2 h' Q$ p8 a( b" m5 Y
  54.         P1= 0xFF;4 G4 i0 y; o9 U2 x
  55.         P5M0 = 0;8 O' M5 \6 x& K/ e
  56.         P5M1 = 0;
    - B$ ^$ o9 ^/ c( L' D+ _6 L0 c6 W
  57.         P5= 0xFF;$ }+ b- P) U( g7 ?2 {2 x
  58.         // P3口初始化为准双向
    : H: N# l( t6 f0 A
  59.         P3M0 = 0;
    9 L* \+ v1 G1 c; g# ]
  60.         P3M1 = 0;
    % k4 Q1 E0 w. s( u7 p
  61.         P3 = 0xFF;4 O8 j- g" A7 o% Z
  62. }
    8 H1 V/ O8 o0 x3 r: Z# G

  63. . h2 J6 \& s% F& B
  64. static void Interrupt_Init(){) h7 s7 E: p/ l/ X; X
  65.         // INT0中断(CLK)触发类型为上升沿+下降沿. s4 C) G1 ~+ x* w8 p( Q
  66.         IT0 = 0;9 y! J: g+ j  b, ^* m8 h
  67.         // 允许INT0中断
    # z% ?4 A! N  ~6 y. Z& c" L9 E
  68.         EX0 = 1;
    ) p& s: i1 T5 d, G, i% Z
  69.         // INT1中断(LATCH)触发类型为上升沿+下降沿$ Y  E) E' c8 i6 P; t
  70.         IT1 = 0;
    / p! U9 C1 y. `4 u2 G% q' _
  71.         // 允许INT1中断
    + K0 s. t# n6 t( A
  72.         EX1 = 1;
    + F, J/ ]3 _+ K) [0 m9 X
  73.         // 开启全局中断: v4 t3 e9 x/ ^" {, J- a
  74.         EA = 1;- ?$ R  Z$ l7 }! t" c/ w4 B
  75. }
    ; e  F# x2 S4 _! K' ]8 t
  76. 6 h' \- X( P) r, I
  77. static void INT0_Isr() interrupt 0{7 _: l2 `& x- \
  78.         // 只有已经成功锁存才允许CLK移位+ O# F! ]# p( K
  79.         if(isReady == 0)
    5 K- r- v2 r6 E, u  ]! m- ^' {! u
  80.                 return;
    1 Y, f6 K' P  q  [4 H) {2 E
  81.         // 读当前引脚电平,如果是低电平则说明是下降沿,此时直接忽略该中断
    0 p) n- D- N$ {8 q; t! ?  Z
  82.         if(CLK == 0)# \, B9 i/ d9 p- {8 ?8 s. W
  83.                 return;
    ! e# q" [% w, z# I/ M  u' d
  84.         // CLK上升沿到来的时候,取锁存值的下一位输出' u/ I9 `: ?/ c0 ]
  85.         idx++;% j$ B$ E! i7 X; n) I# i* h: V
  86.         DATA = key & mask[idx];
    ' m/ j, h% a) k% Y9 e7 p
  87.         // 如果已经完成7次移位,则一轮读取完成8 j5 ?; D" r& e# b  @7 X1 h+ G$ D" ^' [
  88.         if(idx >= 7)
    % D; g' K! R& o5 S$ N; a
  89.                 isReady = 0;' I7 S% ^# w% r$ }, U0 m
  90. }8 a. B9 D0 r% _
  91. ; b, Q5 u1 t0 }1 [1 {0 j
  92. static void INT1_Isr() interrupt 2{
      Q, b9 f/ ~) E1 ]5 v- H" y5 m  J4 `
  93.         // 读当前引脚电平,如果是低电平则说明是下降沿,此时直接忽略该中断4 m, ~0 Y4 b' N5 q  F* S0 j
  94.         if(LATCH == 0)0 h/ m$ M: q& B( M+ O5 F
  95.                 return;
      I4 t- J* Y; c$ F. `% ?, _
  96.         // 当LATCH上升沿到来的时候,锁存所有按键状态,同时把键值A输出到DATA
    / o5 _; v5 G1 x( l* H- N
  97.         key = bufReady;
    9 N5 c2 |. o3 g0 v8 ^! r3 c
  98.         DATA = key & 0x80;//mask[0];        // 为了加速运算,直接取表中的值而不是读表% q; c, Q& g5 _$ N7 \7 x
  99.         idx = 0;
    + y4 Q; ?1 t8 i
  100.         // 允许CLK进行移位
    " U. a% s' {) r' I# d* \
  101.         isReady = 1;) D! L3 f$ p* j8 z# |
  102. }
    $ _( s* e. D' _; E* ~8 W; j$ w
  103. 8 \: H# E" h; D& D
  104. void main(){
    4 r3 M$ ~( r/ d( Q1 B9 f/ a& @& L
  105.         GPIO_Init();4 p" w4 V1 B$ m8 L* o' j
  106.         Interrupt_Init();* T* ~, r( q  W3 u7 _
  107.         % c2 L3 L, P; f. V
  108.         while(1){
    8 t/ O  I$ L' ?+ N
  109.                 //PCON |= 0x01;        // 进入省电模式
    % i7 Q% f% b0 T5 l+ g
  110.                 //_nop_();$ [& e$ j0 o" r
  111.                 //_nop_();
    0 K5 D  p( N3 o0 N
  112.                 //_nop_();; ?) p) b+ P: N; h" r
  113.                 //_nop_();6 Y# h4 C7 g4 m! ^# U* r" g& `' d/ n
  114.                 buf = ~((P1 & 0x3F) | ((P5 << 2) & 0xC0));
    ! U8 p, d; \) ^  o4 S6 }
  115.                 bufReady = buf;
    - _+ [: k: W4 Z/ M! n; ^
  116.         }1 i5 K4 @' N" ]5 e! x5 u5 D" P" Q
  117. }3 |$ r* G9 b3 n! e6 g0 I! B: _
复制代码

7 ]$ y- `; e$ c+ h+ P, [硬件参数配置无特殊要求,晶振频率选择12M即可。# i+ {( Q  {& a  q4 `6 J, \/ y
9 ^+ ^) ^: U( r/ L8 D3 K; T, k
这是编译好的固件。

本帖子中包含更多资源

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

×

评分

参与人数 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
5 O, D+ D: X2 k3 _, L2 R不错的设计,想问一下楼主,FC的15针公头怎么解决?普通的公头太短了,插不进去FC的扩展接口。 ...
2 F0 y0 l% o( x+ z( j! `1 r9 q8 Y
坛友的改造方案
回复

使用道具 举报

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

使用道具 举报

发表于 2019-5-25 12:07:18 | 显示全部楼层
精彩,楼主动手强,也写得很详细。
( i5 y# D! L" ?$ ]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
1 D. g6 _8 }* K) E& @0 c* h精彩,楼主动手强,也写得很详细。
: F# X. `# {" y; `9 N+ W- A: r, ~2.4G方案是目前无线的最低延迟吗?

6 W& k' ]$ ^+ ?我没用过其他无线手柄,所以实在不知道我自己做的这个手柄到底是不是最低延迟。& F- _% O- K8 b3 f; R
不过根据网上的说法,延迟高低主要是由通信协议的复杂程度,以及数据传输速率决定的。这个模块虽然是2.4G无线模块,但由于协议很简单,所以延迟比较低。
6 ^) @( O4 w+ o( t$ N" |( d我用这个手柄玩一些ACT游戏,比如超级马里奥、忍者龙剑传、热血系列,完全感觉不到延迟,和游戏机自带的手柄没有任何区别。唯一的区别就是这个手柄是用火花山寨手柄改造的,外壳是垃圾回收塑料,粗糙+脆弱,导电橡胶弹性不佳,手感不是一般的差。& {8 E$ U! @/ {/ K! U
我手里还有十几张板子,等我有空了我再做一套,到时候买一个好一点的手柄改造。
回复

使用道具 举报

 楼主| 发表于 2019-5-29 16:56:14 | 显示全部楼层
ppad 发表于 2019-5-28 17:27" }$ V! F! C$ M
给技术帝赞一个,有半成品发布吗,自己焊接改造就可以,编程实在不会啊 ...

0 ]0 r2 b) L- @( {1 h很可惜,我手里没有多余的单片机了,LDO也找不到了,锂电池以及充电模块更是没有了。反正就是该用到的元件基本都没了,所以没法发布半成品。6 h/ `* x% b% g2 K& `0 Y; h4 K
两个板子倒是有十几张剩余。
6 n) C+ r6 N) H  x1 e3 u4 A你要是有USB转TTL串口板,完全可以自己买这两种单片机,然后我给你编译好的固件,你自己用串口板下载到单片机里面就行了。两个2.4G无线模块也得通过串口板用AT命令设置参数,不过好在我在设计电路的时候就已经预留好了串口,可以直接在线下载和在线设置参数。总的来说并不麻烦。
回复

使用道具 举报

 楼主| 发表于 2019-5-29 17:00:34 | 显示全部楼层
孙大师 发表于 2019-5-28 18:55
3 D1 P( X* T7 Y9 f) h0 S非常好,楼主是技术帝,到目前我都还没开发fc的无线套件,等空了,开发一套套件,等玩家自己组装。 ...
* D  p3 r( Z) N1 _9 p6 l* P) @( A
能得到孙大师的赞誉,不胜荣幸!! g, |9 \' _% K
不如开发一个多功能手柄,比如用SFC手柄改造,L/R键配合其他组合键可以用来切换2P~4P、调节连发速度、软重启等各种功能。接收端插到15PIN扩展口。
回复

使用道具 举报

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

本版积分规则

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

GMT+8, 2026-3-27 15:25 , Processed in 1.254451 second(s), 14 queries .

Powered by Discuz! X3.5

© 2001-2025 Discuz! Team.

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