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

 找回密码
 注册

QQ登录

只需一步,快速开始

查看: 14185|回复: 27

自制FC无线手柄

  [复制链接]
发表于 2019-5-22 14:16:45 | 显示全部楼层 |阅读模式
本帖最后由 雷精灵2046 于 2019-6-14 09:28 编辑 5 m% ?- F5 K8 W+ m

  \  b0 e$ e5 D2 N1 @1 r( {没有用复杂的分立元件搭建发射接收电路,直接用的现成的2.4G无线模块jdy-40。, N6 ^1 V7 r# m- ?  z

, x( Z5 r+ O0 L, I' F4 R# `0 O
5 {6 k! I; B7 L% J发射端靠3.7V锂电池供电,用了一片SOP8封装的STC单片机,负责产生连发脉冲,同时负责检测电池电量,电压低于3V左右的时候触发低压中断,低压指示LED就会亮起来告知该充电了。平时发射模块和单片机均处于睡眠状态,有按键按下才会唤醒,从而实现省电。实测睡眠状态下整机电流约1~2uA。板子洗了一下稍微干净了一点。因为对于微功耗设备来说,焊接残余的助焊剂可能会增加漏电流。" K" r  k* i* [6 h& q" n
, D- U9 }' p# Q7 f4 \
买了一个火花的FC山寨手柄,去掉里面的牛屎板子,并修正一下塑料挡板,把锂电池和充电模块装进去。
3 P9 V0 ?4 u2 Y0 O为了减少体积,充电模块裁剪得十分小,并且更换了充电电阻使之适应这个小小的锂电池。这么小容量的电池,也不需要多么大的充电电流是吧?
, ]+ X: F5 V; [* d; m3 s& O6 C然后统统用热熔胶粘上。充电电流比较小,所以发热很少,不会熔化热熔胶。, _1 c9 `3 A" t* D
& G3 H7 A) E- n+ t

" m$ [0 V. X* L- }9 Q1 h# p0 F8 K; L
最后把按键、导电橡胶和电路板装上去。
  Z7 D, M1 G1 k* }0 W4 L+ L精心裁剪了电路板,正好扣上,不会阻碍其他元件,也不会影响后盖和拧螺丝。
$ z# _/ f+ t! r
) g) Y1 h' i: x" p/ W  u9 c! b+ ]7 a/ k$ z" Z1 K4 I5 a
完工!
- r0 o9 I  C8 u7 N$ G' ?
! J+ K0 P( m. [  `
% _) F7 k1 F9 ~8 t% h8 h5 _这是充电的MicroUSB插座。旁边的小孔用于透出低压报警LED的光线。  g8 e# I3 ~' C8 h: p/ |( [) ^

3 q4 n/ V: T+ ]3 p0 _; `
/ ~7 l' Z7 ^! D6 i9 S# b接收端用一片DIP16封装的STC单片机模拟CD4021。为啥要用单片机模拟而不是直接用CD4021?因为jdy-40模块接收端在有按键按下的时候输出高电平,无按键按下输出低电平,和普通手柄正好相反。当然我也可以用两片74HC00或者74HC04之类的逻辑门进行反相,但那就增加了芯片的数量。对于FC手柄这种工作频率并不高的设备来说,STC单片机完全可以胜任模拟工作。' q+ N! L5 P" W1 g) [- [! z# N
- F/ ?* [$ V$ h2 _6 |& G

( S1 o4 A1 l& O. p
- v1 K& C) z, s4 G" X9 K# H- Q* d电路设计有点小小的错误,所以有几根飞线。原本设计使用低压差LDO是XC6206,结果在做这个接收模块的时候,买的LDO居然找不到了!无奈只好用了AMS1117。幸好对于接收模块来说是5V降到3.3V,1117可以胜任。要是发射端手柄的话,3.7V降到3.3V,那就非得用6206不可了。) J. ~8 _" e# `5 k0 q% ^
9 Q7 Q6 B. U9 P" \  U+ A
实测十分灵敏,延迟极小几乎感觉不出来。可惜这山寨手柄的手感并不佳,尤其是方向键,软塌塌的。看来我得买个剪线手柄改装。' K3 r- p' {6 m3 F5 e- {! l
8 b' T7 c% n3 Y/ Q; c
这是电路图,有兴趣的朋友可以参考。
$ e7 X8 I. i- ~7 H+ L" A! n/ t! P$ p" P3 ?# v' J

& {3 W' X* Z3 a7 v2 l7 U/ P2 u我信奉开源主义,十分痛恨把技术藏着掖着。好东西大家分享嘛!所以两个单片机的源代码大公开!* M  N& H% G: A: u- C; _- ?8 S
编译器:Keil 51。
  ~: v" w, g& m3 \( h  z/ g, X$ u* d6 K* i4 B/ {% H" a
发射端:
7 u; b, i+ s8 Q0 E/ r% Y/ ?
  1. #include <INTRINS.H>) P4 x1 P/ s9 Q3 x) i( R
  2. #include "STC15W.h". e! J" r9 ?9 s  }% k

  3. / @, M. C, I; F& m* M0 i+ h
  4.   S/ w/ k# Y; X$ }. L
  5. /*$ k6 W2 @9 B; B. i# x3 C9 W0 y1 h
  6. --------------------------" \3 U, G8 [  z/ r4 W6 ?
  7. |1 (OUT)        \__/   (INT1) 8|
    # }/ {( a( j* W2 \" b8 z+ t0 _
  8. |                                                   |0 v0 }- [9 `0 A8 F( k
  9. |2 (VCC)                   (INT0) 7|. |0 Q# v3 z* ?9 l( l* F/ P
  10. |                 STC15W204S                   |
    & m4 K9 _, |* Q0 `. H
  11. |3 (LED)                         (TXD) 6|0 u9 L" k) a; {' ~2 F* W5 w
  12. |                                                   |
    ) Z9 X8 W& ?+ d
  13. |4 (GND)                         (RXD) 5|
    4 u5 D4 I: l% S, m
  14. --------------------------
    # W! M1 @1 Z+ C! R" R2 N
  15. / E% p( c) K+ |# F
  16. LED ---|<|---[===]--- VCC8 s4 N! A" Y* G+ ]
  17.            Red          330
      S( T' t: }. i& v6 ~

  18. 6 ]8 f( T7 t/ j  S) O
  19. Fosc = 6MHz
    ) n0 C, ^2 ~4 T. x, D" m1 x
  20. */
    # v) b0 K8 f! M( A: ~  ]

  21. $ A& i0 G7 m/ t; L5 L2 I1 d

  22. 3 h' U) d3 G: W" Q4 g
  23. // 矩形波输出脚
    ; N. p( ?( ^" ?( ~( L1 b
  24. sbit OUT = P5^4;
    - a+ R3 X1 I5 v+ [& N' `$ h, w* A+ B6 G
  25. // 低压指示灯引脚6 Z, C8 K7 A; F! g, s
  26. sbit LED = P5^5;
    8 l6 ^5 @1 e7 Y$ r5 |, U) _8 ~! ]

  27. * J3 x5 x& W. j
  28. // 停机标志位: U8 s0 Q- r( z1 u  M" a
  29. bit isReadyToHalt = 0;6 k1 H, i0 g; p3 O

  30. 5 F5 e2 q0 s, }3 A% i' A7 N
  31. // 矩形波次数累计
    6 A& ?( s3 k/ {* M! ]* ~
  32. static volatile unsigned char count = 0;
    8 i; F) h2 v4 N9 i$ H1 Y0 c4 V' r
  33. 3 o! b4 s1 O% A. a" \
  34. 7 L5 P* a- T9 o; E  J2 q# l/ I
  35. static void GPIO_Init(){
    6 }! r0 A% e5 w
  36.         // P3口设置为准双向,默认靠内部弱上拉输出高电平" E* u: B% @7 z% L2 ?# Y. u
  37.         P3M0 = 0;' c/ L& ?" O. Q' ?% _
  38.         P3M1 = 0;5 u5 O" L9 t+ n1 y  w' Q& r- c- _6 o; q
  39.         P3 = 0xFF;
    ! v5 m( S8 ?: a5 E
  40.         // P5口设置为准双向,默认靠内部弱上拉输出高电平# G8 _" k% h4 A" D
  41.         P5M0 = 0;
    7 L, t. J/ x- j, t& V- E* r
  42.         P5M1 = 0;
    : H- v3 h* G: I& H' C8 {" G
  43.         P5 = 0xFF;
    6 N4 a' A+ b- I% l4 G# }  O
  44. }* j9 h0 a7 u, f3 l

  45. 2 \6 B4 ^0 `: k7 C& r- e3 h, R
  46. static void Timer0_Init(){4 l' I1 @' m3 Q' p8 e, K. L4 ?
  47.         // 16毫秒@6.000MHz3 E" j: [9 T" \7 j7 b9 C+ F# y
  48.         AUXR &= 0x7F;        // 定时器时钟12T模式
    $ F1 h( u* ~9 B* s, O8 q- D
  49.         TMOD &= 0xF0;        // 设置定时器模式  s$ ~  v8 [- ?0 J4 [- x
  50.         TL0 = 0xC0;                // 设置定时初值9 I1 @% j# T2 ^9 R
  51.         TH0 = 0xE0;                // 设置定时初值9 h) [* z$ o7 Q! i/ s8 u# S
  52.         TF0 = 0;                // 清除TF0标志: p. j# i: B9 A  D
  53.         TR0 = 1;                // 定时器0开始计时6 Q8 S. S* e7 c- X
  54. }
    % r9 y% P) A4 ]0 J* l; H. C# z! a

  55. 2 t! X# Y# @( ], i% W! l4 A- m( \
  56. static void Interrupt_Init(){6 k. [1 K  {/ w, D$ i/ ~( @- q
  57.         // INT0中断触发类型为下降沿触发, k& n4 |3 @# p, l! m) J% d  D2 h
  58.         IT0 = 1;) M0 g. f7 E" K' l! }
  59.         // 允许INT0中断5 n0 \+ W# Y6 }; j. E5 i6 |: B! v
  60.         EX0 = 1;5 i4 s4 A: X& S. ^. p  p
  61.         // INT1中断触发类型为下降沿触发
    ) T! \0 ]  T3 P! e
  62.         IT1 = 1;& M* [/ }, y& C' g0 `; e0 l9 d
  63.         // 允许INT1中断
    ' l( W, M5 P1 o# [* g0 Q8 B) w" j
  64.         EX1 = 1;
    % O# K+ R4 `+ Q$ D& C
  65.         // 允许定时器0中断( [9 l7 x8 }' y  H' x) V
  66.         ET0 = 1;& G4 Z$ F9 w. F: C1 O
  67.         // 允许全局中断1 E9 `& K, v. w% n7 g
  68.         EA = 1;3 x1 P  Y: O$ b4 k8 Q
  69. }
    9 s$ Z. G; Q" I, k1 P: [

  70. ) e) c9 R/ ]$ x; M$ Z( z' P: T  y
  71. static void INT0_Isr() interrupt 0{) M% X/ ~: a& j! {- w* u" e
  72.         // 矩形波次数累计归零
    8 G- B: R. \# ~! {
  73.         count = 0;
    $ X  ?6 L( S# G0 o7 t3 Y
  74.         // 重开定时器0中断: L* r" ]" w8 G9 G3 E
  75.         ET0 = 1;! ?$ Y0 \$ p8 x6 Y- m
  76. }
    ; f# F7 D: k1 b
  77. 5 h: N; y8 E0 a# e+ b  h
  78. static void Timer0_Isr() interrupt 1{
    0 u* ?# |7 M) c9 o* t/ l. \
  79.         // 输出矩形波
    5 H" v( R) Y% q% x  y5 k- I
  80.         OUT = ~OUT;
    4 }  ]. G% F  E2 [
  81.         // 累计矩形波次数
      V% E8 ?5 \# M. ]0 ~( u: B
  82.         count++;
    * Y5 t* {' h; ?! p% W* s! o
  83.         // 超过250个矩形波,准备停机
    ) O+ j* F" F, |7 B, D
  84.         if(count > 250){
    + z$ @# Y* G# G% B, l6 h, A
  85.                 count = 0;' d4 L7 R/ R3 s+ q7 D* _
  86.                 isReadyToHalt = 1;- k! W# K! j, P8 G
  87.         }( D! r" `2 ]* E3 H6 M- Z$ r1 {
  88. }( O# ^1 t/ W1 i) ^, c8 F
  89. 5 J5 v2 X- g+ B! d1 w) j, `5 m
  90. static void INT1_Isr() interrupt 2{
    + y( P  O% c5 p  M! r: S% F5 X% i& s* L
  91.         // 矩形波次数累计归零
    % n- D' G: M, [. t) o
  92.         count = 0;9 q/ w9 L5 C1 }
  93.         // 重开定时器0中断
      e+ S0 c5 U( I; O) u$ |2 E
  94.         ET0 = 1;
    * D* r9 _$ ?, ^6 o9 J4 v: @
  95. }! l9 @2 w" H# l) _
  96. , p; {4 I  F) H7 Q( I& S/ E
  97. $ ~" Y7 z; J1 r0 [7 h
  98. void main(){, ]) y' ?0 L+ Q
  99.         // 初始化P3和P5口$ Q% w/ ]1 ^4 @0 C3 q5 s" n6 f
  100.         GPIO_Init();
    2 y' j- N( W" W( l  S4 I
  101.         // 初始化定时器0
    + r( h/ U( d0 z
  102.         Timer0_Init();
    , a2 W8 b) m6 h0 r( f8 l$ @
  103.         // 初始化中断, J" o* q- U( p6 f
  104.         Interrupt_Init();" i  W' Z" E* x1 x/ v% ]! |
  105.        
    # U0 {& l  _/ h7 [6 Z, X% d& U
  106.         while(1){0 |5 _7 R5 n) o6 L3 |) t& b
  107.                 // 检测电量
    2 ?9 s6 a" G7 k- A4 W( X) s
  108.                 if(PCON & (1 << 5)){: x/ T) \2 u3 q
  109.                         // 如果电量低,低压指示灯亮( c: l0 {* p+ T6 t9 d$ X
  110.                         LED = 0;6 x" }9 d$ w% R. D) ~5 Q( B
  111.                         // 清电量检测硬件标志位4 K  H3 U/ A+ w+ e
  112.                         PCON &= ~(1 << 5);  M' Z  u, Z1 {, l, ?$ c& f
  113.                 }else{
    6 a0 q+ l$ m3 f% o$ n' K4 B
  114.                         // 电量正常,低压指示灯灭% L0 F2 O0 x" T9 W5 x! S& `* c
  115.                         LED = 1;
    " z# B7 N: r  H# Z5 \  _1 L
  116.                 }
    6 D$ X8 k, s- l. Z* z# x
  117. 9 V& L& n# X+ e1 H5 x
  118.                 // 检测到停机标志) |$ U. k& P$ Q! f& i% S  u
  119.                 if(isReadyToHalt == 1){
    ) Q: A8 @/ m/ `
  120.                         // 暂时关闭定时器0中断
    ! M0 V1 z1 {# D
  121.                         ET0 = 0;
    / r% ?/ k0 @7 l  q2 s% ]' z/ ?
  122.                         // 停机之前先把矩形波输出脚置低电平,以方便INT0和INT1唤醒CPU
    % s6 T- C/ a3 s8 Q  ]6 A4 D+ r
  123.                         OUT = 0;' L% H' x) _/ I& k
  124.                         // 停机之前先把低压指示灯灭掉,以省电+ w9 Z. P7 Q4 H* C$ f# [
  125.                         LED = 1;
    * L" q5 i$ d/ s# Q, |
  126.                         // 进入停机模式! Z5 I$ H" O) |$ G
  127.                         PCON |= 0x02;
    " O3 o" Q' U- p& g6 G% }
  128.                         _nop_();
    & T) F# V  G% y
  129.                         _nop_();
    * b% J& ~* U: L; z  I/ }; d8 g
  130.                         _nop_();. }+ s' U$ A' A( j& k
  131.                         _nop_();2 f1 }/ L$ Q1 ~' t1 A' }& |8 w
  132.                         // 唤醒,清标志位
    ) ~' N" {& Y9 O9 _7 X3 c
  133.                         isReadyToHalt = 0;
    3 K0 t0 U9 `7 `; N
  134.                         // 重开定时器0中断
    8 m4 G* v2 k6 [  I
  135.                         ET0 = 1;
    : a6 b8 A" z2 z( b3 p- [
  136.                 }
    + J+ }; r& p) U9 n9 p; G( a
  137.         }5 u2 o8 p- u, x% o; c! J3 D8 E2 E4 f
  138. }
    % L7 v  u' U; i; L' e
复制代码

1 Q' ~0 z3 j; D9 R# V硬件参数配置:- q' X! l4 ]! }" t% w# F! j

% L: f; U9 v' S, K/ o; P& Y9 d5 `* w  Y! B* U3 i; B9 n
接收端:
! C7 e( _6 A5 z; s3 G  Y
  1. #include <INTRINS.H>6 u- L; ~% W4 l9 W
  2. #include "STC15W.h"
    - q+ x9 r& q! i7 w. @& @
  3. : C! {( z- k0 X

  4. ' t3 c! G% D+ n5 P" V
  5. /*) X' ^2 L. L( a; q2 o  f9 a
  6. - o- m8 A; C9 Z9 p& W
  7. *---------------------------** W) s0 ^$ s3 r  p4 j" y! C' t2 x
  8. |1 (GPIO2)         \__/  (GPIO1)16|
    . \* q. @8 c" d4 s
  9. |                                                        |; |3 G; [) l+ M! Z
  10. |2 (GPIO3)                   (GPIO0)15|- d6 [$ E" W# B" v- d
  11. |                                                        |- h2 J0 q4 G- o
  12. |3 (GPIO4)                                  14|
    7 Z: Z* M' P; X$ |, r* h5 y
  13. |                                                        |
    ' W8 ?/ @! Q" s% U: S
  14. |4 (GPIO5)                        (DATA)13|$ C5 D& H- O% q  ~6 [# J2 y
  15. |                  STC15W204S                |/ W( V, ?4 y1 x3 ~: g3 G4 }4 I6 [
  16. |5 (GPIO6)                   (LATCH)12|$ Z) J8 q) c( I- ]
  17. |                                                        |
    , ^2 m4 o- z* c9 d; l& ]2 n  o, Y
  18. |6 (VCC)                         (CLK)11|
    . l. @$ h- i" _
  19. |                                                          |
      n4 I' b5 Y; _3 \
  20. |7 (GPIO7)                         (TXD)10|
    0 y$ M! V$ y- b& J0 `
  21. |                                                        |* M3 I+ r# ~0 g& k: l
  22. |8 (GND)                         (RXD) 9|8 `% G# v' x6 M3 X# G
  23. *---------------------------*( h9 X/ k; b5 x0 i
  24. Fosc = 12MHz: A& w; K. n  N/ P5 r
  25. - H+ j0 Y. K- m% [4 f' Z6 |% {$ \
  26. P1.0 -> 上! ^7 k' X1 M9 g/ p4 Q1 d
  27. P1.1 -> 左
    $ w* ?3 W8 O1 i5 C# A* T1 ]& e( Q) \
  28. P1.2 -> 下1 V. a; r8 V& T
  29. P1.3 -> 右  K+ h' ^: h% I! e3 \9 K
  30. P1.4 -> SEL9 i! ?' H; Z9 P$ |7 r
  31. P1.5 -> STA
    8 H, h8 O) y! j; D8 A) r
  32. P5.4 -> B$ ?  o2 p# @: R' `
  33. P5.5 -> A" B+ h: A- z7 e5 A0 s7 a
  34. # z$ ?0 V0 |% L, W% b
  35. */
    , t  N2 p0 _) f5 e/ o4 M
  36. : X  j; i9 r% {- j3 c
  37. * c7 z5 E8 e! ?: h2 Q' T
  38. sbit CLK        = P3^2;, v- {8 g. e- q: z5 B+ l6 X4 B
  39. sbit LATCH        = P3^3;
      B7 V. ]( h' w* p7 X; Q
  40. sbit DATA        = P3^6;
    , J3 K7 o6 h- P& |: J9 `7 f

  41. 6 k5 c8 N3 }) @& N" B  }% j( p
  42. bit isReady = 0;% V/ `* T! X" R/ e* H
  43. static unsigned char key = 0;7 U$ @# `& @  q; F& F: r
  44. static unsigned char buf = 0;        // 双缓冲。这个缓冲区保存从P1和P5组合而来的键值
    : ^# f8 Q$ N7 H5 i
  45. static unsigned char bufReady = 0;        // 双缓冲。这个缓冲区保存上面那个缓冲区的备份8 z  Q7 {+ f, e; J) R2 ?
  46. static const unsigned char data mask[] = {0x80, 0x40, 0x10, 0x20, 0x01, 0x04, 0x02, 0x08};        // A B SELECT START UP DOWN LEFT RIGHT。为提升速度,这个表放到RAM中
    , `2 W2 M8 r. ?" @
  47. static unsigned char idx = 0;( Y% y" Z# A* T" ?$ m0 O% E
  48. 5 X3 Y6 D* k; }" k
  49. - `: m% [: u8 S* O/ z0 ?( Z
  50. static void GPIO_Init(){
    $ T* w3 C5 n( U6 |' k
  51.         // P1口和P5口用于接收并行信号,全部初始化为准双向,依靠内部弱上拉输出高电平
    % m' |# N" l' ]
  52.         P1M0 = 0;
    3 ]1 F2 V/ S6 [
  53.         P1M1 = 0;
    5 E3 v% @  U' N
  54.         P1= 0xFF;
    + f7 Y; _' T& a* }. o* n2 L6 C) N
  55.         P5M0 = 0;1 g( |, q/ t  v6 C3 l7 v3 e+ I+ S
  56.         P5M1 = 0;
    . n* t4 K5 m- T$ ^) m: f
  57.         P5= 0xFF;# N' a6 v7 X2 S
  58.         // P3口初始化为准双向
    / l! h# p- ~/ u
  59.         P3M0 = 0;
    % Y$ K# N- L) s7 A/ [0 a5 S
  60.         P3M1 = 0;
    ; g# O  i3 B4 x$ M8 `( F6 j
  61.         P3 = 0xFF;
    * q' Z2 x8 o2 C& u# ^
  62. }; s/ s9 {, m5 R4 m+ M" x

  63. * k: Q1 v, N& ^% A' w! l: [
  64. static void Interrupt_Init(){6 O: Y' u: S: v; N, Z$ v" l
  65.         // INT0中断(CLK)触发类型为上升沿+下降沿
    * j0 x/ P# c0 k$ [1 k
  66.         IT0 = 0;
    " g' d$ C, c, @
  67.         // 允许INT0中断
    2 w0 [, z; E! J8 ]% i7 Z/ k
  68.         EX0 = 1;6 K3 w. \7 \5 Q( S1 a
  69.         // INT1中断(LATCH)触发类型为上升沿+下降沿
    ' x8 A: G; O* f5 v# O
  70.         IT1 = 0;/ H4 j4 D+ n0 ^3 c: J
  71.         // 允许INT1中断2 u" A. V6 T! `$ e
  72.         EX1 = 1;4 X, _; A& K. m7 J; z4 q4 x, b
  73.         // 开启全局中断
    8 \* T! a- v" J% P9 \) R/ j& U
  74.         EA = 1;
    $ d% A! X! X# T) G+ W9 X6 ]
  75. }5 `& g5 U# Q2 C  W% X
  76. ) e5 S1 c- ], O) f
  77. static void INT0_Isr() interrupt 0{8 E( t9 Z- k8 \: b& Q* _
  78.         // 只有已经成功锁存才允许CLK移位7 ~+ }# o: z, U* s5 z
  79.         if(isReady == 0)2 a, Q) B. [& `) H4 m. C0 S
  80.                 return;
    8 O* g/ R+ Y0 @# _
  81.         // 读当前引脚电平,如果是低电平则说明是下降沿,此时直接忽略该中断
    3 V6 n& O9 u  t) G  N$ N; Q
  82.         if(CLK == 0)/ l( R6 q' B. D8 M2 l8 g! h
  83.                 return;
    / {2 M; o$ O; Y: Z, ?
  84.         // CLK上升沿到来的时候,取锁存值的下一位输出: \2 ?' R' ~! g* {' }$ t, R
  85.         idx++;
    " s9 U2 p# e! h* s% ]
  86.         DATA = key & mask[idx];
    5 `) F" N4 K( c# u  E0 G; V$ Z1 h
  87.         // 如果已经完成7次移位,则一轮读取完成4 U7 e- L1 A' E6 H2 Q: n# Q
  88.         if(idx >= 7); B# q* h! O; b3 U. Q  R" u- U1 @
  89.                 isReady = 0;2 A1 }' @; H8 \6 o8 ^
  90. }$ S8 r5 b% m# A. _" [

  91. 2 h7 Q; c$ n, W, B* B# W) M. p8 _
  92. static void INT1_Isr() interrupt 2{% F& C$ V) Z6 b6 w$ d3 \. E4 M6 _) Z
  93.         // 读当前引脚电平,如果是低电平则说明是下降沿,此时直接忽略该中断) L' @2 u/ `$ H) s: R
  94.         if(LATCH == 0)7 R' B: n4 E* G# ]: F
  95.                 return;
    & y' ~  i3 i0 M2 @+ [; t
  96.         // 当LATCH上升沿到来的时候,锁存所有按键状态,同时把键值A输出到DATA
    / N- Z. O9 A+ U
  97.         key = bufReady;3 C! O( A7 T& w$ ~0 R, ~) u3 w
  98.         DATA = key & 0x80;//mask[0];        // 为了加速运算,直接取表中的值而不是读表
    2 }3 S7 F1 p5 \& G
  99.         idx = 0;
    - j& j* R" ?0 l+ d& G) D2 o! a& R' h
  100.         // 允许CLK进行移位
    ' x* u; Y  Q3 b6 J% p- n
  101.         isReady = 1;
    ; E1 }/ g( S4 Y8 l: I3 A. ?
  102. }
    2 W- Q  b7 k; e0 v8 |. }9 D
  103. ( n' d& O! a( m* c- L* j
  104. void main(){
    8 C% Y0 s! T% O! s! o! y8 q" A
  105.         GPIO_Init();2 n+ _, x) w, ?0 {6 b. ?0 z; ?
  106.         Interrupt_Init();
      f$ S  D1 d* s+ `$ J) F; f3 o
  107.        
    : [' E# K+ P, L9 X
  108.         while(1){
    & `/ Z, a( j' Z( K0 z  ]1 o
  109.                 //PCON |= 0x01;        // 进入省电模式
    " b' \7 I. [4 _1 Y6 e( A
  110.                 //_nop_();* X7 d7 j$ H& H% ^+ N' O: r+ u
  111.                 //_nop_();) b' Q2 q) m. T; p! v7 E8 f
  112.                 //_nop_();
    ! B* H: X* t7 M3 `
  113.                 //_nop_();! ]' u# y7 `/ T
  114.                 buf = ~((P1 & 0x3F) | ((P5 << 2) & 0xC0));1 S8 {" n3 R4 @4 `6 y4 H
  115.                 bufReady = buf;" s- k, `' q6 h# X3 E
  116.         }' [. c' ]: g7 F4 E" o5 J
  117. }$ a8 L5 N6 s, K
复制代码
% \( u7 l; Z- E
硬件参数配置无特殊要求,晶振频率选择12M即可。# ], b/ E" n* n. e7 ]

( i0 c* \4 J: ]. ?0 E8 z  @1 g  m这是编译好的固件。

本帖子中包含更多资源

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

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& U7 t& h2 G6 Q1 k, o
不错的设计,想问一下楼主,FC的15针公头怎么解决?普通的公头太短了,插不进去FC的扩展接口。 ...

/ v' t* r7 f* r7 w, J5 d# T坛友的改造方案
回复

使用道具 举报

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

使用道具 举报

发表于 2019-5-25 12:07:18 | 显示全部楼层
精彩,楼主动手强,也写得很详细。& s# ]9 f4 i9 j  E$ K+ S/ r- f
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
7 x. u# b  J. J. G精彩,楼主动手强,也写得很详细。
& F1 ~6 z0 V: j" n7 a5 h2.4G方案是目前无线的最低延迟吗?
4 h: _$ @! S% v# q
我没用过其他无线手柄,所以实在不知道我自己做的这个手柄到底是不是最低延迟。
' C( A8 V, x& @0 p7 w- P; o不过根据网上的说法,延迟高低主要是由通信协议的复杂程度,以及数据传输速率决定的。这个模块虽然是2.4G无线模块,但由于协议很简单,所以延迟比较低。
& R+ ^' P8 y# r+ O( Z我用这个手柄玩一些ACT游戏,比如超级马里奥、忍者龙剑传、热血系列,完全感觉不到延迟,和游戏机自带的手柄没有任何区别。唯一的区别就是这个手柄是用火花山寨手柄改造的,外壳是垃圾回收塑料,粗糙+脆弱,导电橡胶弹性不佳,手感不是一般的差。
) s0 X& _9 o! i: [( Z& [' _. u我手里还有十几张板子,等我有空了我再做一套,到时候买一个好一点的手柄改造。
回复

使用道具 举报

 楼主| 发表于 2019-5-29 16:56:14 | 显示全部楼层
ppad 发表于 2019-5-28 17:27
4 [( N3 ?. E8 o  x: E+ d给技术帝赞一个,有半成品发布吗,自己焊接改造就可以,编程实在不会啊 ...
" p" b. K1 Q! t4 Q8 k  \- C
很可惜,我手里没有多余的单片机了,LDO也找不到了,锂电池以及充电模块更是没有了。反正就是该用到的元件基本都没了,所以没法发布半成品。' E3 A# o4 X3 w+ \( B% q
两个板子倒是有十几张剩余。5 B1 }! ^9 J0 ]) ?. A7 O
你要是有USB转TTL串口板,完全可以自己买这两种单片机,然后我给你编译好的固件,你自己用串口板下载到单片机里面就行了。两个2.4G无线模块也得通过串口板用AT命令设置参数,不过好在我在设计电路的时候就已经预留好了串口,可以直接在线下载和在线设置参数。总的来说并不麻烦。
回复

使用道具 举报

 楼主| 发表于 2019-5-29 17:00:34 | 显示全部楼层
孙大师 发表于 2019-5-28 18:550 m& `% S) ~' y3 D
非常好,楼主是技术帝,到目前我都还没开发fc的无线套件,等空了,开发一套套件,等玩家自己组装。 ...

% b) }( U! i8 r能得到孙大师的赞誉,不胜荣幸!
' g7 J8 s* C. s" l不如开发一个多功能手柄,比如用SFC手柄改造,L/R键配合其他组合键可以用来切换2P~4P、调节连发速度、软重启等各种功能。接收端插到15PIN扩展口。
回复

使用道具 举报

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

本版积分规则

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

GMT+8, 2024-3-29 20:09 , Processed in 0.061516 second(s), 14 queries .

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

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