找回密码
 注册

QQ登录

只需一步,快速开始

查看: 24845|回复: 32

自制FC无线手柄

  [复制链接]
发表于 2019-5-22 14:16:45 | 显示全部楼层 |阅读模式
本帖最后由 雷精灵2046 于 2019-6-14 09:28 编辑
+ w9 P9 R- K0 X  a4 Y" ?) X
1 \# r# Y, r. [; N; W( {没有用复杂的分立元件搭建发射接收电路,直接用的现成的2.4G无线模块jdy-40。, e4 H% |7 x. F! [

' u# d6 T3 \5 V. c1 G* i' f
: ^$ q& ?/ R2 O8 j发射端靠3.7V锂电池供电,用了一片SOP8封装的STC单片机,负责产生连发脉冲,同时负责检测电池电量,电压低于3V左右的时候触发低压中断,低压指示LED就会亮起来告知该充电了。平时发射模块和单片机均处于睡眠状态,有按键按下才会唤醒,从而实现省电。实测睡眠状态下整机电流约1~2uA。板子洗了一下稍微干净了一点。因为对于微功耗设备来说,焊接残余的助焊剂可能会增加漏电流。$ S9 R9 k  Q3 x) X* r% N5 @7 q

$ O6 T8 k" d/ H' u. S5 n+ a! v; F买了一个火花的FC山寨手柄,去掉里面的牛屎板子,并修正一下塑料挡板,把锂电池和充电模块装进去。
( P$ D8 @& v  W  I9 z8 \3 S4 r2 s为了减少体积,充电模块裁剪得十分小,并且更换了充电电阻使之适应这个小小的锂电池。这么小容量的电池,也不需要多么大的充电电流是吧?3 @/ `* I; i! G  ?
然后统统用热熔胶粘上。充电电流比较小,所以发热很少,不会熔化热熔胶。
& b! T* }! C  x9 ~6 v$ Q2 H; C2 F! [: w& ]+ `' R' @9 ]( b
' y4 `9 N. g- a. y

) x1 C8 G* h$ E$ j最后把按键、导电橡胶和电路板装上去。" n' I! Z6 P4 y6 e$ E3 p& @1 z
精心裁剪了电路板,正好扣上,不会阻碍其他元件,也不会影响后盖和拧螺丝。3 Z. x5 x$ ~7 |  M  w
4 c/ S& O, S& J- c# ?( P% N
# @1 @( F) k1 l8 Z
完工!
( N% O( {, S# _
& Z* z- f5 x# V+ V( T; @: a) N
+ ]  T) g( u3 K3 w这是充电的MicroUSB插座。旁边的小孔用于透出低压报警LED的光线。; i4 F% p. W8 j! T
: W- N& Q! p) U$ M# }
7 E" G" p: E- w3 e1 \
接收端用一片DIP16封装的STC单片机模拟CD4021。为啥要用单片机模拟而不是直接用CD4021?因为jdy-40模块接收端在有按键按下的时候输出高电平,无按键按下输出低电平,和普通手柄正好相反。当然我也可以用两片74HC00或者74HC04之类的逻辑门进行反相,但那就增加了芯片的数量。对于FC手柄这种工作频率并不高的设备来说,STC单片机完全可以胜任模拟工作。
* H, J% i/ O5 l) q" {
1 D; S. H, T6 w/ Z
& _- A6 x- N  {/ ]( H  o, N3 ^' @; n* r( S
电路设计有点小小的错误,所以有几根飞线。原本设计使用低压差LDO是XC6206,结果在做这个接收模块的时候,买的LDO居然找不到了!无奈只好用了AMS1117。幸好对于接收模块来说是5V降到3.3V,1117可以胜任。要是发射端手柄的话,3.7V降到3.3V,那就非得用6206不可了。. [/ {; N) F1 c0 q
& m6 v4 M) L0 d8 N
实测十分灵敏,延迟极小几乎感觉不出来。可惜这山寨手柄的手感并不佳,尤其是方向键,软塌塌的。看来我得买个剪线手柄改装。: P/ i) ^9 a, V  X2 h5 T# _* R
5 D& w, O4 n4 l
这是电路图,有兴趣的朋友可以参考。9 `# z/ M$ H! _: z( N0 c2 X

1 _8 z6 y4 f9 ]# f8 u9 F4 s- e. V9 s
# A. v- W6 r. j9 r6 _. U1 m2 N我信奉开源主义,十分痛恨把技术藏着掖着。好东西大家分享嘛!所以两个单片机的源代码大公开!
: m8 C" C3 Z* I% r9 Z编译器:Keil 51。
5 s7 I1 }& U: k5 S1 H$ W6 \. M" P
, A9 Q* p5 H5 O发射端:
2 H* w" q8 s5 W; O
  1. #include <INTRINS.H>
    % J9 w+ P0 d  H* ^" P
  2. #include "STC15W.h"
    6 c8 N& Q5 J0 l& O
  3. % p: n) y* x$ ~& S% K& ]2 U
  4. ' n" h6 S9 V, d8 m% x4 v2 h
  5. /*
    2 x) t. k6 [9 J! r" ]- G* z* m
  6. --------------------------
    / F$ |$ i, b/ h( Q9 I$ k
  7. |1 (OUT)        \__/   (INT1) 8|& q  q$ |) {/ `2 `, ]4 o: u/ `
  8. |                                                   |: M6 v" ~  s! h: b
  9. |2 (VCC)                   (INT0) 7|
    ' D7 @/ S) i  L( i. m
  10. |                 STC15W204S                   |
    + ]2 u# `5 t1 ^! q9 w  D2 {: k
  11. |3 (LED)                         (TXD) 6|
    + G* o0 u; T2 b: {
  12. |                                                   |
    $ c( ^& u( C/ Z
  13. |4 (GND)                         (RXD) 5|$ Z  X% ~, T+ t- ?
  14. --------------------------
    " h- C2 w( \7 S, \

  15. ! Q( [* j+ }. `0 Q
  16. LED ---|<|---[===]--- VCC
    9 j0 S9 Z8 g! y/ c
  17.            Red          330
    / b3 y& P9 w1 U; o8 A
  18. 1 i) o! X, a' `: l6 ~2 s) P
  19. Fosc = 6MHz! u+ O; x; y+ E
  20. */, N: A  B7 X' g7 {" }& Z, H
  21. ( N7 E- m' w1 C
  22. 3 [% }2 \5 _* h$ b  l
  23. // 矩形波输出脚
    9 f' x: Y( X* w  e
  24. sbit OUT = P5^4;
    2 j6 W; l; g- [) z' l* T
  25. // 低压指示灯引脚
    8 G! ?4 u/ k( n0 O
  26. sbit LED = P5^5;
    : V: O3 J, P8 ~! j6 M/ |
  27. " E; j* G8 D. ~1 k( D
  28. // 停机标志位
    9 a! j4 g' w" e* L1 I$ G
  29. bit isReadyToHalt = 0;
    " l# l$ K! ~9 ]6 D& b+ Z
  30. 8 N+ m' Q+ a; M& z4 t! ~" c
  31. // 矩形波次数累计
      b% K1 B! V  [, `& G$ j
  32. static volatile unsigned char count = 0;
    8 C* a# ~$ K. s2 |" o( R* K
  33. & l4 l* d- a+ Z& y( ?& t! X8 j' ~& Z) o
  34. " Q' k! ~* f& E4 Z
  35. static void GPIO_Init(){3 X8 n3 }9 m  e- T5 U$ m- ~
  36.         // P3口设置为准双向,默认靠内部弱上拉输出高电平( }$ h, r) \; A; g! K
  37.         P3M0 = 0;
    8 \7 a6 f* M$ x$ H8 h
  38.         P3M1 = 0;
    ) @: |. ^# R+ v
  39.         P3 = 0xFF;$ B) l& n7 k8 H$ P
  40.         // P5口设置为准双向,默认靠内部弱上拉输出高电平
    % @8 n. o3 l, _- ~* }6 R/ F3 ]" n
  41.         P5M0 = 0;
      h/ j5 G9 j  Q# {/ w* u, d
  42.         P5M1 = 0;" C- u! ]' K9 X
  43.         P5 = 0xFF;: C9 w8 J# H" l
  44. }
    . R2 }& N$ G: A" m8 n- d
  45. # x# G; C1 e8 z9 _# Z
  46. static void Timer0_Init(){( C0 b0 h( k; n' o7 ~
  47.         // 16毫秒@6.000MHz
    & t1 A6 G: H  ?8 m8 @( T/ J8 S
  48.         AUXR &= 0x7F;        // 定时器时钟12T模式8 V5 c+ N! N7 L
  49.         TMOD &= 0xF0;        // 设置定时器模式. V. ]' x5 {" J3 E9 z" g
  50.         TL0 = 0xC0;                // 设置定时初值& W2 ~. N" C' k6 M& w* S$ C3 o9 X
  51.         TH0 = 0xE0;                // 设置定时初值
    9 p, o5 i) ]+ m! V% ^
  52.         TF0 = 0;                // 清除TF0标志7 N3 ~, I, F  C" K, Q
  53.         TR0 = 1;                // 定时器0开始计时
    / M$ N9 k# Y+ G- D5 }
  54. }
    ( ^& z6 Y3 x( ?" C  r" x  |7 s& A4 R
  55. 5 S5 b" m5 \7 J- E" F" H
  56. static void Interrupt_Init(){9 a+ ~6 {/ f$ z8 }% K
  57.         // INT0中断触发类型为下降沿触发
    ) }8 K# U( V1 l& E& I: s0 G
  58.         IT0 = 1;
    ) R, K" t, H/ X/ J% l' Q
  59.         // 允许INT0中断
    3 K' b1 }9 q3 M7 n; y. W8 n- w) e
  60.         EX0 = 1;
    3 B+ O6 h7 e2 @+ h- H, W
  61.         // INT1中断触发类型为下降沿触发
    8 P% K. u/ j# w/ m
  62.         IT1 = 1;5 j3 D! P9 @8 o
  63.         // 允许INT1中断
    : b' R) s7 [- R; X9 v
  64.         EX1 = 1;( S! g- G' D6 n0 R( V9 O
  65.         // 允许定时器0中断
    ( m$ Z; f! m) \6 E/ [; v( e
  66.         ET0 = 1;
    6 }' o" m- I& P% P6 S2 m
  67.         // 允许全局中断7 K/ X. ]/ z. K" d* q. b
  68.         EA = 1;+ _8 e7 b$ ?" |8 @0 [* |5 {
  69. }
    : i0 k* l+ [1 G/ a; n4 N9 g
  70.   A% ?1 K2 w5 v' [: e* V
  71. static void INT0_Isr() interrupt 0{" r! R9 R1 n+ ^# S# U
  72.         // 矩形波次数累计归零& e7 l/ C3 T7 n" ~$ T; \' B
  73.         count = 0;# X( R5 Q% C4 W7 _" O% F
  74.         // 重开定时器0中断
    , i% B- ~' V7 ]
  75.         ET0 = 1;6 o6 ^! ]2 G1 B, F9 v( D
  76. }
    1 \0 @: m* r6 F" O) b2 h; p

  77. $ e; j. q1 {5 D1 p0 P* H4 k* Z
  78. static void Timer0_Isr() interrupt 1{" M4 o/ v  a# M) r+ T
  79.         // 输出矩形波" p( ~8 ~$ J3 c* J  Q+ z+ A
  80.         OUT = ~OUT;
    . R) x0 I; a3 v8 T; D2 F# ^1 R- a
  81.         // 累计矩形波次数
    $ s- R- h3 Q* n- }5 u, E
  82.         count++;1 _) ~: L1 ?! x4 U0 ~! O  M
  83.         // 超过250个矩形波,准备停机+ i9 O: b4 ^$ \9 [# R
  84.         if(count > 250){  o( H7 v& k; ]: G4 ^& A
  85.                 count = 0;
    8 c* j. h1 c; i6 O' p
  86.                 isReadyToHalt = 1;! o0 |, W0 |' t2 Z
  87.         }! s0 |6 e5 H! r) B& s! o
  88. }0 M% R" Z+ ^5 P4 e/ [$ E
  89. , t/ e( k( o1 q# l# a
  90. static void INT1_Isr() interrupt 2{5 ]1 J4 S! N% m# h# n
  91.         // 矩形波次数累计归零; y5 r1 d3 U( Q6 f" c
  92.         count = 0;3 l/ z  i- C# n# Q! t
  93.         // 重开定时器0中断1 l7 l& ~" C- p9 w& n0 j" Y
  94.         ET0 = 1;
    ! V  _: G- S0 `. f
  95. }- o9 l: F& D+ e; p3 G
  96. $ ~; u+ _7 k/ L& f

  97. ; U  c" O; K# q5 G7 k
  98. void main(){
    5 |5 L9 p( \2 D; y
  99.         // 初始化P3和P5口% N% ?! f8 m4 p0 q+ E
  100.         GPIO_Init();: v. ?; [6 I1 ?: U4 Q+ P/ _9 T4 ^
  101.         // 初始化定时器07 n4 @: e. P& v4 k: A  q. Z
  102.         Timer0_Init();  h9 L) a2 d5 K( K8 `1 W7 u, S; o
  103.         // 初始化中断
    + a0 K. A& I# m* p# x
  104.         Interrupt_Init();
    & \" o$ k# o& Q' Z$ E, \3 f2 U
  105.        
    * g& r7 v% J- T' o; F$ w
  106.         while(1){+ O7 x, b4 L- l/ U
  107.                 // 检测电量
    0 `$ Z) |, Z3 q
  108.                 if(PCON & (1 << 5)){
    / @9 H1 t4 b4 i$ f9 D% D
  109.                         // 如果电量低,低压指示灯亮
    ( I' W* P- r. Q
  110.                         LED = 0;' o# t3 }8 [0 w% i& [6 X6 L$ V
  111.                         // 清电量检测硬件标志位
    ' x7 I3 n4 t. F4 c; ?
  112.                         PCON &= ~(1 << 5);
    $ Z" D5 l2 m" p+ A
  113.                 }else{
    3 A  m9 y9 ~9 g  z
  114.                         // 电量正常,低压指示灯灭
    7 c% T2 @, |. _; H! i6 x/ j. B
  115.                         LED = 1;
    6 y, Y: i0 b5 c; K+ i- X) m: c7 l+ Z
  116.                 }
    ; R9 i3 m) Q5 a3 X4 N; t3 x5 j: a) t
  117. ) B  W0 ^# e$ ?  n
  118.                 // 检测到停机标志/ d% ~+ Y! T6 D" u/ E# ^1 a
  119.                 if(isReadyToHalt == 1){, ?/ a# @& k9 |. u
  120.                         // 暂时关闭定时器0中断, U% }% Y& _$ ~! l" i
  121.                         ET0 = 0;7 g' K) H( Y6 [; p! W
  122.                         // 停机之前先把矩形波输出脚置低电平,以方便INT0和INT1唤醒CPU- {$ U( M1 v, f8 \' J1 |* g9 p
  123.                         OUT = 0;- j* p8 B8 ^" n& K- C* ]& @5 Q
  124.                         // 停机之前先把低压指示灯灭掉,以省电2 `) i. T& W2 p% O1 i5 l0 k" n
  125.                         LED = 1;
    5 k5 M0 \4 h" [! t$ ]  v
  126.                         // 进入停机模式, B  o2 r5 l2 s0 P
  127.                         PCON |= 0x02;
    9 y; u5 I5 U& R7 ~" C, b
  128.                         _nop_();4 g- ?5 N* N! A
  129.                         _nop_();+ k& K* N- O1 x# `  I
  130.                         _nop_();, \" ?* ]; q& q' x
  131.                         _nop_();
    ( ~, M# N4 l8 t; H0 M+ {
  132.                         // 唤醒,清标志位
    6 a* U9 O4 H. S7 |  \2 e
  133.                         isReadyToHalt = 0;
    - |4 e+ H: R/ J) u# U0 t2 n1 ^9 u
  134.                         // 重开定时器0中断" Y2 W) U7 T9 M
  135.                         ET0 = 1;6 M: H9 D" E+ B( c
  136.                 }
    ! h( f% Z1 {8 j3 |
  137.         }0 ^; M5 Y% C6 D. \5 H7 [0 O
  138. }
    7 \% e. }& |: p6 j8 T
复制代码
; i8 M- [' w: T. h9 r# G; q
硬件参数配置:0 `! Q; x8 I. h

2 r3 M( v4 A) R8 K5 U* Z6 A/ o) K! R6 R
接收端:! j. Z* F; ^5 x0 M
  1. #include <INTRINS.H>: R! [4 Y5 @/ k6 d% `0 R
  2. #include "STC15W.h"- h' ~. f) s! M$ ?3 N

  3. - M/ |$ V0 L. v# \4 K# ~" A' l4 b

  4. 1 u( U- o, p0 l$ }' ]
  5. /*3 {+ m" x! s' s7 d) z4 U" L

  6. 5 Q: C9 F7 b# E4 y1 {$ @
  7. *---------------------------*7 C4 T- P6 A: s" l
  8. |1 (GPIO2)         \__/  (GPIO1)16|
    ) x+ b: z* a; G2 }
  9. |                                                        |
    ; H& M  l; }1 P& P
  10. |2 (GPIO3)                   (GPIO0)15|/ W% h8 G4 o1 l$ w; F2 K8 V0 N& V
  11. |                                                        |* E+ l- j' ^$ z& R
  12. |3 (GPIO4)                                  14|
    * S! M  U, X8 I# \# j$ A$ d; E
  13. |                                                        |; G/ a+ e  u( {( Q5 ?7 M2 S, X
  14. |4 (GPIO5)                        (DATA)13|3 l& h3 x" m; W- \, C+ r$ ?# \1 _
  15. |                  STC15W204S                |
    4 b, |4 p4 Z0 Q5 Z  {) ~% l; s
  16. |5 (GPIO6)                   (LATCH)12|
    ' {3 x! ]5 h, z" j9 L
  17. |                                                        |
    ( k4 D( H% n6 B5 c# E
  18. |6 (VCC)                         (CLK)11|+ t. D- _$ x% r# X+ |& b
  19. |                                                          |
    ' f" `0 W7 _5 F$ s# ^8 W
  20. |7 (GPIO7)                         (TXD)10|2 @9 C) p+ R8 A4 S0 Q, c
  21. |                                                        |
    ; K* j. x' ]4 T9 m# V
  22. |8 (GND)                         (RXD) 9|
    9 ^- `) L/ C2 I  o: N. T0 h
  23. *---------------------------*
    % W' T' n2 [# `- z, S2 n/ Z
  24. Fosc = 12MHz
    9 v% U6 C3 |7 d  G

  25. & P* G- c' ~3 u( ^
  26. P1.0 -> 上1 _" v: {6 f  D; H7 c( L7 y  J
  27. P1.1 -> 左
    + [- K# N$ L# B* m2 j$ ^9 [1 b
  28. P1.2 -> 下
    1 R# V% A, N5 d  D, e7 I
  29. P1.3 -> 右( P# F3 I* w5 R0 p7 w
  30. P1.4 -> SEL
    " H1 u) V  A0 Z% ~
  31. P1.5 -> STA
    1 @( k! m1 ~2 l! g0 ?7 }
  32. P5.4 -> B! o1 m" y: l( X) V+ s! v
  33. P5.5 -> A
    . M( Q) K9 G% e& U; C

  34. 2 o1 M, S" g* Q7 @6 D  @$ ~# e
  35. */; C$ [- v* F0 J7 E

  36. & ^4 s& m/ J; b% E8 q) d+ ~# ~' H
  37. ! {7 F0 `* z& y2 ^  B
  38. sbit CLK        = P3^2;3 r! L# O9 d/ ?5 U3 C+ }# L' W
  39. sbit LATCH        = P3^3;
    4 t8 W8 e2 |! g
  40. sbit DATA        = P3^6;
    3 ~7 q1 L9 W5 G& V; V% l6 i
  41. 0 o' L8 A, f% c( Z. l# _% O' S
  42. bit isReady = 0;
    . T; B. W0 m9 M7 `3 I" c
  43. static unsigned char key = 0;3 I- b! g9 e" a8 g; [8 p
  44. static unsigned char buf = 0;        // 双缓冲。这个缓冲区保存从P1和P5组合而来的键值
    7 u7 h- p! \, [; m# {3 H$ Y7 V
  45. static unsigned char bufReady = 0;        // 双缓冲。这个缓冲区保存上面那个缓冲区的备份
      w9 x1 Z, Z. t% Z" W, 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中* S2 H7 Q; e8 p, Y1 B3 a+ R$ q
  47. static unsigned char idx = 0;
    ( g2 b# V* ^7 w; T% E

  48. # v5 V+ o" D+ s' U1 u
  49.   M7 t4 M( ~! X4 r+ |! a; ~
  50. static void GPIO_Init(){4 o' C, Z0 k; y
  51.         // P1口和P5口用于接收并行信号,全部初始化为准双向,依靠内部弱上拉输出高电平5 B, \3 J7 z2 t4 V0 Z
  52.         P1M0 = 0;, ~! b( m, X. n" V
  53.         P1M1 = 0;
    2 a$ s# q2 t; a. J
  54.         P1= 0xFF;: f' b  M' o5 e# h- M* t5 A  n
  55.         P5M0 = 0;' K5 ]- C$ Z$ y, d# a3 `
  56.         P5M1 = 0;
    & O+ j7 q( Z" F/ a- s
  57.         P5= 0xFF;9 C& o% D- h2 ]2 D
  58.         // P3口初始化为准双向
    . L( ]9 K! l+ t( F0 Q  \
  59.         P3M0 = 0;
    ) {7 o0 E+ t( s: i8 a  W) h  e
  60.         P3M1 = 0;
    : z0 X! r$ Q& R4 j; }
  61.         P3 = 0xFF;4 I4 p  _. q3 G
  62. }; v5 s4 E8 F/ g8 ]3 A- |9 m& u

  63. 6 B) F  j3 Q* W! o4 W
  64. static void Interrupt_Init(){" I; n7 j- c- N, Y5 Z
  65.         // INT0中断(CLK)触发类型为上升沿+下降沿
    ; U; w' J; _9 V6 ~
  66.         IT0 = 0;' y  }7 m* ?0 C& t
  67.         // 允许INT0中断: [0 S9 X' t. S& \& [( p/ q
  68.         EX0 = 1;
    ' |( W# O0 j( \7 w
  69.         // INT1中断(LATCH)触发类型为上升沿+下降沿
    & J8 K; r3 X) e9 j6 Y+ L' \* C
  70.         IT1 = 0;
    0 A. k7 J" k& g# w9 {
  71.         // 允许INT1中断" G  C4 u+ k+ o9 p
  72.         EX1 = 1;
    ) t# d. K+ K! ?; H
  73.         // 开启全局中断
      H1 U, |9 u- d  p  d
  74.         EA = 1;4 K1 ~# F. H7 _  o% b( b
  75. }
    " ^2 X; ^5 {& k$ ~
  76. ! o; ?$ d' a, _1 t# u
  77. static void INT0_Isr() interrupt 0{
    ' Z" }/ l$ Y' J3 Z2 R3 u
  78.         // 只有已经成功锁存才允许CLK移位
    ( f$ G5 \1 h/ H7 N
  79.         if(isReady == 0)
    ) _, {$ A% M- X/ q0 _, z3 g
  80.                 return;
    8 \9 k7 n$ E( s- k) q
  81.         // 读当前引脚电平,如果是低电平则说明是下降沿,此时直接忽略该中断
    $ E: Z% m( j: w) |& H
  82.         if(CLK == 0)
    ; B8 p/ A+ d- v9 D7 [. F
  83.                 return;1 q% R. u0 V) |
  84.         // CLK上升沿到来的时候,取锁存值的下一位输出
    $ a7 y3 I. y2 N, A
  85.         idx++;; I# W1 W1 d, ]6 q
  86.         DATA = key & mask[idx];
    , i% T0 {- _2 f2 v
  87.         // 如果已经完成7次移位,则一轮读取完成' D5 G9 C, O  j( }5 }
  88.         if(idx >= 7)- c7 _+ r4 Y' B3 Z
  89.                 isReady = 0;1 x6 i" I+ n; T4 o
  90. }1 b/ q! B' y: j( ~# q/ |
  91. # J! P( U6 C6 v) Y; @+ S& D
  92. static void INT1_Isr() interrupt 2{
    & s, q1 \1 ~1 a2 k/ V/ v1 i
  93.         // 读当前引脚电平,如果是低电平则说明是下降沿,此时直接忽略该中断
      H5 Q" r  Y: O8 L. D. C) ]
  94.         if(LATCH == 0)
    1 l% l! R' F  o, F
  95.                 return;6 i+ M% K' c: P6 G
  96.         // 当LATCH上升沿到来的时候,锁存所有按键状态,同时把键值A输出到DATA
    / `; i& b/ r8 j6 j& C, t
  97.         key = bufReady;
    $ o" V4 V* ^7 `
  98.         DATA = key & 0x80;//mask[0];        // 为了加速运算,直接取表中的值而不是读表
    ) ?) C1 s3 e3 ~3 w. U
  99.         idx = 0;  U* d) Q# c& O7 R
  100.         // 允许CLK进行移位8 g# ]+ M+ X" B
  101.         isReady = 1;
    # I% K; K& ~' a) K
  102. }; j8 T, y0 A0 x3 d; g) A  X  j

  103. 7 p% i) y5 l6 m( _% O# v; K' Y; p
  104. void main(){
    0 v9 ^$ b  Y% a  K8 e
  105.         GPIO_Init();" C& A0 H2 {& P
  106.         Interrupt_Init();
    3 ^, x- V$ o% f0 s
  107.        
    . W: f$ r' W/ s" w; Y' ?
  108.         while(1){
    % N" W% x$ Q( P1 k
  109.                 //PCON |= 0x01;        // 进入省电模式. ?: |7 H: Y% `  x0 j% j, J
  110.                 //_nop_();
    + E# S! s/ H. |' j" J
  111.                 //_nop_();: c: ~1 n! a* e
  112.                 //_nop_();
    % `- @- Z# E0 `0 E1 f! d. h/ |
  113.                 //_nop_();
    + l# Q) V" _  Z; u& I
  114.                 buf = ~((P1 & 0x3F) | ((P5 << 2) & 0xC0));, f4 [1 m2 O( r$ a% _
  115.                 bufReady = buf;5 O) l; ]3 K% M, i0 C
  116.         }
    9 i( y  V5 n4 x, a! l: B
  117. }0 m" ]4 y% a6 v* @' S. \( k
复制代码
4 g: X% U6 s& t- K6 N; e5 X
硬件参数配置无特殊要求,晶振频率选择12M即可。
6 ?9 `0 T9 Y# ~, C" U/ w& e; L0 g, x/ t. \3 v( _2 t
这是编译好的固件。

本帖子中包含更多资源

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

×

评分

参与人数 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; c$ R  w  K/ }. V5 ^: i5 d9 Z
不错的设计,想问一下楼主,FC的15针公头怎么解决?普通的公头太短了,插不进去FC的扩展接口。 ...

3 y( w3 r: [, f9 G& A% Y& Y坛友的改造方案
回复

使用道具 举报

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

使用道具 举报

发表于 2019-5-25 12:07:18 | 显示全部楼层
精彩,楼主动手强,也写得很详细。' y! g$ q0 c' T, s/ z& D" R
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
9 ?' v5 Y- ~. D4 O7 c精彩,楼主动手强,也写得很详细。' t- f% L  N$ y
2.4G方案是目前无线的最低延迟吗?

: R7 E: U, [( T6 J# g( d0 M9 o我没用过其他无线手柄,所以实在不知道我自己做的这个手柄到底是不是最低延迟。
2 ~; S) n, {/ U& Z9 q不过根据网上的说法,延迟高低主要是由通信协议的复杂程度,以及数据传输速率决定的。这个模块虽然是2.4G无线模块,但由于协议很简单,所以延迟比较低。8 a" t, o8 N* V/ h+ \5 x
我用这个手柄玩一些ACT游戏,比如超级马里奥、忍者龙剑传、热血系列,完全感觉不到延迟,和游戏机自带的手柄没有任何区别。唯一的区别就是这个手柄是用火花山寨手柄改造的,外壳是垃圾回收塑料,粗糙+脆弱,导电橡胶弹性不佳,手感不是一般的差。
# J' ?6 y. r( n. o" q* y我手里还有十几张板子,等我有空了我再做一套,到时候买一个好一点的手柄改造。
回复

使用道具 举报

 楼主| 发表于 2019-5-29 16:56:14 | 显示全部楼层
ppad 发表于 2019-5-28 17:27: Z" I4 i# Q0 }+ e) T' E* h4 p
给技术帝赞一个,有半成品发布吗,自己焊接改造就可以,编程实在不会啊 ...

# q* A' k) _! S) ]1 \4 w很可惜,我手里没有多余的单片机了,LDO也找不到了,锂电池以及充电模块更是没有了。反正就是该用到的元件基本都没了,所以没法发布半成品。/ D& ^% h3 w  w0 _- H* o
两个板子倒是有十几张剩余。3 f' }+ x) F4 [
你要是有USB转TTL串口板,完全可以自己买这两种单片机,然后我给你编译好的固件,你自己用串口板下载到单片机里面就行了。两个2.4G无线模块也得通过串口板用AT命令设置参数,不过好在我在设计电路的时候就已经预留好了串口,可以直接在线下载和在线设置参数。总的来说并不麻烦。
回复

使用道具 举报

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

  h3 S$ v& M6 g1 O- J7 S能得到孙大师的赞誉,不胜荣幸!
! r# q% p& L+ p6 B' r1 t/ ~% ]不如开发一个多功能手柄,比如用SFC手柄改造,L/R键配合其他组合键可以用来切换2P~4P、调节连发速度、软重启等各种功能。接收端插到15PIN扩展口。
回复

使用道具 举报

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

本版积分规则

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

GMT+8, 2026-5-6 16:25 , Processed in 0.109340 second(s), 14 queries .

Powered by Discuz! X3.5

© 2001-2025 Discuz! Team.

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