找回密码
 注册

QQ登录

只需一步,快速开始

查看: 25487|回复: 32

自制FC无线手柄

  [复制链接]
发表于 2019-5-22 14:16:45 | 显示全部楼层 |阅读模式
本帖最后由 雷精灵2046 于 2019-6-14 09:28 编辑
, x" Q" `4 b) o4 q0 n+ O& O% g8 W) X3 b* C! Y) _: [( \! h
没有用复杂的分立元件搭建发射接收电路,直接用的现成的2.4G无线模块jdy-40。: d" F2 l1 s) [9 G- R2 ~) h% |
; y9 A( {0 [: j  l7 l2 K5 E  `

9 \- ]4 L& u) c1 n! Z9 g发射端靠3.7V锂电池供电,用了一片SOP8封装的STC单片机,负责产生连发脉冲,同时负责检测电池电量,电压低于3V左右的时候触发低压中断,低压指示LED就会亮起来告知该充电了。平时发射模块和单片机均处于睡眠状态,有按键按下才会唤醒,从而实现省电。实测睡眠状态下整机电流约1~2uA。板子洗了一下稍微干净了一点。因为对于微功耗设备来说,焊接残余的助焊剂可能会增加漏电流。& i( C6 Y$ A! o4 }) N, X  ]" w

1 K$ b+ K$ W( W, c4 r买了一个火花的FC山寨手柄,去掉里面的牛屎板子,并修正一下塑料挡板,把锂电池和充电模块装进去。
/ O% P  [' t$ A) m7 \为了减少体积,充电模块裁剪得十分小,并且更换了充电电阻使之适应这个小小的锂电池。这么小容量的电池,也不需要多么大的充电电流是吧?+ |/ u9 _! V! R9 {" F$ F5 L
然后统统用热熔胶粘上。充电电流比较小,所以发热很少,不会熔化热熔胶。
4 u3 |' Y! v, a# C7 _3 E) n4 u3 V' g
* V9 ~: d+ |+ m2 d5 k; K

: O( {1 F+ c$ @- O最后把按键、导电橡胶和电路板装上去。1 x4 E8 Y) G1 R! g
精心裁剪了电路板,正好扣上,不会阻碍其他元件,也不会影响后盖和拧螺丝。
' _( y, T) ^4 N5 f8 ?
, o8 d: R7 G& B, Y: C# m3 v
5 k1 U. N: \$ \- a& f, n. q完工!6 F; q. R: E" q% ]; D% C: u5 u

- a' u: Z* H3 S7 e! n5 K) @) t2 o7 [0 l' L+ Q* i1 h
这是充电的MicroUSB插座。旁边的小孔用于透出低压报警LED的光线。
# _% f( {6 u6 v5 x1 v* H5 ?/ R/ e5 E1 f1 B& Z7 E& m/ l' L+ c  M
9 s! P$ W" B) S7 I: f5 {0 B) k
接收端用一片DIP16封装的STC单片机模拟CD4021。为啥要用单片机模拟而不是直接用CD4021?因为jdy-40模块接收端在有按键按下的时候输出高电平,无按键按下输出低电平,和普通手柄正好相反。当然我也可以用两片74HC00或者74HC04之类的逻辑门进行反相,但那就增加了芯片的数量。对于FC手柄这种工作频率并不高的设备来说,STC单片机完全可以胜任模拟工作。
! h0 t. w+ K# V# u- ?
' l% }# T- u; M2 Q" r1 ~* b5 E$ V( A/ |0 T  `6 O

  E/ d: G% g" B3 @3 }& ~, ^电路设计有点小小的错误,所以有几根飞线。原本设计使用低压差LDO是XC6206,结果在做这个接收模块的时候,买的LDO居然找不到了!无奈只好用了AMS1117。幸好对于接收模块来说是5V降到3.3V,1117可以胜任。要是发射端手柄的话,3.7V降到3.3V,那就非得用6206不可了。
6 m* ~+ H3 W* d9 ^+ p3 _9 P7 l
7 E4 s. Q. \7 P, u/ D3 ~5 [实测十分灵敏,延迟极小几乎感觉不出来。可惜这山寨手柄的手感并不佳,尤其是方向键,软塌塌的。看来我得买个剪线手柄改装。' \) l  g, ^9 l

4 s; F. ~4 Q; `, W5 X7 U6 `3 {这是电路图,有兴趣的朋友可以参考。" @# F( C# z1 T+ r& \9 E
0 y5 V5 X* W5 _. J3 y* Q
4 P2 q5 T/ j- t
我信奉开源主义,十分痛恨把技术藏着掖着。好东西大家分享嘛!所以两个单片机的源代码大公开!
, r! K1 ]* X8 Z& i- V/ b1 \编译器:Keil 51。" g' X7 k- E) ?- [7 K( \( e

/ G3 }! }5 m* h; I/ N% R( R1 Q发射端:9 Z* L! b: z1 U
  1. #include <INTRINS.H>) R7 U6 j7 `& e) B( N# K+ {, n
  2. #include "STC15W.h"
    + f+ J/ f" {! n2 S0 x! W/ u7 I
  3. * h; g' J, E2 M7 D
  4. 4 w4 t( J4 z8 i' ^8 T
  5. /*
    0 I7 l/ q. {# u/ X; y' @3 O
  6. --------------------------+ O8 x- e5 a8 v1 a+ k: ]
  7. |1 (OUT)        \__/   (INT1) 8|0 x% D# Y+ a( ^4 }4 y" @  ?
  8. |                                                   |
    - _) k8 e, M4 B% L$ Z
  9. |2 (VCC)                   (INT0) 7|
    0 D' {- Z: ~6 |4 H- A4 M7 v
  10. |                 STC15W204S                   |2 N! W9 b$ F1 F7 a0 ]# O
  11. |3 (LED)                         (TXD) 6|
    " e$ Z) l$ R  P  }
  12. |                                                   |) {1 p" ?! b# j$ [7 t! l
  13. |4 (GND)                         (RXD) 5|8 m$ b" y+ @; J5 G) y, ?+ v
  14. --------------------------
    9 _$ F* U; O; D# \. i7 x- Q5 X( l# p
  15. . W$ i' l" y3 C
  16. LED ---|<|---[===]--- VCC2 \" O- l% ]" ^9 d8 s
  17.            Red          330
    ; W( H6 A) [; V' ^) S9 z6 v; ]
  18. 3 J* b3 g+ V: O1 b2 {" ]# T: m) [0 q
  19. Fosc = 6MHz
    : k# P3 [  J& t( y- a9 v% }% j, w2 G
  20. */
    + u! N- s1 n/ u% |* u! g

  21. . T/ z; k% I3 w' `& a# u

  22. 0 ^( I8 C4 [/ C3 q, X8 i
  23. // 矩形波输出脚
    ! J- f9 ]$ r  X' M1 p
  24. sbit OUT = P5^4;
    . q) f7 X7 X' X1 k4 l6 @3 v8 h
  25. // 低压指示灯引脚
    ; x! k# u: j2 [% U( I0 r" k
  26. sbit LED = P5^5;
    2 v. A  P: D. |& r$ \0 k  \/ Z' U' c" Z

  27. 7 l) H  J9 k$ V2 f
  28. // 停机标志位% G/ S* K+ r9 ]: J; F3 }$ V
  29. bit isReadyToHalt = 0;. Z8 A2 _$ R/ |3 l7 n& G- J6 |) k, A

  30. 0 \& I- f4 O" @7 ?/ O
  31. // 矩形波次数累计$ T& s/ R  v: Z7 x, w, M' ~
  32. static volatile unsigned char count = 0;7 P1 a" O" W6 d! Q4 G; C) ?
  33. 4 n% A! |2 M6 y! q: ~, k) C: V; Q4 [1 }
  34. 8 h7 F. g0 u+ F; a5 Z
  35. static void GPIO_Init(){
    5 q9 @$ E( a2 L4 a! q9 G
  36.         // P3口设置为准双向,默认靠内部弱上拉输出高电平. l) }6 \4 d0 S) }; E& E- b
  37.         P3M0 = 0;) y5 h2 s1 D; A: O8 }
  38.         P3M1 = 0;
    ) Y5 t4 M; z' \' S$ @) o1 U! c  \! i
  39.         P3 = 0xFF;
    6 s+ g8 t# F4 @2 H% t9 Q
  40.         // P5口设置为准双向,默认靠内部弱上拉输出高电平. Z$ l- f% Z$ U3 n  a
  41.         P5M0 = 0;
    ( Q1 Q/ I  h! l6 a5 M- D
  42.         P5M1 = 0;
    ) p( y# A* b  q- R% L$ w
  43.         P5 = 0xFF;
    2 k# J1 [8 }9 O0 u: i% m2 o
  44. }+ T: x; @- c+ N; ~

  45. ' X+ j  v9 _5 u4 G7 w$ u( D
  46. static void Timer0_Init(){. ~. e$ A$ ?9 X2 h
  47.         // 16毫秒@6.000MHz
    % C' J7 r3 ~6 h; n+ [, S5 x& f
  48.         AUXR &= 0x7F;        // 定时器时钟12T模式
    / L# {8 g5 U+ @8 {
  49.         TMOD &= 0xF0;        // 设置定时器模式6 z# o3 B. z. h
  50.         TL0 = 0xC0;                // 设置定时初值
    4 s- t3 U( H3 N* [
  51.         TH0 = 0xE0;                // 设置定时初值
    7 P6 r+ O& w$ L, `) r. N3 y* \
  52.         TF0 = 0;                // 清除TF0标志
    " A2 Z( H3 h8 i$ R: `7 C
  53.         TR0 = 1;                // 定时器0开始计时" g) l! X0 {0 P. R! m
  54. }
    2 g$ B; k$ H5 K1 U) O
  55. + h2 L9 q* d* M# @
  56. static void Interrupt_Init(){
    ! Q% T, J5 E: q  G" n0 U
  57.         // INT0中断触发类型为下降沿触发
    3 d" m9 o. F& O7 l: @, m/ F; z6 U/ w
  58.         IT0 = 1;
    4 a$ w1 H* R' d
  59.         // 允许INT0中断
    " y+ Q, t& T) w- o* f% P. I' Z/ \( m
  60.         EX0 = 1;
    4 N  r3 Z4 A: u+ I
  61.         // INT1中断触发类型为下降沿触发" h$ T! `# `: A8 Y: ]
  62.         IT1 = 1;7 j5 y- |+ I/ s7 A
  63.         // 允许INT1中断
    7 l3 ~) |' [9 k/ y6 w8 W1 u
  64.         EX1 = 1;  X" U: f5 l0 f* C# ~
  65.         // 允许定时器0中断
    ' k- ?, E) p% o$ p5 q, p- e" H8 U2 v! B
  66.         ET0 = 1;# V+ ^" s- \9 ?  W" R9 i
  67.         // 允许全局中断, X/ E# O4 P% t# {' m
  68.         EA = 1;/ N% O1 Y% y9 e- F  S4 ]  V2 U
  69. }
    6 X0 c# I% L6 f) |* t1 v- _
  70. % c+ o, z! d3 |$ g# \, ^9 @, U
  71. static void INT0_Isr() interrupt 0{
    ) ^& g  k$ p9 `1 G6 ^3 a, \. H% A
  72.         // 矩形波次数累计归零
    % s6 e4 s- H& N3 w6 C& T0 g- |* ^
  73.         count = 0;
      p. j% i0 j( \$ `
  74.         // 重开定时器0中断6 R! G  o& x& {5 g3 a' R
  75.         ET0 = 1;$ e1 ]. W3 ^2 {$ A; k! a5 q
  76. }
      a4 @$ O. W/ j9 N/ E
  77. + Y; }$ w' A" ?
  78. static void Timer0_Isr() interrupt 1{  i: O: O& {# X" b
  79.         // 输出矩形波
    7 T0 w6 X4 y# ^5 P) U8 W2 o
  80.         OUT = ~OUT;& B, o+ J; O# {; ]6 ?/ Z, y9 @
  81.         // 累计矩形波次数
    ' }. V5 ~# A/ ]! n- M! x+ }  [
  82.         count++;
    # R: w* r. s: Y) U0 M
  83.         // 超过250个矩形波,准备停机
    " l5 N+ g7 w0 J5 e( l! W3 L
  84.         if(count > 250){
    & q0 }* m. u+ ^: T: e
  85.                 count = 0;
    2 ?& M3 Y: {* H) E! `) E' h
  86.                 isReadyToHalt = 1;, v% F; F* _1 E4 L  ?1 D0 t7 v5 d* t
  87.         }
    5 ?: \/ Q8 y1 O& L) D4 }6 |1 r
  88. }
    0 E) \6 Z& p  ?2 Z( Q, l3 R
  89. - K* B6 L' w1 N: A7 G
  90. static void INT1_Isr() interrupt 2{  n0 {: q8 i  K# y+ @  l
  91.         // 矩形波次数累计归零9 l) v& w6 S+ L! c2 I
  92.         count = 0;% j) {" o' u2 U
  93.         // 重开定时器0中断/ D0 e5 |0 |2 q! `
  94.         ET0 = 1;! |0 P. @' D6 d$ U3 A; k8 ]! L% w, H6 Y
  95. }
    9 v1 g7 n; F8 A1 T7 d" w& g6 L

  96. 1 [' m# z$ i" l5 \9 Z8 V" y

  97. - j7 b, J3 _9 t- O+ p' z
  98. void main(){- c: _0 i# j3 x! \8 d% J$ d1 ~7 P
  99.         // 初始化P3和P5口
    # Z7 L( w5 O: w7 q1 P
  100.         GPIO_Init();
    ! M/ U; L% q3 k8 r) O+ F" a! O
  101.         // 初始化定时器0
    ; Z5 K2 e" L# ~0 w5 k: W
  102.         Timer0_Init();
    # x* }8 C( W, X9 R; V1 V
  103.         // 初始化中断
    ) [. @4 d9 c9 q+ v, i6 a9 G
  104.         Interrupt_Init();
    9 \- _) v4 _7 h5 l3 C
  105.         4 \4 N! G4 t; g8 X7 f
  106.         while(1){
    0 h$ G, T' b* M' e; v
  107.                 // 检测电量0 c& @$ h0 p7 N9 z' m' N9 \
  108.                 if(PCON & (1 << 5)){) r8 s. |9 d! D7 i
  109.                         // 如果电量低,低压指示灯亮
    7 q1 H% j) B% S/ U* J: e8 D
  110.                         LED = 0;: H  G" d* ?1 g2 c8 ?$ Q  U5 F/ ]
  111.                         // 清电量检测硬件标志位
    ( I+ H5 B/ _+ @+ i8 `
  112.                         PCON &= ~(1 << 5);/ N" b: g3 e: b* ?- w" ?$ |2 m
  113.                 }else{
    9 a" T5 W! u6 B5 C
  114.                         // 电量正常,低压指示灯灭
    1 i3 w; ~; r% G+ k2 d- h( ~. v* D- y
  115.                         LED = 1;
    $ d# Q* S7 q/ Q: T6 _
  116.                 }6 k. L5 e# n% Y8 o
  117. # n! w. r. z' G
  118.                 // 检测到停机标志
    ( @8 j  t$ c, h' J
  119.                 if(isReadyToHalt == 1){# f9 c' ~' e# @) D  y0 p, h
  120.                         // 暂时关闭定时器0中断
    * Z5 D. U7 T0 Q% A9 U; |4 d
  121.                         ET0 = 0;. Z' U* M1 ?0 r: `
  122.                         // 停机之前先把矩形波输出脚置低电平,以方便INT0和INT1唤醒CPU
      T/ C0 x7 r+ N+ u
  123.                         OUT = 0;4 H* G: Y  |- B- r4 t
  124.                         // 停机之前先把低压指示灯灭掉,以省电
    6 B2 B/ S1 }/ g5 i7 t2 _
  125.                         LED = 1;6 L! V( s2 Y3 w$ I  |9 }
  126.                         // 进入停机模式, T. ]9 \% q3 K, E) x0 B
  127.                         PCON |= 0x02;
    4 Z- q5 D  V% o0 X% r  L
  128.                         _nop_();
    : {, h  C5 p$ J0 d7 m8 Z4 f
  129.                         _nop_();: z2 R1 I! i2 b2 _
  130.                         _nop_();# c" q" I, y/ J& D- `  K9 `
  131.                         _nop_();
    9 ~. V7 G" }- r" {# W( M- @5 E3 o
  132.                         // 唤醒,清标志位- \- ?) _' c) f7 U9 M- s2 T4 Q9 @3 T
  133.                         isReadyToHalt = 0;' ~( r" d6 l: ~, P# i; P
  134.                         // 重开定时器0中断
    & d! P* d& x9 [2 l( d! w7 \$ K
  135.                         ET0 = 1;
    ) |" [. |6 a" K" N" e
  136.                 }9 o  _' j5 ]+ o1 ], H
  137.         }. k( _; ~9 d6 m7 R" I; B) J" D2 t
  138. }
    , c/ V! f$ M; Y8 K6 n
复制代码
$ ^1 C& }$ y  v/ E2 \+ \9 R- F% J
硬件参数配置:% u7 M7 m; x# w+ W
# Y) }) Y, c  u. R5 P$ [( A4 ]

9 O4 s# @0 h8 G; ~/ d/ @; z接收端:% `3 y" _/ B' J, g
  1. #include <INTRINS.H>
    - H9 g; s: A, ^8 c
  2. #include "STC15W.h"
    7 c; U+ j7 r" e, i$ Z1 |3 @
  3. 3 X" @" }4 {) w! g4 y! W7 d
  4. , i" z/ s% c/ Y* u: I; Y6 C
  5. /*
    5 d) i& D4 z6 v3 {: P7 @
  6.   g; D4 b1 ?4 d+ g! w( e/ j' Y; `
  7. *---------------------------*: j  L. e- ]/ {- [( W
  8. |1 (GPIO2)         \__/  (GPIO1)16|- Y: ?) w+ y$ |9 H
  9. |                                                        |5 G+ L  [9 R6 l
  10. |2 (GPIO3)                   (GPIO0)15|
    . A$ i# U8 v/ b7 D: P
  11. |                                                        |6 }  t2 M/ U) h7 R- ?1 l& g. e
  12. |3 (GPIO4)                                  14|
      J+ C; X$ G# q2 v& H" f, u- W4 N
  13. |                                                        |0 L) c( X4 e% ~/ a7 l' g
  14. |4 (GPIO5)                        (DATA)13|. u" T# J$ q/ R! p3 t
  15. |                  STC15W204S                |' k0 z! h* {( S" S- n0 [
  16. |5 (GPIO6)                   (LATCH)12|
    " O2 E+ \# S2 o
  17. |                                                        |: V0 x2 V# L' _2 ^4 G# K* U
  18. |6 (VCC)                         (CLK)11|
    9 A! v% c( _1 D8 C
  19. |                                                          |$ W( K9 F2 A' }/ W: G) [
  20. |7 (GPIO7)                         (TXD)10|- D* m& u/ \$ B3 [- o
  21. |                                                        |
    ) d1 B2 C  y/ A3 `
  22. |8 (GND)                         (RXD) 9|
    8 i7 f, `( i' X
  23. *---------------------------** d0 k5 n* {  q: a( Y% t2 C+ \
  24. Fosc = 12MHz4 b4 T8 T8 o1 L; m& X

  25. ) ^% B& Z! R: k
  26. P1.0 -> 上
    $ n7 V6 I& [! h
  27. P1.1 -> 左/ m- H! L% @/ Q$ g
  28. P1.2 -> 下9 x1 \+ a6 ?& I9 F% _: P  C
  29. P1.3 -> 右3 S8 f0 {* H3 b2 d: v+ V* n' k+ B
  30. P1.4 -> SEL& `( i! f! ^* L, R$ ?+ R4 Z: R
  31. P1.5 -> STA
    + N3 I/ L/ G8 }0 z# X/ r
  32. P5.4 -> B. n4 e9 F- d# l& Z" v; M7 M# B
  33. P5.5 -> A
    - M* c: h0 }% \

  34. 5 E1 O! e: c& X' S, ^: B( ^/ `' h2 F, l4 c
  35. */* E" t! V7 {& B  Z
  36. 3 i; g+ @5 e, m" y

  37. + h, K: L/ _: C' A, B+ O" ?) r
  38. sbit CLK        = P3^2;
    ' C: o* G; }% W* @6 W2 N5 ^& s
  39. sbit LATCH        = P3^3;2 I5 |) |9 K6 ]7 I2 G1 O
  40. sbit DATA        = P3^6;
    9 g- Y1 q7 I" ^9 S4 {
  41. 0 e7 R5 b0 d: Y: b
  42. bit isReady = 0;
    4 s5 d6 j- b- p; r+ h/ A4 v( G
  43. static unsigned char key = 0;/ ?+ X0 c. L( h* R' P
  44. static unsigned char buf = 0;        // 双缓冲。这个缓冲区保存从P1和P5组合而来的键值
    . a6 y- c3 u3 u9 S2 z9 i# P& E
  45. static unsigned char bufReady = 0;        // 双缓冲。这个缓冲区保存上面那个缓冲区的备份  s' ]1 o# J3 E; t) F0 m$ r
  46. static const unsigned char data mask[] = {0x80, 0x40, 0x10, 0x20, 0x01, 0x04, 0x02, 0x08};        // A B SELECT START UP DOWN LEFT RIGHT。为提升速度,这个表放到RAM中4 B! D, W# Y) X3 ~) R6 H2 n/ s& ~
  47. static unsigned char idx = 0;
    % K1 T5 K9 X; v/ L% e5 g8 H! i/ G9 N: @
  48. : A3 m7 |6 R4 Y
  49. ( ^+ i; f. z; M! Q! b, B
  50. static void GPIO_Init(){4 s1 ^: E( j- x. a) \+ g! ]
  51.         // P1口和P5口用于接收并行信号,全部初始化为准双向,依靠内部弱上拉输出高电平. U: Z& @+ N; O0 G5 p+ q* Y
  52.         P1M0 = 0;6 e) E4 ]; \3 r2 J$ T: f
  53.         P1M1 = 0;( j  ?/ E5 W! }7 H" T
  54.         P1= 0xFF;
    % ^+ a2 c6 p* g6 ~
  55.         P5M0 = 0;  ]' l9 N4 J0 j# E
  56.         P5M1 = 0;
    0 }8 p( D  n4 @5 s- t; l" a
  57.         P5= 0xFF;
      z$ ^7 }. \. p  n5 ]; @# _1 e8 M( M
  58.         // P3口初始化为准双向
    2 q+ K" A3 g( x% X
  59.         P3M0 = 0;0 Y3 k$ u9 k" f
  60.         P3M1 = 0;$ n( j9 ?" o! D, O
  61.         P3 = 0xFF;7 O9 K; q' d. ~; Q6 s2 F
  62. }% c8 o, k8 a" U" M
  63. : M! P, F4 E9 S, g! M+ J& R! }
  64. static void Interrupt_Init(){- l0 T: r% z8 g. X2 A
  65.         // INT0中断(CLK)触发类型为上升沿+下降沿# @- @7 |; I7 U- \
  66.         IT0 = 0;
    4 Z- v: W1 U0 D1 C8 ?
  67.         // 允许INT0中断
    $ A. A7 O3 d& j2 z4 ^  D
  68.         EX0 = 1;: t) n  Y1 i$ q
  69.         // INT1中断(LATCH)触发类型为上升沿+下降沿
    0 Y5 }6 w$ \# B" S3 V( N
  70.         IT1 = 0;
    5 q& P' i4 Z4 y5 o% f7 Q. A3 W! B( a
  71.         // 允许INT1中断
    4 B4 x' ?6 D# Q9 s5 o
  72.         EX1 = 1;. X1 f, q% r, |0 x) s$ |
  73.         // 开启全局中断
    " D9 }% Z: W0 ?5 t2 Y
  74.         EA = 1;/ @2 U" I* `) S
  75. }$ u6 A( v. g1 q% G

  76. ( @% W9 Y: V& Y4 f
  77. static void INT0_Isr() interrupt 0{
    8 D' P) E' n% b
  78.         // 只有已经成功锁存才允许CLK移位" z9 I8 x2 U2 C  M( P
  79.         if(isReady == 0)6 l' H" ~$ x9 ^* D& A- C/ `
  80.                 return;! c; S( V* Q. H2 x8 C, u
  81.         // 读当前引脚电平,如果是低电平则说明是下降沿,此时直接忽略该中断8 u* h* ]2 _; a+ J+ p
  82.         if(CLK == 0)+ {5 R1 T6 H- n. G$ F
  83.                 return;
    3 z  j: v& p! D+ A
  84.         // CLK上升沿到来的时候,取锁存值的下一位输出9 a3 b' L; @) s
  85.         idx++;
    ) o" I+ B5 y8 q
  86.         DATA = key & mask[idx];
    ) h% {( n  t* g1 N4 j
  87.         // 如果已经完成7次移位,则一轮读取完成+ d$ J) k1 U$ W) P" E6 }- P$ R: P
  88.         if(idx >= 7)) D  t$ G* A/ W7 p* n) D
  89.                 isReady = 0;5 j) `. m7 p: U
  90. }/ M& u& V% `, M/ }

  91. 3 Y# V: H! o3 g* d. v" S& K
  92. static void INT1_Isr() interrupt 2{
    / Y3 ]( O0 s* I3 Q3 C- A
  93.         // 读当前引脚电平,如果是低电平则说明是下降沿,此时直接忽略该中断/ v7 N% a+ p7 @/ P0 \# @. J, @
  94.         if(LATCH == 0)
    / l( N+ i, Q' \! {
  95.                 return;
    ' T1 J5 U; H4 S2 ~% [/ _. H! ]
  96.         // 当LATCH上升沿到来的时候,锁存所有按键状态,同时把键值A输出到DATA
    ; [- s3 \) T, y; B5 {4 @
  97.         key = bufReady;; `5 C) m6 v% y: x4 l5 p" A
  98.         DATA = key & 0x80;//mask[0];        // 为了加速运算,直接取表中的值而不是读表
    6 S) X2 ~4 r0 L! g
  99.         idx = 0;
    3 x. n5 O3 a9 }
  100.         // 允许CLK进行移位* F  K3 D4 Y2 c8 j( ^" Q% I8 v1 d
  101.         isReady = 1;
    & c" |+ b' x5 v1 n$ H
  102. }
    , L2 p' y; w2 ^. x5 q# \1 w
  103. 1 I% R6 Q0 H; d/ B
  104. void main(){7 I0 u* U% f9 N; N: k
  105.         GPIO_Init();
    : M" Q* F( J) k& ]0 c; C2 S
  106.         Interrupt_Init();% x) V* f% Z- X/ E  H
  107.        
    ( Y5 j6 l, W/ @. u! l. |
  108.         while(1){
    ; K  Q9 R1 W2 h. a
  109.                 //PCON |= 0x01;        // 进入省电模式
    $ {4 C' N9 l2 }- d9 ^
  110.                 //_nop_();, h0 _* f" z7 N: _: N2 X
  111.                 //_nop_();4 ^( K% J+ ^) X/ D! v& Z. ?
  112.                 //_nop_();! s  J' |8 b. C6 Z; q
  113.                 //_nop_();
    % Z6 {$ Z4 |% i9 P# ~+ v
  114.                 buf = ~((P1 & 0x3F) | ((P5 << 2) & 0xC0));
    3 ~8 m8 v$ @9 U- ^
  115.                 bufReady = buf;# f) R$ Y7 }  ^/ Q3 c/ Q0 Y7 i
  116.         }
    6 I. l# M5 s! b3 w$ ?9 G1 u4 ?9 J
  117. }
    . ~! |9 B! O0 t6 ]8 u, y
复制代码
' d6 K  F/ U" B2 N, ]" t; G
硬件参数配置无特殊要求,晶振频率选择12M即可。8 v6 _+ d, R7 {! I$ t3 d" H0 f
2 H) O, g6 l- \& o
这是编译好的固件。

本帖子中包含更多资源

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

×

评分

参与人数 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:053 ?5 o8 z7 N4 q
不错的设计,想问一下楼主,FC的15针公头怎么解决?普通的公头太短了,插不进去FC的扩展接口。 ...
" y$ ~: T( R3 r9 a9 Q6 ]
坛友的改造方案
回复

使用道具 举报

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

使用道具 举报

发表于 2019-5-25 12:07:18 | 显示全部楼层
精彩,楼主动手强,也写得很详细。; r0 y: I6 y9 ~+ D: l' z: k
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
/ ?& z" B* a0 z1 \0 Q8 [# S精彩,楼主动手强,也写得很详细。7 L7 h8 Y/ b0 u
2.4G方案是目前无线的最低延迟吗?

) ]7 \6 |$ Y% L# _( j我没用过其他无线手柄,所以实在不知道我自己做的这个手柄到底是不是最低延迟。
) u/ l& u4 m8 Q, {& t. {不过根据网上的说法,延迟高低主要是由通信协议的复杂程度,以及数据传输速率决定的。这个模块虽然是2.4G无线模块,但由于协议很简单,所以延迟比较低。6 D+ x9 r$ E6 @) d
我用这个手柄玩一些ACT游戏,比如超级马里奥、忍者龙剑传、热血系列,完全感觉不到延迟,和游戏机自带的手柄没有任何区别。唯一的区别就是这个手柄是用火花山寨手柄改造的,外壳是垃圾回收塑料,粗糙+脆弱,导电橡胶弹性不佳,手感不是一般的差。+ V  O* y& @+ u4 S
我手里还有十几张板子,等我有空了我再做一套,到时候买一个好一点的手柄改造。
回复

使用道具 举报

 楼主| 发表于 2019-5-29 16:56:14 | 显示全部楼层
ppad 发表于 2019-5-28 17:278 Z: I! n0 C5 b3 U
给技术帝赞一个,有半成品发布吗,自己焊接改造就可以,编程实在不会啊 ...

8 y6 ]9 d  H4 s. o很可惜,我手里没有多余的单片机了,LDO也找不到了,锂电池以及充电模块更是没有了。反正就是该用到的元件基本都没了,所以没法发布半成品。
. i: Z6 a) e3 i. U7 r) a; O4 o! d0 R- e两个板子倒是有十几张剩余。
6 Z. q% V( \, j& k4 H1 j你要是有USB转TTL串口板,完全可以自己买这两种单片机,然后我给你编译好的固件,你自己用串口板下载到单片机里面就行了。两个2.4G无线模块也得通过串口板用AT命令设置参数,不过好在我在设计电路的时候就已经预留好了串口,可以直接在线下载和在线设置参数。总的来说并不麻烦。
回复

使用道具 举报

 楼主| 发表于 2019-5-29 17:00:34 | 显示全部楼层
孙大师 发表于 2019-5-28 18:55
! f: s. Z$ i. k# p7 m4 E2 ?非常好,楼主是技术帝,到目前我都还没开发fc的无线套件,等空了,开发一套套件,等玩家自己组装。 ...
% E4 _9 A$ e% U: [7 X
能得到孙大师的赞誉,不胜荣幸!$ o  i9 Z" A' m
不如开发一个多功能手柄,比如用SFC手柄改造,L/R键配合其他组合键可以用来切换2P~4P、调节连发速度、软重启等各种功能。接收端插到15PIN扩展口。
回复

使用道具 举报

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

本版积分规则

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

GMT+8, 2026-6-21 09:42 , Processed in 0.108956 second(s), 15 queries .

Powered by Discuz! X3.5

© 2001-2025 Discuz! Team.

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