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

 找回密码
 注册

QQ登录

只需一步,快速开始

查看: 14729|回复: 27

自制FC无线手柄

  [复制链接]
发表于 2019-5-22 14:16:45 | 显示全部楼层 |阅读模式
本帖最后由 雷精灵2046 于 2019-6-14 09:28 编辑
! T3 }: |  ?2 Q, O  R$ z* l" ]" [
, S+ P! G: p: V) Q# C/ P没有用复杂的分立元件搭建发射接收电路,直接用的现成的2.4G无线模块jdy-40。
0 N% G, Z0 H( G) w; M& \6 ^
. z0 Z  `4 w7 z; p
, a, A) }& R" k2 G% W1 r发射端靠3.7V锂电池供电,用了一片SOP8封装的STC单片机,负责产生连发脉冲,同时负责检测电池电量,电压低于3V左右的时候触发低压中断,低压指示LED就会亮起来告知该充电了。平时发射模块和单片机均处于睡眠状态,有按键按下才会唤醒,从而实现省电。实测睡眠状态下整机电流约1~2uA。板子洗了一下稍微干净了一点。因为对于微功耗设备来说,焊接残余的助焊剂可能会增加漏电流。
( o) u/ u! K1 X. ]9 r; K
. t* l5 @6 x5 O买了一个火花的FC山寨手柄,去掉里面的牛屎板子,并修正一下塑料挡板,把锂电池和充电模块装进去。
9 L6 w( z5 [& E# W- i9 v9 j为了减少体积,充电模块裁剪得十分小,并且更换了充电电阻使之适应这个小小的锂电池。这么小容量的电池,也不需要多么大的充电电流是吧?
4 B. a2 r) B9 p' o) J  z然后统统用热熔胶粘上。充电电流比较小,所以发热很少,不会熔化热熔胶。6 N) G% P: P" Q2 |9 `0 x' r) N1 q2 F- n
6 G2 C6 j7 ^+ v( ~% ?7 L

. {/ u# m- c- q4 i; M3 s7 O4 f7 X; x
& ]3 [; |1 \7 p: _: m/ E最后把按键、导电橡胶和电路板装上去。3 v% I/ C  ?+ o- ~" \, z& `# Y
精心裁剪了电路板,正好扣上,不会阻碍其他元件,也不会影响后盖和拧螺丝。
  h; m$ E0 m. q; R
' P# ~' z$ T% |; g# T5 Z. J% T9 @& m; d
完工!) F# m1 d2 g" A' n. o
6 s* U6 M, }6 y- g: w* J2 o; l) q
( W, _7 P$ m  s$ s
这是充电的MicroUSB插座。旁边的小孔用于透出低压报警LED的光线。) Y7 x+ I9 n  @! f  k+ N
5 @- c2 l8 M" \
- {7 V; x/ j0 B$ v
接收端用一片DIP16封装的STC单片机模拟CD4021。为啥要用单片机模拟而不是直接用CD4021?因为jdy-40模块接收端在有按键按下的时候输出高电平,无按键按下输出低电平,和普通手柄正好相反。当然我也可以用两片74HC00或者74HC04之类的逻辑门进行反相,但那就增加了芯片的数量。对于FC手柄这种工作频率并不高的设备来说,STC单片机完全可以胜任模拟工作。" e6 C; W& X1 G% O6 u

8 [* M7 I/ @% x8 _; D! C5 t  D: x: l, }; j# t4 H! i( B
, V# I) E9 D1 T. E8 b/ d" a. q
电路设计有点小小的错误,所以有几根飞线。原本设计使用低压差LDO是XC6206,结果在做这个接收模块的时候,买的LDO居然找不到了!无奈只好用了AMS1117。幸好对于接收模块来说是5V降到3.3V,1117可以胜任。要是发射端手柄的话,3.7V降到3.3V,那就非得用6206不可了。3 L8 p( X, Z' i' c! _6 L* S! h* P
/ D5 H: y! a  [. t$ h4 \3 S5 y
实测十分灵敏,延迟极小几乎感觉不出来。可惜这山寨手柄的手感并不佳,尤其是方向键,软塌塌的。看来我得买个剪线手柄改装。
3 m( d' C, n, O$ E! K$ A7 B. Y: n& o
这是电路图,有兴趣的朋友可以参考。
( z7 i. F& D- M5 F# A
9 g& y% V4 W% J# L7 L: _8 T* t5 B7 x7 A, S, P8 L
我信奉开源主义,十分痛恨把技术藏着掖着。好东西大家分享嘛!所以两个单片机的源代码大公开!
0 i% S  `. [+ x编译器:Keil 51。
( U4 S3 Q9 I% n* i/ [$ |. ]: n9 |3 k: X( C
发射端:
' p; m6 g* [. p& K, A0 C4 m# C# p
  1. #include <INTRINS.H>) A3 r/ _. k% S
  2. #include "STC15W.h"# Q% E" l6 A$ ^. P! L

  3. + |, j) K' ~. S
  4. 0 J5 F/ j. S: n9 {% R
  5. /*
    + @4 `, \3 X: f# O0 e) k
  6. --------------------------
    : j% @0 u* m9 M4 j$ t8 n
  7. |1 (OUT)        \__/   (INT1) 8|
    1 \% C5 [: }* \1 R$ L4 v* M, r  I
  8. |                                                   |* @! M( o0 n- b! i1 p- k
  9. |2 (VCC)                   (INT0) 7|* n, _, C; f/ R8 F9 q" U. Z; g
  10. |                 STC15W204S                   |/ i. W) q, O8 p) {3 x
  11. |3 (LED)                         (TXD) 6|
    " G; b! L; ~1 E
  12. |                                                   |
    2 I! F2 v  O( t$ A- z
  13. |4 (GND)                         (RXD) 5|# }5 M- X$ b. a; }, r) K3 A: [
  14. --------------------------) h5 @1 p; P9 t! n$ D! S8 T" b
  15. 6 Z% S; i4 ^+ a
  16. LED ---|<|---[===]--- VCC$ \1 `! S8 z+ s7 }% v( b% e5 V
  17.            Red          330+ O1 T. K6 P  b% u
  18. / _/ s) S# Z9 t1 o9 u5 X
  19. Fosc = 6MHz/ f) ?+ V( ]- C; V# r" J- Y$ }
  20. */
    0 C( H0 A' I" ^9 |6 x- I

  21. & k5 X7 j4 x- p

  22. % Q; d* N( L6 @1 A( W0 u9 r2 L
  23. // 矩形波输出脚" u( f: B7 Y/ Y% U" Y
  24. sbit OUT = P5^4;9 L% |9 B7 K$ M* {' Y/ g; l9 k* V6 V2 s
  25. // 低压指示灯引脚' W) o0 u! E: \; }& U( |6 |2 h- T
  26. sbit LED = P5^5;
    $ ^% N5 ?4 c4 `$ E6 T, x5 V# C

  27. 4 Z  b1 ]* L* a
  28. // 停机标志位
    5 W# Q# e  s: i
  29. bit isReadyToHalt = 0;( v  d4 h6 o; V/ f

  30. & k+ E3 t7 n, L1 {- f* R% j1 S
  31. // 矩形波次数累计
    4 O3 P% O6 j5 m1 V& r2 T* ?
  32. static volatile unsigned char count = 0;2 r3 I6 w; m! ]* n4 o- S
  33. 8 n# x5 Y: k1 ?4 p" V, Y7 [

  34. - A% A! _7 f4 K  V
  35. static void GPIO_Init(){
    ! S6 w5 D9 B2 b# J. A  H; n; y' o
  36.         // P3口设置为准双向,默认靠内部弱上拉输出高电平4 {; K# a  J$ H1 m9 _" S: \* c
  37.         P3M0 = 0;
    ! i% X$ |5 _- e1 N+ W( r- z
  38.         P3M1 = 0;
    ' i4 _2 U) V8 `0 z$ X* Z
  39.         P3 = 0xFF;4 e& s  S4 \7 _! V" q
  40.         // P5口设置为准双向,默认靠内部弱上拉输出高电平" Z( o+ [# G& w; h1 B, g
  41.         P5M0 = 0;& ]7 a4 k2 I( Z6 V4 F
  42.         P5M1 = 0;
    ' L+ z% e/ W: U6 x3 H  V
  43.         P5 = 0xFF;# E- P/ T5 s, q
  44. }
    $ G$ Y$ H/ z. G, Q1 q* P
  45. " C4 r  W; D6 s
  46. static void Timer0_Init(){! ^0 p6 N( {) R; E2 J$ P& x: ~! l
  47.         // 16毫秒@6.000MHz, s; J+ c) h3 j
  48.         AUXR &= 0x7F;        // 定时器时钟12T模式
    ) X$ b; `8 f1 W3 K- g8 m- g0 w
  49.         TMOD &= 0xF0;        // 设置定时器模式
    . h, R2 Y" Y" V  k
  50.         TL0 = 0xC0;                // 设置定时初值# T. S/ w% I- U- d' ~- r
  51.         TH0 = 0xE0;                // 设置定时初值8 j4 `2 N! x7 L  P) ?& u$ r$ W
  52.         TF0 = 0;                // 清除TF0标志
    % Y" W2 B$ Y+ T- H: |1 l
  53.         TR0 = 1;                // 定时器0开始计时
    - h5 M$ S8 g& _
  54. }
    ! J6 q/ S) q; D. ]) C) g

  55. - w. p6 a1 O& S. j! a8 p* c
  56. static void Interrupt_Init(){
    2 [8 t5 Q) e! ?( e$ B7 c' P
  57.         // INT0中断触发类型为下降沿触发0 f. Y1 D% m5 t* f
  58.         IT0 = 1;$ L& t! G4 S, H0 ]# y. V
  59.         // 允许INT0中断
      T) _6 x0 a! X1 ]
  60.         EX0 = 1;; n' k9 c  D7 h1 A' E
  61.         // INT1中断触发类型为下降沿触发
    8 u5 ]1 E7 Z; d0 A& l& [( A; A) E
  62.         IT1 = 1;7 N: t- Y  }- }1 S7 x
  63.         // 允许INT1中断1 Q( `) _8 C) \% h* s8 j
  64.         EX1 = 1;6 y  K( B; N& A
  65.         // 允许定时器0中断; Q. G- l: i6 k; A' h' ^6 N
  66.         ET0 = 1;
    % [  z" w' B; L' E. x( b5 f" [/ Y
  67.         // 允许全局中断+ J! c, d% M( h7 }/ m% }
  68.         EA = 1;- V2 ~3 M9 {8 y( L
  69. }3 W2 b( q3 T0 ~; B( ^

  70. ) K$ B- J8 o& A# o4 r9 Y6 I2 s
  71. static void INT0_Isr() interrupt 0{& Y) o, M$ S% A* U9 b) b* B
  72.         // 矩形波次数累计归零
    ; F( X+ r: `+ O& O+ X# B- @) z
  73.         count = 0;
    ( o8 Z- f* b) A4 z. I8 W! E0 W
  74.         // 重开定时器0中断
    % [8 r: T, y4 C3 O  k# w- m- F& _
  75.         ET0 = 1;7 f; X+ T( _1 l3 w3 g0 }
  76. }5 T' p" a- e6 X

  77. 9 |. n0 M) ]3 `0 q( t; t- t3 t
  78. static void Timer0_Isr() interrupt 1{
    / L& H' V; Z3 S7 J! [  {
  79.         // 输出矩形波* E( i! o1 n& h( S. R
  80.         OUT = ~OUT;
    2 }( [8 n2 O2 M! J4 t) Q
  81.         // 累计矩形波次数# I: F0 t! k0 M
  82.         count++;
    2 K# f6 S+ d, \& C9 ~9 x
  83.         // 超过250个矩形波,准备停机" F! D5 |# a3 v2 A
  84.         if(count > 250){3 R4 t, W9 B7 y0 X; w, g9 |
  85.                 count = 0;
    2 t) f' L  h3 q; v7 Y% o  J4 V
  86.                 isReadyToHalt = 1;
    1 c/ ?: E: n8 l- d. c1 Y
  87.         }2 n6 Q* ]% l  W" Q
  88. }3 U' a" Z( U- p& I' F, K

  89. * e; t6 d7 ]: c/ V$ `, G
  90. static void INT1_Isr() interrupt 2{( Q& ], X2 H. @; h$ z! y1 D$ Y" ?% Z
  91.         // 矩形波次数累计归零
    0 n6 W0 t6 V+ ?, E: @* m
  92.         count = 0;0 \5 v/ x+ u6 m* A8 u" f' a2 R  r
  93.         // 重开定时器0中断
    8 N9 {3 V6 _$ h9 T) a- ~" ?
  94.         ET0 = 1;
    + n# w7 n2 A* q5 a
  95. }
    * H9 |: r8 t  L! y. P, h8 @
  96. 3 Q1 ]- ^* ^1 ?* z  J% H8 ]
  97. ) _- u1 ]  Y* C/ V, {% ?+ e
  98. void main(){) J5 i% Z& K# X; K0 S; S
  99.         // 初始化P3和P5口
    3 B5 }! T' _3 W2 \9 K
  100.         GPIO_Init();
    ' i8 `! g1 X2 h. B
  101.         // 初始化定时器0% ~- E) n) D& w9 S$ ~! R
  102.         Timer0_Init();. E  G; P7 s% j+ ?( x6 ^% ]& Q) P4 O
  103.         // 初始化中断
    2 r0 T# f6 _+ N/ f% P" m1 q4 K
  104.         Interrupt_Init();8 `6 G6 `, Y. L% |5 a1 D
  105.        
    ' C2 }( H  Z$ j  K
  106.         while(1){
    3 }. V; V5 [2 V/ [' G2 S- h
  107.                 // 检测电量" U" C9 a1 |" N4 O! I6 y: L# z
  108.                 if(PCON & (1 << 5)){( b. ]) k* ?# a# I
  109.                         // 如果电量低,低压指示灯亮+ E1 H9 n  m. O! z) D
  110.                         LED = 0;2 W; S! T# X9 \
  111.                         // 清电量检测硬件标志位
    4 T* k( @2 S# @5 Y' L/ ?8 ?: M
  112.                         PCON &= ~(1 << 5);
    . _+ L' b1 P  S. ]4 J1 g& H
  113.                 }else{
    3 j( i+ ~5 T( Q! I  V( j# n2 p
  114.                         // 电量正常,低压指示灯灭
    / ]7 Z( O3 _  O8 p6 v9 U+ ?' S
  115.                         LED = 1;
    ) J* o$ F  D3 O* g4 ^7 I  Z0 ^" S
  116.                 }1 W6 g* o, a( j
  117. 4 V+ e6 m/ B- N) ~; q0 U
  118.                 // 检测到停机标志
    & ^1 |% y1 _2 r- ]6 X8 s
  119.                 if(isReadyToHalt == 1){
    - n; Y+ p$ I# p
  120.                         // 暂时关闭定时器0中断, c1 t3 F6 S6 `- C
  121.                         ET0 = 0;
    % `/ _/ M2 u# ^
  122.                         // 停机之前先把矩形波输出脚置低电平,以方便INT0和INT1唤醒CPU% s/ M. Q/ X; `! `5 X8 O
  123.                         OUT = 0;
    & b  M: n6 |6 V; `
  124.                         // 停机之前先把低压指示灯灭掉,以省电6 c) P0 J2 b- i1 k" }5 d( y+ A, A$ \
  125.                         LED = 1;* E# `3 F( N2 l
  126.                         // 进入停机模式! G( b; p+ b. p: |+ S. y
  127.                         PCON |= 0x02;. z# i) }8 E" u4 Y  ^
  128.                         _nop_();
    7 r& i8 f- P+ P6 m8 y
  129.                         _nop_();
    / q* {, N8 M- d0 d/ T+ E: ~
  130.                         _nop_();4 c' ^# f0 I8 b
  131.                         _nop_();0 [+ N/ m2 K; |4 w
  132.                         // 唤醒,清标志位, @0 b8 X# |4 H9 O, K
  133.                         isReadyToHalt = 0;
    ' S% c9 m' i  ~& c
  134.                         // 重开定时器0中断7 V. _$ F, e3 y! S+ K( S+ q' v
  135.                         ET0 = 1;
    4 \( M$ e* M& d% S5 m3 R6 L
  136.                 }: o5 r  T/ @6 V+ [: `  ]* D1 V1 ~
  137.         }& m6 ]4 R/ s- j. o4 B: V0 D, _# f
  138. }5 e4 O2 r/ a% U4 ?: L- V
复制代码
4 T6 C* L% B$ V' v
硬件参数配置:- D3 c: Y3 T8 K
  H" d1 a+ F" q  D" N5 A4 f  L8 k) F. t

! M! ?$ A, q$ k1 g* w接收端:, ^: Z: A% [4 z  g
  1. #include <INTRINS.H>
    + c6 [6 b  l/ p
  2. #include "STC15W.h"' _7 b* N8 j! G$ ^# `; n

  3. ) b! y+ Q- l/ U

  4. $ I. A. M- w  f5 t, f) U! p
  5. /*
    : ^" B# M" q/ K- C
  6. ! k/ Y$ x' Z) X: H+ @$ c& o+ V
  7. *---------------------------*' G* {- B* D$ H2 m' Y, [  ?5 b
  8. |1 (GPIO2)         \__/  (GPIO1)16|
    6 n- \/ K- R0 e/ i
  9. |                                                        |
    3 V4 ?3 L. P% s% Z
  10. |2 (GPIO3)                   (GPIO0)15|' P; Z% u; ]( u. G8 F% [9 K
  11. |                                                        |9 n1 P& s/ i9 \6 o/ Y6 B/ t
  12. |3 (GPIO4)                                  14|- \; u+ g' Z; w$ l9 S/ g( k
  13. |                                                        |
    / e7 F! d# H0 G8 k" k
  14. |4 (GPIO5)                        (DATA)13|
    0 J+ P2 k6 @! s& S3 J
  15. |                  STC15W204S                |
    - }: A, D( M: z
  16. |5 (GPIO6)                   (LATCH)12|
    3 S6 r: E8 S; t( f4 ]( T1 H4 d2 I
  17. |                                                        |: `) T8 j. n. G& v+ r  j
  18. |6 (VCC)                         (CLK)11|
    8 r- h4 z4 I- Q$ p5 X
  19. |                                                          |4 \3 O$ y1 G6 Z5 R7 A& O( Y7 E5 `
  20. |7 (GPIO7)                         (TXD)10|
    . x5 N5 l' n: ^6 ?# k' V7 p
  21. |                                                        |' a5 a5 O! M7 ~. o' N/ ]' R
  22. |8 (GND)                         (RXD) 9|
    4 D& i* G3 ]: `' p9 r  g+ v
  23. *---------------------------*/ U! {7 n8 V& }5 y/ g% ?4 V
  24. Fosc = 12MHz& I& ?5 }4 U# G/ P4 F) s; x
  25. 5 q9 T! o+ D: n) [1 k3 b
  26. P1.0 -> 上0 ]6 l# w9 v. J, u
  27. P1.1 -> 左# A5 F5 e" N: `: O( S
  28. P1.2 -> 下
    & e; t2 g8 E1 V  {- i8 n
  29. P1.3 -> 右
    & `$ `, Z1 N  R  H: X+ P* T' _
  30. P1.4 -> SEL5 Y8 u; h9 x$ ?+ D. i
  31. P1.5 -> STA! g# U, e4 G/ F4 a6 J9 {0 V2 m' r8 D
  32. P5.4 -> B
    + p; h5 y$ r* }- ?6 v' f% Z7 ~
  33. P5.5 -> A6 F! Z: O( ^, `  R

  34. 4 H: ?# n. f: l
  35. */
    " `1 \$ r; H( W
  36. 5 O! j+ k2 O9 Q9 r# s7 x: b

  37. : d1 [% P* Q0 n
  38. sbit CLK        = P3^2;
    9 s8 a% N/ F, \2 c, U, O
  39. sbit LATCH        = P3^3;
    2 M8 c( O: g& x3 t1 O; B+ {; i# _
  40. sbit DATA        = P3^6;
    , f5 T$ c8 B# n9 ~0 P
  41. 9 P" s$ S. I; ~( k1 V6 I
  42. bit isReady = 0;
    8 U+ q- T1 H9 I/ }
  43. static unsigned char key = 0;6 N3 w8 e# a, ~6 Y+ z/ Y
  44. static unsigned char buf = 0;        // 双缓冲。这个缓冲区保存从P1和P5组合而来的键值' @) a  n4 F2 s* C1 O2 K  m
  45. static unsigned char bufReady = 0;        // 双缓冲。这个缓冲区保存上面那个缓冲区的备份
    # s/ b4 U9 ^2 a0 K1 q! 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中5 p1 Y; Z5 h" |+ I7 q  v9 y$ S! q
  47. static unsigned char idx = 0;
    : A2 Q2 [9 s/ H* a, O$ I
  48. - K; n% W: K8 k  ?7 @, X! O5 i
  49. , ~' a9 \+ P0 G" |
  50. static void GPIO_Init(){- W5 ]- @% C! z9 e4 e/ {, i9 E
  51.         // P1口和P5口用于接收并行信号,全部初始化为准双向,依靠内部弱上拉输出高电平( {7 M( k& P( i, d: s& P0 v3 p
  52.         P1M0 = 0;# e* q& }7 N9 b, P, Q" k+ j) a# T
  53.         P1M1 = 0;; k: V- k0 l4 o# A' l* }
  54.         P1= 0xFF;9 }( f8 D+ C7 T
  55.         P5M0 = 0;! |6 O" ~  m2 w: F+ {: s/ ?9 v7 j
  56.         P5M1 = 0;
    2 |1 \2 ~+ c8 a# V6 A
  57.         P5= 0xFF;6 R. b- G7 s& P9 r
  58.         // P3口初始化为准双向
    1 g3 Q. M; b/ p& w' {* b* n% N
  59.         P3M0 = 0;
    ( f1 M' j$ \! e! g3 n* U
  60.         P3M1 = 0;
    4 J! s" ?- L  N" j/ z
  61.         P3 = 0xFF;6 y; T0 w) t  b/ D
  62. }8 i, O1 F* _4 y6 q
  63. ) j* L/ i8 a$ k" P& H5 |  |
  64. static void Interrupt_Init(){
    ' Q# N8 c8 Q  O$ g$ d
  65.         // INT0中断(CLK)触发类型为上升沿+下降沿
    ( o. ~( `* K  e9 W
  66.         IT0 = 0;
    # ^: _3 m% Z+ o  u! @' r
  67.         // 允许INT0中断
    ) W6 X4 R: R$ o4 i
  68.         EX0 = 1;8 _: Z7 c6 `0 z' l9 ?% {* V  U; Z5 I
  69.         // INT1中断(LATCH)触发类型为上升沿+下降沿, f$ K9 G1 k+ j1 P9 ^; h
  70.         IT1 = 0;' e; w! x0 \5 I
  71.         // 允许INT1中断
    ) ~$ j0 i4 K, r  p" h
  72.         EX1 = 1;; A2 k1 \# I; |' y3 ]! `
  73.         // 开启全局中断4 _8 Z0 l/ d  T: z# M1 P6 d
  74.         EA = 1;/ q& W: v* R0 T' _* `
  75. }
    * y6 u/ n! f; \. U1 S! a
  76. , J3 I+ `" V0 P' Y7 i0 A2 H# ]# ]
  77. static void INT0_Isr() interrupt 0{/ X. q% T" M9 q6 M
  78.         // 只有已经成功锁存才允许CLK移位
    $ c3 y+ h+ V+ z
  79.         if(isReady == 0)
    / M& J" l3 a+ m6 Y! A  V6 t( K
  80.                 return;
    ) A  w0 g$ P4 i; s( l3 _0 \3 T# t
  81.         // 读当前引脚电平,如果是低电平则说明是下降沿,此时直接忽略该中断
    * e, O. C4 E+ _3 H9 X
  82.         if(CLK == 0)
    ; }9 i$ N* }1 T* U- K
  83.                 return;
    . e6 r0 m4 x7 U& A/ A
  84.         // CLK上升沿到来的时候,取锁存值的下一位输出# U% K1 D8 m" v" m
  85.         idx++;7 W8 h2 p+ Q- r
  86.         DATA = key & mask[idx];
    4 P. L2 L5 s9 w7 B/ J0 P% k
  87.         // 如果已经完成7次移位,则一轮读取完成
    9 R3 U7 V6 [& V4 o
  88.         if(idx >= 7)) [7 T0 O: M: i. z* |
  89.                 isReady = 0;; `9 D* x3 w0 H) h' [* I
  90. }. t0 ~5 I& O2 Z  J$ @- o
  91. # i* L9 W: f' r8 D5 {
  92. static void INT1_Isr() interrupt 2{
    ! }/ f3 T  E+ N. Z5 ^
  93.         // 读当前引脚电平,如果是低电平则说明是下降沿,此时直接忽略该中断- z* t$ ^& h! k
  94.         if(LATCH == 0)8 _# Z; ?* N: B4 M2 g4 t- T
  95.                 return;
    3 o( A& t- c, V8 j( `. R7 J6 H
  96.         // 当LATCH上升沿到来的时候,锁存所有按键状态,同时把键值A输出到DATA+ P  y. o$ X3 g
  97.         key = bufReady;
    $ y# q9 a  N' a, ^' Q, W- F
  98.         DATA = key & 0x80;//mask[0];        // 为了加速运算,直接取表中的值而不是读表
    & c# X7 y3 o4 r1 z3 v
  99.         idx = 0;
    4 h9 H# P9 L' ?: F6 c
  100.         // 允许CLK进行移位
    7 R7 |; F9 O, I: Z3 b" N0 S8 ]
  101.         isReady = 1;; p5 w$ V6 D3 p' y8 u
  102. }9 C8 j% n: U) f5 R1 ~
  103. 5 Z& v+ }' Q' R9 r' t. w4 m
  104. void main(){
    $ P2 f2 m! O- X! N, f! \
  105.         GPIO_Init();
    4 {, `& L1 P2 o: G3 @0 U
  106.         Interrupt_Init();0 k$ R* f. y$ W+ J
  107.        
    % i& J$ {7 L0 D- B) o1 V
  108.         while(1){
    ( {$ @  ^6 U0 O* |
  109.                 //PCON |= 0x01;        // 进入省电模式
    + q8 T7 s' [* p; U/ `; [
  110.                 //_nop_();
    : ~' j- \4 d: b: L7 G: }6 g
  111.                 //_nop_();
    & {# w2 @  T+ w1 l! E: s
  112.                 //_nop_();
    ( e4 T5 U5 x! z& Q
  113.                 //_nop_();! D4 m5 j# c( E2 r
  114.                 buf = ~((P1 & 0x3F) | ((P5 << 2) & 0xC0));
    * t: f0 t( t1 ?& v
  115.                 bufReady = buf;; ?1 ^( v6 p4 S3 T
  116.         }9 X$ l4 K7 p! @
  117. }. a2 r, R6 Z& u+ f, ?/ }
复制代码
: S- q" ]! z* _
硬件参数配置无特殊要求,晶振频率选择12M即可。- ?( b/ P: t; {, s
% [# \$ M0 V: T( q8 @% G0 M1 w
这是编译好的固件。

本帖子中包含更多资源

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

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- N4 R$ I, {# i2 E
不错的设计,想问一下楼主,FC的15针公头怎么解决?普通的公头太短了,插不进去FC的扩展接口。 ...
; s* D# p7 T7 U0 S. b% J5 \. H0 q
坛友的改造方案
回复

使用道具 举报

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

使用道具 举报

发表于 2019-5-25 12:07:18 | 显示全部楼层
精彩,楼主动手强,也写得很详细。/ N5 E! A2 D6 @+ ^: q% s  J
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
& O: o' H9 z* T  `4 h8 j精彩,楼主动手强,也写得很详细。
; Q8 P5 g  M) D, M  h2.4G方案是目前无线的最低延迟吗?
- p' O$ T+ r0 O7 E6 B
我没用过其他无线手柄,所以实在不知道我自己做的这个手柄到底是不是最低延迟。
& x( c* B0 v- E$ _- b& ~, _, Q$ k7 F) }不过根据网上的说法,延迟高低主要是由通信协议的复杂程度,以及数据传输速率决定的。这个模块虽然是2.4G无线模块,但由于协议很简单,所以延迟比较低。
6 ?) N4 a$ m& |9 h4 z! g我用这个手柄玩一些ACT游戏,比如超级马里奥、忍者龙剑传、热血系列,完全感觉不到延迟,和游戏机自带的手柄没有任何区别。唯一的区别就是这个手柄是用火花山寨手柄改造的,外壳是垃圾回收塑料,粗糙+脆弱,导电橡胶弹性不佳,手感不是一般的差。$ e1 c6 P/ R3 L; }, G6 L; H; E' z
我手里还有十几张板子,等我有空了我再做一套,到时候买一个好一点的手柄改造。
回复

使用道具 举报

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

使用道具 举报

 楼主| 发表于 2019-5-29 17:00:34 | 显示全部楼层
孙大师 发表于 2019-5-28 18:559 k6 `- \/ p7 r5 C
非常好,楼主是技术帝,到目前我都还没开发fc的无线套件,等空了,开发一套套件,等玩家自己组装。 ...
# I2 i$ ]" Q1 m3 S) i/ ?. H
能得到孙大师的赞誉,不胜荣幸!( b' W, q/ `$ ~$ B) b; ^% z
不如开发一个多功能手柄,比如用SFC手柄改造,L/R键配合其他组合键可以用来切换2P~4P、调节连发速度、软重启等各种功能。接收端插到15PIN扩展口。
回复

使用道具 举报

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

本版积分规则

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

GMT+8, 2024-4-27 01:38 , Processed in 0.059863 second(s), 14 queries .

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

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