电玩DIY [ VG DIY ] - Video Game Do It Yourself

 找回密码
 注册

QQ登录

只需一步,快速开始

查看: 14724|回复: 27

自制FC无线手柄

  [复制链接]
发表于 2019-5-22 14:16:45 | 显示全部楼层 |阅读模式
本帖最后由 雷精灵2046 于 2019-6-14 09:28 编辑
$ W8 K3 r, X3 c% `0 h1 \* n/ I3 p4 E
没有用复杂的分立元件搭建发射接收电路,直接用的现成的2.4G无线模块jdy-40。
  w' x5 f$ N1 G( ?" j
8 ~6 l) v+ S& X
9 t0 T# [$ ~' Z. r发射端靠3.7V锂电池供电,用了一片SOP8封装的STC单片机,负责产生连发脉冲,同时负责检测电池电量,电压低于3V左右的时候触发低压中断,低压指示LED就会亮起来告知该充电了。平时发射模块和单片机均处于睡眠状态,有按键按下才会唤醒,从而实现省电。实测睡眠状态下整机电流约1~2uA。板子洗了一下稍微干净了一点。因为对于微功耗设备来说,焊接残余的助焊剂可能会增加漏电流。+ `" v* B9 F( X

6 d- P" U5 n, W: U买了一个火花的FC山寨手柄,去掉里面的牛屎板子,并修正一下塑料挡板,把锂电池和充电模块装进去。
+ x% t. c. y* L& ^$ q7 E5 K# C  s4 Q为了减少体积,充电模块裁剪得十分小,并且更换了充电电阻使之适应这个小小的锂电池。这么小容量的电池,也不需要多么大的充电电流是吧?
& b0 V3 C; D3 T" B& s3 O然后统统用热熔胶粘上。充电电流比较小,所以发热很少,不会熔化热熔胶。' Q/ m9 M# P  z7 K

4 u- F% L2 l7 C' Y3 D* K) P8 Z- x) ?7 Z. ~

* ?7 }9 Q( A& G6 Q; q, c最后把按键、导电橡胶和电路板装上去。! s9 G. _+ z- l$ R
精心裁剪了电路板,正好扣上,不会阻碍其他元件,也不会影响后盖和拧螺丝。
, I0 b- V$ |/ R! U, L- b% c1 B; u+ l5 z" j0 B
/ }/ r! W2 J% `) \: n
完工!2 S4 a6 m9 L6 Q
7 t( R: J' ~- \. u. B0 e9 a7 p+ }  N# R

% U- w" ]9 A+ ]9 ^# {/ y这是充电的MicroUSB插座。旁边的小孔用于透出低压报警LED的光线。0 G2 h) v2 R8 }/ S
& w6 ^: G4 P0 H2 H8 m- `
6 U5 x) y" T% j$ P
接收端用一片DIP16封装的STC单片机模拟CD4021。为啥要用单片机模拟而不是直接用CD4021?因为jdy-40模块接收端在有按键按下的时候输出高电平,无按键按下输出低电平,和普通手柄正好相反。当然我也可以用两片74HC00或者74HC04之类的逻辑门进行反相,但那就增加了芯片的数量。对于FC手柄这种工作频率并不高的设备来说,STC单片机完全可以胜任模拟工作。
* [+ n* e# A5 l
. i9 S# ]& Z5 a; w
# p! b: ~8 |; M8 q
7 C" v* a/ P5 H2 R( B8 C电路设计有点小小的错误,所以有几根飞线。原本设计使用低压差LDO是XC6206,结果在做这个接收模块的时候,买的LDO居然找不到了!无奈只好用了AMS1117。幸好对于接收模块来说是5V降到3.3V,1117可以胜任。要是发射端手柄的话,3.7V降到3.3V,那就非得用6206不可了。3 v, \6 Z- l) k# d' e8 c0 [
8 D$ L3 u- \2 h$ x+ l) e
实测十分灵敏,延迟极小几乎感觉不出来。可惜这山寨手柄的手感并不佳,尤其是方向键,软塌塌的。看来我得买个剪线手柄改装。% q/ J1 u; ?; g; D8 m: E
+ h1 S- l  {& c  }3 z2 n
这是电路图,有兴趣的朋友可以参考。
$ z, p) Z# h- b  G3 Y+ b
: D5 P7 W* @0 `7 N. x8 B/ s, W: I% Q4 u' Y; ?. c1 J$ e6 g. @
我信奉开源主义,十分痛恨把技术藏着掖着。好东西大家分享嘛!所以两个单片机的源代码大公开!7 E# q: T3 _7 W- Q: c  v1 v8 p
编译器:Keil 51。7 D9 Y! `! @4 @6 C. f+ F5 d
7 W3 L% |' ~: ]+ F2 O
发射端:
' a/ t. A  A' }/ g+ n+ _, H  t# T
  1. #include <INTRINS.H>
    % ~; ?$ P2 l; Q& [1 f0 H
  2. #include "STC15W.h"/ \; \; c2 s& T7 E6 x! Z# V9 R
  3. # @6 ?8 e$ J& z4 P; S2 _) _
  4. & ~- R$ q. `5 {6 ]1 ?
  5. /*
    / Q6 h) h7 k4 [% X! s
  6. --------------------------; n! B9 C" s! ]9 `+ Z; y
  7. |1 (OUT)        \__/   (INT1) 8|  {2 _1 F( L4 \$ s/ u) l$ t; k6 N
  8. |                                                   |1 A1 z  N% x4 h9 c$ @, @
  9. |2 (VCC)                   (INT0) 7|3 w* X3 {* ?& [  I8 [; d
  10. |                 STC15W204S                   |; u) x! {: b" j2 l- `. B6 s
  11. |3 (LED)                         (TXD) 6|" S4 V4 E- x7 q3 F5 ]4 _6 Z
  12. |                                                   |4 B; t3 |8 [/ y2 m
  13. |4 (GND)                         (RXD) 5|
    ) |" u- x5 @. ]+ B# I5 q3 f
  14. --------------------------
    $ X. m( d5 ?* |& D- f8 K: t
  15. 5 C/ R! J, o: i
  16. LED ---|<|---[===]--- VCC
    ( b( \, [! G, _" V5 n) \5 R
  17.            Red          3306 j. f; f  _* M8 t7 W( z- ~

  18. # G- y* `2 }( y: z
  19. Fosc = 6MHz
    1 W/ ^8 S3 R" e& y. H9 m
  20. */3 \" W& y# |+ e" R

  21. # N& @$ K4 i) v! `0 H# h8 }7 a8 o

  22. 1 |) C8 c9 x9 {7 J/ c# \0 l! A( e5 D
  23. // 矩形波输出脚
    8 P# x) P& q# k, H* m8 E
  24. sbit OUT = P5^4;
    ; y7 R+ M, g/ h
  25. // 低压指示灯引脚# K* n# z7 s' |- N# |# A; U
  26. sbit LED = P5^5;
    & O5 p9 s  k/ c2 @4 c* y0 }

  27. % K! g! p0 h* m6 L
  28. // 停机标志位1 m2 @9 y, G3 o' t# m8 a0 Y
  29. bit isReadyToHalt = 0;
    ) b9 V/ f0 w1 D6 l4 U9 @5 M% a

  30. : c& j( S) ?4 H
  31. // 矩形波次数累计
    - U# S( f& o& j. G  U/ V
  32. static volatile unsigned char count = 0;6 ~' k; m0 z$ P, V! S

  33. 4 G  b  G- n* g- n

  34. 5 k0 C7 z! p% y6 S+ S
  35. static void GPIO_Init(){
    ; l7 W8 E0 t1 c
  36.         // P3口设置为准双向,默认靠内部弱上拉输出高电平8 ~. a- s7 @2 z( U3 Z
  37.         P3M0 = 0;/ L4 i7 P) G( M. C- y9 {
  38.         P3M1 = 0;$ q/ O/ C' U6 T; B( f% T0 V& t
  39.         P3 = 0xFF;
    - u1 W; M* L7 g: {- Y1 T
  40.         // P5口设置为准双向,默认靠内部弱上拉输出高电平
    4 a1 U5 g( S( c! M/ |, `3 l' }( c
  41.         P5M0 = 0;
    2 w! y- N4 d" `
  42.         P5M1 = 0;" Y9 A2 S% V; V' [- |5 j9 Q
  43.         P5 = 0xFF;/ E$ m: [6 i1 a$ T0 z
  44. }
    % b$ G' n' |; q7 ?1 I
  45. " ~' I% |$ `) F0 H( p: u7 Q( L
  46. static void Timer0_Init(){7 R: [( [2 N, i  L# g" p
  47.         // 16毫秒@6.000MHz
    1 C) x5 M* g9 D* p
  48.         AUXR &= 0x7F;        // 定时器时钟12T模式- r8 T/ V9 t2 j8 `3 p0 P
  49.         TMOD &= 0xF0;        // 设置定时器模式6 O+ S* P' Q4 A) [2 r8 o1 j
  50.         TL0 = 0xC0;                // 设置定时初值
    ! ]8 }' x% [" i5 Y
  51.         TH0 = 0xE0;                // 设置定时初值
    ( t" f' K6 F& z2 d" s; A- K8 S' `
  52.         TF0 = 0;                // 清除TF0标志
    ; g$ r/ {: h) N3 `- @2 Y. l$ E
  53.         TR0 = 1;                // 定时器0开始计时
    # R  o* ~' I7 a# V4 O
  54. }
    / u0 u1 @+ {+ B4 ^; g
  55. / u/ l1 [* A9 g9 L9 O
  56. static void Interrupt_Init(){) ^+ W& y2 y6 q' v+ M8 U( G7 N
  57.         // INT0中断触发类型为下降沿触发
    / V2 p( }( z2 G) I( Q. i; H7 I
  58.         IT0 = 1;& ]. z1 H* l7 A4 _. N
  59.         // 允许INT0中断8 A0 D2 h: I6 E$ [) S6 e
  60.         EX0 = 1;
    8 p9 t. W' g# p
  61.         // INT1中断触发类型为下降沿触发1 r2 F2 g# K9 E2 L3 i
  62.         IT1 = 1;
    ' Y0 U" d+ F6 d% y1 G
  63.         // 允许INT1中断
    ( }+ S3 X3 d& b; j9 k" J5 H
  64.         EX1 = 1;6 o2 n% Q  n; V: k8 }1 e( R! T
  65.         // 允许定时器0中断
    % y6 f5 P" N& z) ~- u( d6 h; x
  66.         ET0 = 1;
    0 m4 D6 J5 b" d# B; m9 @
  67.         // 允许全局中断
    / j( n& I/ {6 N! [- m/ X
  68.         EA = 1;
    ) ?9 A6 {1 I# ?$ o2 i
  69. }" ^9 ], e) L5 r* U3 |# l) ~  j
  70. 5 T5 }7 |0 P& B% L
  71. static void INT0_Isr() interrupt 0{
    4 h( U, v" p& d1 b1 v( [
  72.         // 矩形波次数累计归零( ], K% H" ^+ D, R4 d% g
  73.         count = 0;; \0 k# {2 P8 ~5 o3 i
  74.         // 重开定时器0中断! `2 a' C6 A  ~5 V9 v
  75.         ET0 = 1;
    8 ~( M# v0 c$ S. V' C
  76. }1 S, x; L% e! H4 ~. o* h. X

  77. * I3 h/ z3 k; B7 f
  78. static void Timer0_Isr() interrupt 1{
    2 p5 Y: l2 b  u: k8 G# F/ [- L
  79.         // 输出矩形波
    & E/ R) {: k" b! Y
  80.         OUT = ~OUT;4 a5 y. r) w6 Q8 x0 _8 T. N
  81.         // 累计矩形波次数
    3 }& c" M# N- M6 w
  82.         count++;
    ) H( ]4 g8 Y# B# c. Y. c
  83.         // 超过250个矩形波,准备停机
    4 ^& d0 o7 L1 |3 W* T- M
  84.         if(count > 250){0 `. m! W0 A. f" G* i
  85.                 count = 0;! W2 |: C! y3 E- L
  86.                 isReadyToHalt = 1;
    # z0 T3 C0 z$ T7 y! e8 F
  87.         }; U8 r2 H- u) u5 W
  88. }
    / m  g6 _& {. ^& z
  89. & f9 W) T% A+ P/ v
  90. static void INT1_Isr() interrupt 2{
    4 r3 m- F- d' [" `; S3 R5 F; H& _$ K
  91.         // 矩形波次数累计归零
    + M1 r) ~2 p# _+ r" T! G* Z' `7 n
  92.         count = 0;
    $ A$ Y! U3 r* }7 W0 k
  93.         // 重开定时器0中断
    . c2 l% g- B4 i
  94.         ET0 = 1;
    / j, L' G: j. q4 {3 Y4 H" I9 j
  95. }
    , F/ z4 y+ e) o0 n  Z
  96. , h# F/ ^3 P4 q+ O) \6 i0 D+ y

  97. , @( r5 x" F* |3 z- i. a" n6 Z" q
  98. void main(){
    - y4 F9 G2 D  I+ h3 d
  99.         // 初始化P3和P5口
    $ w& T+ p& X/ @! o  V7 c1 F- z
  100.         GPIO_Init();2 R& j7 F' O$ l. j; A
  101.         // 初始化定时器0
    . k- s3 [! \" v( `- l
  102.         Timer0_Init();
      t: H% C- N. e' t  u6 Y
  103.         // 初始化中断
    4 }- S& Z, o, g: [+ G
  104.         Interrupt_Init();
    ( q) ~' u8 N  i. k- d
  105.        
    / ?! a1 n# k: d$ D' w8 A
  106.         while(1){
    ; T6 {+ w" O+ o$ V9 D
  107.                 // 检测电量) s* [( G7 f" W% @: O- O
  108.                 if(PCON & (1 << 5)){
    " T$ s0 M" {# ]0 {! v' z+ X
  109.                         // 如果电量低,低压指示灯亮" r0 M4 N8 E6 R( ]4 X8 v5 h
  110.                         LED = 0;
    % ?% b% D5 \" Q! `  k. W+ l5 g
  111.                         // 清电量检测硬件标志位( x) R  Y  W( S
  112.                         PCON &= ~(1 << 5);
    ! Y3 x. p$ L) U2 h; J  R# k" z
  113.                 }else{
    5 e! {+ B, D3 {5 {. {* s- E$ {
  114.                         // 电量正常,低压指示灯灭
    # `- e8 N$ x) G5 ^
  115.                         LED = 1;* ?0 J8 U& J) ~& Q. U1 e" a  q
  116.                 }; d8 U  @* b/ X& K' n0 x

  117. . F2 ?) F0 Q& C. V" ~! F- J
  118.                 // 检测到停机标志
    * {) k3 S% i" m6 l8 S( i
  119.                 if(isReadyToHalt == 1){
    6 x  d! p) F  J& \
  120.                         // 暂时关闭定时器0中断/ j1 ~! Q8 A7 K1 H" `$ D2 g6 M+ q
  121.                         ET0 = 0;) E/ }5 ?+ j% p6 e6 E. u- O1 I
  122.                         // 停机之前先把矩形波输出脚置低电平,以方便INT0和INT1唤醒CPU
    : F( K8 Q7 P5 a6 S
  123.                         OUT = 0;5 `1 ]: i  \. w% S+ [  }
  124.                         // 停机之前先把低压指示灯灭掉,以省电) c- q( V- F) E4 v5 H) v
  125.                         LED = 1;  n  }* q& ^+ t0 C9 [9 x
  126.                         // 进入停机模式
    ( @% ]- p& M' y( r
  127.                         PCON |= 0x02;0 O8 a( N1 c2 q% @/ W+ c+ S' j
  128.                         _nop_();
    ) u4 ~" i% D# b( h8 Q8 Z4 y4 Y
  129.                         _nop_();7 m$ T8 }+ C: ~
  130.                         _nop_();
    6 Z! d) w% J# a$ B" v' D0 C% l
  131.                         _nop_();
    2 @: l& G6 t% v8 H& [1 D% j' o: b0 k9 M
  132.                         // 唤醒,清标志位
    3 W% ~# x$ |4 l/ Y4 P4 s0 P
  133.                         isReadyToHalt = 0;
    : J) p3 S9 n- B- K- n. M/ j
  134.                         // 重开定时器0中断, Q4 ?* z& y, O
  135.                         ET0 = 1;5 S: m4 n- O5 |; \/ b8 r
  136.                 }7 r+ V  }5 ~0 Q
  137.         }
    9 l+ c2 I" H  z: S; u; }
  138. }4 u1 |6 E4 R* ~0 c0 f/ Z. G
复制代码

* r0 u! S- D7 G1 ?- K+ x. E6 ]/ `硬件参数配置:" J# Z3 \) G  t

5 ~2 [) \0 {; x' z: ]) z* O
# A/ }- f- Z) G' W接收端:! F5 G$ u6 s9 N1 b: o
  1. #include <INTRINS.H>! I' b  B: M6 K
  2. #include "STC15W.h"( P" `- e5 F# M+ A! o& B

  3. : z* `5 ]( ]; X6 l: S
  4. ' I" }( u2 g+ y& O) X$ ~
  5. /*4 s! A( Q& B* |
  6. & A! {: I6 E& F; l1 j
  7. *---------------------------*
    1 j3 N7 n" d& F+ Z9 [3 ~# U' ~
  8. |1 (GPIO2)         \__/  (GPIO1)16|
    # D- O% }2 {; ?
  9. |                                                        |
    , S0 @8 y* X% i2 P; H! P4 H' N
  10. |2 (GPIO3)                   (GPIO0)15|
    " J& L) F! J5 Z3 G, y. P7 F
  11. |                                                        |0 ^/ o- D+ L" d8 Z4 Z  _. f
  12. |3 (GPIO4)                                  14|
    - B3 x$ Q  K8 K5 \  z0 j- o& j
  13. |                                                        |- V! W4 b" H( g# {- R
  14. |4 (GPIO5)                        (DATA)13|) |" e4 @; Y; A& \
  15. |                  STC15W204S                |0 [* {0 @6 Z9 z8 v1 s
  16. |5 (GPIO6)                   (LATCH)12|6 m9 n/ h- j7 k- _3 ?
  17. |                                                        |( A4 u( |) A  V9 @$ @! Z5 D" @
  18. |6 (VCC)                         (CLK)11|2 I: p# e9 A1 e( b  m0 ]
  19. |                                                          |' G  Z7 ], O3 s" b; `6 G
  20. |7 (GPIO7)                         (TXD)10|  r" G+ [2 m# T! W
  21. |                                                        |% F+ u( y1 }" d* \- l
  22. |8 (GND)                         (RXD) 9|
    ; L: ^" x2 k; d% G- A8 G) G1 H' }
  23. *---------------------------*
    1 t4 Q9 U1 ]% k' _7 r
  24. Fosc = 12MHz
    1 ~+ X$ ]* Z9 J+ G# V" n8 g
  25. / i. J( l. c2 z. U& }; M( y4 Q
  26. P1.0 -> 上" j" T+ i* J9 j- Z  b4 l- R2 c
  27. P1.1 -> 左+ \" y1 I% M) h/ P& Q7 `( z2 d
  28. P1.2 -> 下3 p) J& }/ F( `, e% q
  29. P1.3 -> 右  v: w5 k' ?8 ?. [; g8 h# o
  30. P1.4 -> SEL
    " _: c4 A, R' H" P
  31. P1.5 -> STA$ p% k; l0 K2 x5 n! y
  32. P5.4 -> B3 p: t8 T1 k. B
  33. P5.5 -> A
    ; D7 V, A: z: n

  34. ' F) q' e, k7 q
  35. */
    0 C4 q& ]$ G8 `' U) i) P
  36. 6 z4 J" F5 e) @: W5 T  y

  37. ( A) a) e5 e& I% V! D8 \. }* H( G/ D
  38. sbit CLK        = P3^2;+ l! @, ]' j, E: q$ [  a+ _3 _
  39. sbit LATCH        = P3^3;/ J5 ]& B4 S# w) z% z7 O. X9 r
  40. sbit DATA        = P3^6;
    # P) S; o1 H$ B2 n  n

  41. ; ?& E) m2 ^7 \- l* {
  42. bit isReady = 0;2 c# Y  O& T0 l% {9 n# f
  43. static unsigned char key = 0;' G  b& g2 O* ^: n2 r* \
  44. static unsigned char buf = 0;        // 双缓冲。这个缓冲区保存从P1和P5组合而来的键值
    7 K0 S6 x; m6 R% `% S; R9 I
  45. static unsigned char bufReady = 0;        // 双缓冲。这个缓冲区保存上面那个缓冲区的备份
    ! B! ?- x6 P4 @3 ~) [
  46. static const unsigned char data mask[] = {0x80, 0x40, 0x10, 0x20, 0x01, 0x04, 0x02, 0x08};        // A B SELECT START UP DOWN LEFT RIGHT。为提升速度,这个表放到RAM中6 Y. G2 `% T7 k" \8 j
  47. static unsigned char idx = 0;4 Z/ L! H6 t. c" I9 J1 S

  48. 4 C" y5 N- O3 l- x
  49. ( {' C! J7 H" \1 x, W. d9 F  L5 Y
  50. static void GPIO_Init(){
    5 M9 j; s0 a( c% S& O0 F& h
  51.         // P1口和P5口用于接收并行信号,全部初始化为准双向,依靠内部弱上拉输出高电平/ F# ?2 }; l: N) Y3 v' f) u
  52.         P1M0 = 0;
    + s" B1 A# ~4 u8 l. o
  53.         P1M1 = 0;
    % K/ t' X7 f5 ?$ N: u' `8 y
  54.         P1= 0xFF;
    ' `1 |! E' O5 I4 f
  55.         P5M0 = 0;" G9 R) B5 t; }, ^1 C5 x0 D
  56.         P5M1 = 0;# a) }* G) Q) ?, \' @. {8 w9 }7 H
  57.         P5= 0xFF;( [2 r* |' }" a# r7 O( F  m1 d8 b
  58.         // P3口初始化为准双向- J9 \( [4 E) @6 w9 `
  59.         P3M0 = 0;
    - t$ V$ B  X! I
  60.         P3M1 = 0;
    6 y, a4 e1 p- n- o( k# Y
  61.         P3 = 0xFF;
    2 U+ F3 j: r) `  f$ l  e* P2 c
  62. }
    * S; o0 A( T7 p; h, R) t  \
  63. 4 p9 Y+ Y1 g. @3 }$ c2 ~6 C8 r
  64. static void Interrupt_Init(){% L$ e: f  D6 Y+ {& D
  65.         // INT0中断(CLK)触发类型为上升沿+下降沿
    % |4 ?' g% e, O3 J5 m. K' S
  66.         IT0 = 0;
    % P& ^7 l: L9 @2 |; _5 z5 w. b0 f
  67.         // 允许INT0中断7 t3 G1 I, j. Y- c" V+ k8 W9 l* T
  68.         EX0 = 1;
    * O0 j  e* c: N6 Q) p( I
  69.         // INT1中断(LATCH)触发类型为上升沿+下降沿" v% L; G/ ^( U' t0 ?
  70.         IT1 = 0;" d* M3 G6 T, Y+ c8 {  j2 k  N& \
  71.         // 允许INT1中断
    & l  T" H- D+ w; ^) Q6 v  x
  72.         EX1 = 1;
    2 i' H3 p% w3 A7 ~, D1 c
  73.         // 开启全局中断! j" M2 V0 K, U6 u6 D+ z
  74.         EA = 1;
    , `% b) a3 U5 T* Q9 C# S
  75. }+ \3 |. ?) ]; [
  76. 8 I- V. k* Q# j; m( P. T! ~# t" c
  77. static void INT0_Isr() interrupt 0{
    & z0 y; B$ O% N8 Y% H2 k9 {
  78.         // 只有已经成功锁存才允许CLK移位
    - z( X4 ^/ o$ @1 _& l" W* K. j
  79.         if(isReady == 0)
    ! t3 ?7 ^! s2 g; z) c8 d/ ^# Z
  80.                 return;1 ^$ Z8 D4 D/ K+ J: t$ L
  81.         // 读当前引脚电平,如果是低电平则说明是下降沿,此时直接忽略该中断
    8 b- _1 V1 [3 B" f: y8 t' D
  82.         if(CLK == 0)0 ~" a( C& m$ C  T0 U! h+ }  g2 Z
  83.                 return;. t( D0 T9 Z9 w4 D1 p8 e4 O
  84.         // CLK上升沿到来的时候,取锁存值的下一位输出
    + o9 j! H" J+ g7 v
  85.         idx++;8 c, _. z/ [+ d# _- ^4 e* z& S
  86.         DATA = key & mask[idx];" v# ?* Y3 e* G" ?* T7 M
  87.         // 如果已经完成7次移位,则一轮读取完成
    / b1 _/ K8 }- Z
  88.         if(idx >= 7)
    ) ^1 e- D2 }% [6 O- v3 E
  89.                 isReady = 0;
    , q0 E1 h7 v$ ?- N# c7 B
  90. }
    . E, ~% X  C7 N& N" r+ r" |
  91. / x8 r, L$ H$ N: f% F4 y1 u
  92. static void INT1_Isr() interrupt 2{" Y# [' c' z2 _1 A6 Q
  93.         // 读当前引脚电平,如果是低电平则说明是下降沿,此时直接忽略该中断
    & A: X0 h7 C. o' R; M* x/ p, e' j8 m
  94.         if(LATCH == 0)
    5 P0 {5 b3 `9 h8 Z+ X
  95.                 return;
    4 q8 f  b( e) \* L; j4 ?  m
  96.         // 当LATCH上升沿到来的时候,锁存所有按键状态,同时把键值A输出到DATA2 _6 @$ k3 j* B  @+ t7 u; D
  97.         key = bufReady;& _, Y/ w& t" u' S$ y1 X
  98.         DATA = key & 0x80;//mask[0];        // 为了加速运算,直接取表中的值而不是读表
    3 r/ {# x2 u  P) M5 H
  99.         idx = 0;
    ) E, w# g2 N2 z: j
  100.         // 允许CLK进行移位
    % a( a% {- ]" b7 b$ r5 ?; g) W( v
  101.         isReady = 1;# x* i- `- I- t+ ?& m. t
  102. }# Z# `# H( W1 B- }5 p& j

  103. ! h( ?2 U, o# H- x* S
  104. void main(){+ S, }2 C& X/ ]+ N) R9 F, K! r1 G+ Y
  105.         GPIO_Init();5 v2 W' M) N* Y4 C
  106.         Interrupt_Init();- `: N: _) ]2 O6 l
  107.         . @" w( X1 R* W% ]" N3 Z/ X
  108.         while(1){
    & z- T, O+ H% n% P( M9 x
  109.                 //PCON |= 0x01;        // 进入省电模式. X0 \0 s" h$ N4 G
  110.                 //_nop_();
    : P) o) }. a  k* P% s
  111.                 //_nop_();
    * i7 R1 P4 H6 c, f' G4 {
  112.                 //_nop_();+ D# @+ L7 v/ i9 w: Q, y: f
  113.                 //_nop_();
    % `- ^& P: z5 W. X
  114.                 buf = ~((P1 & 0x3F) | ((P5 << 2) & 0xC0));
    ; Q+ n6 N; n7 ^# q2 z, o9 N
  115.                 bufReady = buf;
    7 V1 T. Y6 F% C" N8 b
  116.         }
    8 t9 N/ H/ t; @+ O" q3 |
  117. }
    5 b5 G8 Q. {' Q. Z- N3 L( Y. B# r
复制代码

  `! y+ l( R1 N. r: h硬件参数配置无特殊要求,晶振频率选择12M即可。
; {$ X: }1 C. b! m& C- _. u  g0 [1 m! e; _$ g0 d1 A7 p
这是编译好的固件。

本帖子中包含更多资源

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

x

评分

参与人数 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
7 x4 Q" j9 ^7 f0 V+ q: t- R不错的设计,想问一下楼主,FC的15针公头怎么解决?普通的公头太短了,插不进去FC的扩展接口。 ...
5 A1 d9 F5 M6 C7 z, c6 s# u
坛友的改造方案
回复

使用道具 举报

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

使用道具 举报

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

使用道具 举报

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

使用道具 举报

 楼主| 发表于 2019-5-29 17:00:34 | 显示全部楼层
孙大师 发表于 2019-5-28 18:55* M, O+ E4 M$ \7 C
非常好,楼主是技术帝,到目前我都还没开发fc的无线套件,等空了,开发一套套件,等玩家自己组装。 ...

! C) B9 N3 V! ^7 k$ S  V3 j能得到孙大师的赞誉,不胜荣幸!- \$ U5 E5 {% Y( F
不如开发一个多功能手柄,比如用SFC手柄改造,L/R键配合其他组合键可以用来切换2P~4P、调节连发速度、软重启等各种功能。接收端插到15PIN扩展口。
回复

使用道具 举报

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

本版积分规则

小黑屋|手机版|Archiver|Video Game Do It Yourself ( 闽ICP备14000865号 )

GMT+8, 2024-4-26 17:25 , Processed in 0.067308 second(s), 14 queries .

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

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