找回密码
 注册

QQ登录

只需一步,快速开始

查看: 24333|回复: 32

自制FC无线手柄

  [复制链接]
发表于 2019-5-22 14:16:45 | 显示全部楼层 |阅读模式
本帖最后由 雷精灵2046 于 2019-6-14 09:28 编辑
  O! L: y0 c6 h* x& L9 M2 M0 e7 Y3 g# u3 e! j. p1 p- c4 y1 f
没有用复杂的分立元件搭建发射接收电路,直接用的现成的2.4G无线模块jdy-40。* M, `6 ~% F0 s6 m: ^) C  P$ r( ^

! A$ L* R# f6 ~' \8 d) o( B7 b; p3 W9 Z9 D( o( D' _
发射端靠3.7V锂电池供电,用了一片SOP8封装的STC单片机,负责产生连发脉冲,同时负责检测电池电量,电压低于3V左右的时候触发低压中断,低压指示LED就会亮起来告知该充电了。平时发射模块和单片机均处于睡眠状态,有按键按下才会唤醒,从而实现省电。实测睡眠状态下整机电流约1~2uA。板子洗了一下稍微干净了一点。因为对于微功耗设备来说,焊接残余的助焊剂可能会增加漏电流。+ d, @* U, B- O) Y

) U& A* j0 d9 S; |买了一个火花的FC山寨手柄,去掉里面的牛屎板子,并修正一下塑料挡板,把锂电池和充电模块装进去。* @  I& S: q0 [/ G* j
为了减少体积,充电模块裁剪得十分小,并且更换了充电电阻使之适应这个小小的锂电池。这么小容量的电池,也不需要多么大的充电电流是吧?
. \5 T/ Q1 t% m: [" W然后统统用热熔胶粘上。充电电流比较小,所以发热很少,不会熔化热熔胶。- _7 D. m: X) N1 |$ y
7 S0 s, K: P1 h& t# n; O( \; k/ Q: g' q

! G$ g0 @- @) V% J5 w: J
3 i) y8 {# r, j. h* h4 U5 w/ \$ q8 J最后把按键、导电橡胶和电路板装上去。1 j6 P: P- E' I& _3 K9 O
精心裁剪了电路板,正好扣上,不会阻碍其他元件,也不会影响后盖和拧螺丝。
8 j1 e: }6 L5 x3 N
& i" N" f: \# R: }! t2 L- M
( x; }% j. _; z# F7 o  H1 C! G! O' M完工!
/ B& W7 ^* B/ f1 X) A
+ }- p: F$ T: H* S, Q1 z
# {( S# ?5 `* S3 _4 Z这是充电的MicroUSB插座。旁边的小孔用于透出低压报警LED的光线。
" j* J! c2 `1 s
6 r9 P6 p+ ]+ J/ G9 _$ T0 o/ j9 `& M
4 x" @- D5 `. h  X" x+ n接收端用一片DIP16封装的STC单片机模拟CD4021。为啥要用单片机模拟而不是直接用CD4021?因为jdy-40模块接收端在有按键按下的时候输出高电平,无按键按下输出低电平,和普通手柄正好相反。当然我也可以用两片74HC00或者74HC04之类的逻辑门进行反相,但那就增加了芯片的数量。对于FC手柄这种工作频率并不高的设备来说,STC单片机完全可以胜任模拟工作。$ Y$ d. w1 _* ?+ R1 x. Q' B) L3 d
$ @7 b3 v+ d2 h+ \1 |
* O% p& w2 T8 m( g8 n4 X
: }0 Y( E- O, R! h& p! e. L3 H: S
电路设计有点小小的错误,所以有几根飞线。原本设计使用低压差LDO是XC6206,结果在做这个接收模块的时候,买的LDO居然找不到了!无奈只好用了AMS1117。幸好对于接收模块来说是5V降到3.3V,1117可以胜任。要是发射端手柄的话,3.7V降到3.3V,那就非得用6206不可了。2 ~: _# [$ _  L1 L! A4 ^

2 e& M8 k& g' g: {0 b9 \实测十分灵敏,延迟极小几乎感觉不出来。可惜这山寨手柄的手感并不佳,尤其是方向键,软塌塌的。看来我得买个剪线手柄改装。
& V* a' c9 X. J% ]* f) b4 _8 }7 J
这是电路图,有兴趣的朋友可以参考。
0 i) A  h8 B% j, t4 R. B
% i8 O1 D. Y: n
8 d; T. i5 f) X+ K) K我信奉开源主义,十分痛恨把技术藏着掖着。好东西大家分享嘛!所以两个单片机的源代码大公开!! Z& r3 J1 n9 j8 O. O" e. U
编译器:Keil 51。4 V& @0 X& G: q0 h+ B; e
+ }: X' }% z4 f9 g# ?7 N
发射端:) E* F3 f3 F0 L, d+ L8 i! ?
  1. #include <INTRINS.H>
    ! r4 x6 }$ q& o
  2. #include "STC15W.h") r* u9 ~1 _) r" p) u! k
  3. " `* k( w* t7 M' V, o+ O) F

  4. : q9 r6 }; q( S8 ~: d
  5. /*7 L% _3 o% e; |  C/ R- W8 x' _
  6. --------------------------
    . h: H9 J: v2 o
  7. |1 (OUT)        \__/   (INT1) 8|
    7 o7 e0 Q. I% f& i* J
  8. |                                                   |9 k# I* \/ y. Z0 v1 U! \& B
  9. |2 (VCC)                   (INT0) 7|* |7 c- [$ m5 N  |5 l* N9 q: s
  10. |                 STC15W204S                   |
    0 ~+ h* s  _) |& G5 m& p8 F7 C
  11. |3 (LED)                         (TXD) 6|
    9 q6 V+ N. {$ p9 R1 D
  12. |                                                   |7 f; X! F7 R+ E5 Y! R* o
  13. |4 (GND)                         (RXD) 5|& v  x& D9 ~5 u$ g# K2 c  n3 u2 H
  14. --------------------------
    8 m+ v2 `* J* G3 \

  15. " P6 C& l  X2 J
  16. LED ---|<|---[===]--- VCC! S+ f& c9 Z, m* l* O, K
  17.            Red          330
    : b( F% q5 X( R% f

  18. ; D; S) ]1 F- p+ V& |
  19. Fosc = 6MHz
    ! z3 y2 K7 g4 Q3 T8 _3 |2 q' P+ s
  20. */
    9 y' T/ ~7 k8 \4 a9 X# ?

  21. * f( J4 ]# m# l# t+ O4 t3 P. ?0 o
  22. 4 N) G& V! Y) }7 a+ x# G# j
  23. // 矩形波输出脚
    , l; v$ |" F6 `0 f' l
  24. sbit OUT = P5^4;% y+ o, L5 K% d. Y- [
  25. // 低压指示灯引脚
    ' C! C$ f" d8 v
  26. sbit LED = P5^5;
    5 X" t( c$ \: V0 I& L
  27. ; w3 g& h- t, x
  28. // 停机标志位* S6 b. C5 f1 k  I: i
  29. bit isReadyToHalt = 0;
    + O+ i. v9 ]' H0 H! G0 e; L
  30. 9 {6 a9 q4 p7 a8 t9 M3 b) \8 |
  31. // 矩形波次数累计7 H/ F+ i6 [) A# r- A8 \7 _
  32. static volatile unsigned char count = 0;
    7 e: F1 e) w( e, Y6 z

  33. ) Q8 r* p$ U5 `) F
  34. " s& C) j8 d: s8 ~5 e( n/ H
  35. static void GPIO_Init(){, h, U2 K; F6 m' U. ]' W
  36.         // P3口设置为准双向,默认靠内部弱上拉输出高电平  s+ \7 R$ K+ V
  37.         P3M0 = 0;
    0 S! s( L9 y$ ~7 Y
  38.         P3M1 = 0;* ~4 z4 u6 B1 j( z1 q# j
  39.         P3 = 0xFF;8 s4 R3 W6 F$ N
  40.         // P5口设置为准双向,默认靠内部弱上拉输出高电平
    $ a# X) R, j: g
  41.         P5M0 = 0;
    ! C& N- d, D$ V
  42.         P5M1 = 0;
    8 E. ~. w) ^1 z* k, q
  43.         P5 = 0xFF;9 Z* J. A. J1 @; `! J9 T0 {
  44. }, I- ?4 L6 B! ^% k0 @$ ~/ c5 ~+ Y
  45. 8 S& J. c7 Z. s; f: g
  46. static void Timer0_Init(){
    4 }  ?* g0 \6 A; t
  47.         // 16毫秒@6.000MHz
    ; o+ U2 g: x- ?2 q- i) q7 S
  48.         AUXR &= 0x7F;        // 定时器时钟12T模式% j) g5 W( F/ m0 B: x4 s
  49.         TMOD &= 0xF0;        // 设置定时器模式
    + N5 ?* ]  c* y: G9 ]
  50.         TL0 = 0xC0;                // 设置定时初值& ~* g7 f( F9 F" P
  51.         TH0 = 0xE0;                // 设置定时初值
    4 r" ^3 }7 E! K  H! f& U
  52.         TF0 = 0;                // 清除TF0标志# H6 f. c! S4 ?; ?' l$ t, G
  53.         TR0 = 1;                // 定时器0开始计时
    " Y. L6 J, O# c5 V/ {
  54. }9 P. E6 j3 z/ c5 O4 H2 G9 ]  C9 c; g7 q

  55. : p( S2 @( W0 ?% q
  56. static void Interrupt_Init(){
    8 G6 `; p/ v1 W
  57.         // INT0中断触发类型为下降沿触发
    ) W- m" S! a: H- q
  58.         IT0 = 1;
    ' e3 ^2 ]/ o" @
  59.         // 允许INT0中断* }' x$ `; A' q- x8 `
  60.         EX0 = 1;
    ; c/ g0 u3 G( W) z( e
  61.         // INT1中断触发类型为下降沿触发& Z1 X  p$ t6 Y9 U
  62.         IT1 = 1;
    9 X/ a2 R: @; C. `4 y4 d
  63.         // 允许INT1中断
    1 ]4 ?  D' h8 Y8 t3 j- A+ N6 ]
  64.         EX1 = 1;* j5 v0 R7 f+ R% h
  65.         // 允许定时器0中断
    . g- u: F, Q2 c; U+ S' K7 L
  66.         ET0 = 1;' r4 [) a% U8 B1 d# Y
  67.         // 允许全局中断
    8 e9 B4 j$ G, p% V0 d; F4 v
  68.         EA = 1;
    ; `/ H& a, s( I# {# p( k
  69. }
    # P5 Q! R* u. C% L$ Z
  70. % H4 \9 l- i6 Y& P6 p7 {2 q
  71. static void INT0_Isr() interrupt 0{, l9 [# E1 o$ ?1 s- S$ ^
  72.         // 矩形波次数累计归零# R# d, |; A4 v
  73.         count = 0;5 e) H6 @& p: L8 D& w
  74.         // 重开定时器0中断
    " ~$ ~, t! I' ?; i9 ^
  75.         ET0 = 1;
    + U) ]1 z9 z7 a6 y
  76. }
    5 f) W/ V7 c2 B

  77. 6 c4 P0 D0 Y6 O; f5 U
  78. static void Timer0_Isr() interrupt 1{' V+ L$ p7 q& e0 X% u: z
  79.         // 输出矩形波3 P6 Z2 \0 e2 M/ x8 }2 ]
  80.         OUT = ~OUT;4 B% W2 N! U% D/ \9 o
  81.         // 累计矩形波次数
    : o. n0 [& b. P' N1 Y/ l: e* t
  82.         count++;7 R5 z* p- ?* E! r' r: ?
  83.         // 超过250个矩形波,准备停机
    $ d$ A* y/ L" F# h" \2 ?/ K
  84.         if(count > 250){
    7 `8 z( H0 h3 v# F
  85.                 count = 0;
    ! w- A8 U' z* i+ k2 I
  86.                 isReadyToHalt = 1;
    . d6 ~/ M7 }4 R; n! J* P9 R
  87.         }0 H) I  u7 x( I' y
  88. }
      T# e2 f( `/ @# D( X, f% N, h

  89. ' D3 x& @2 N$ M% A- A% r1 {
  90. static void INT1_Isr() interrupt 2{" s$ f. a0 S0 X' u& h, x
  91.         // 矩形波次数累计归零' n6 v: i: ^2 L2 h+ Y
  92.         count = 0;* D* M; n; e1 p+ }: J2 f
  93.         // 重开定时器0中断
    + i( I. ^1 q  a9 j5 m$ w
  94.         ET0 = 1;3 E. D; p' ~% m6 p1 f2 S3 m
  95. }
    / H2 E  R! |7 U8 Q& i
  96. 1 \6 Y" B+ T8 M7 w9 M9 y1 D2 l

  97. 1 w  f4 d! u# E# ?" h
  98. void main(){) A- L- k6 L8 o9 i0 L
  99.         // 初始化P3和P5口$ A8 L$ r# U7 {) v( o$ U. b
  100.         GPIO_Init();9 z/ a+ A6 R: t) |1 B% l. f; P
  101.         // 初始化定时器0
    # o" X9 `4 B6 k* P  A
  102.         Timer0_Init();# ?! A6 ]/ Q  w4 Q) K3 Q- E
  103.         // 初始化中断
    : J) y9 A* H" X, O* I
  104.         Interrupt_Init();# K1 a/ i8 a0 Y% W9 c; g9 ?1 ]' A: }
  105.        
      f& @7 K! n$ p4 S' j& ^. h
  106.         while(1){
    ) m* L7 D; m$ ^/ f
  107.                 // 检测电量. B8 f6 K+ s7 h: ]! `3 X
  108.                 if(PCON & (1 << 5)){
    7 ?' }8 ]( @0 |$ I) H4 O' ]
  109.                         // 如果电量低,低压指示灯亮
    " Y- O/ j; r4 y
  110.                         LED = 0;" q( T- x2 ]* L0 Q; s
  111.                         // 清电量检测硬件标志位. k9 H% K. r/ P0 c
  112.                         PCON &= ~(1 << 5);! P0 r- B( c, g+ d
  113.                 }else{
    ( q/ _' I# t9 q0 A% p' b! G. Z
  114.                         // 电量正常,低压指示灯灭
    - H( e2 `6 \; z) k& R9 w2 v
  115.                         LED = 1;
    ! d. e. r, k9 r1 l; u4 w: R
  116.                 }0 ^% F5 m, T9 b
  117. & a! `/ h/ j  F. B1 E/ j8 ^
  118.                 // 检测到停机标志6 T7 H- m. N% y- S
  119.                 if(isReadyToHalt == 1){
    % g5 g1 J& _) s  D
  120.                         // 暂时关闭定时器0中断7 Y2 h/ P7 i% j5 T3 J
  121.                         ET0 = 0;! F, M0 L$ l) r% H
  122.                         // 停机之前先把矩形波输出脚置低电平,以方便INT0和INT1唤醒CPU
    : r+ q2 c/ q9 {  N4 t- e& M; a7 i4 f+ X
  123.                         OUT = 0;
    ; L2 W0 a% W- q; j5 m. O
  124.                         // 停机之前先把低压指示灯灭掉,以省电  e1 c2 R, q. I/ V! F
  125.                         LED = 1;  p6 N' Q4 S5 M, v% R$ W3 m4 U
  126.                         // 进入停机模式
    . s/ }; S6 N: l# _; }
  127.                         PCON |= 0x02;
    ( `. Q* R6 v! [6 Q9 `& f
  128.                         _nop_();
    8 F9 R# \3 r3 w& S! r$ g, C
  129.                         _nop_();
    2 }+ j- q/ t0 S4 |
  130.                         _nop_();1 N: a$ p4 F1 n) J! G' k3 [
  131.                         _nop_();
    6 q  \9 O/ A4 t# u2 y
  132.                         // 唤醒,清标志位
    , W$ f# j4 C5 i1 q2 [
  133.                         isReadyToHalt = 0;& d( W: c8 @3 H7 g; T
  134.                         // 重开定时器0中断9 B  i4 G, L- Y5 p2 [  ?" I
  135.                         ET0 = 1;
    5 n: r: L, b/ M1 A& M; J, v$ u
  136.                 }0 p5 w+ D( c- ^7 E
  137.         }2 Q' o) J+ V+ C
  138. }) b# p9 D$ }, K4 c' z9 @$ s
复制代码

1 M" x3 Y; a) m% t硬件参数配置:
5 d# G1 n# f! E) m- X: H3 G* `5 o4 r* ~$ O( m
' U2 g, W( o5 q. Y
接收端:; ]8 y' ~4 T6 W
  1. #include <INTRINS.H>: t8 X/ z) M7 E' _5 h
  2. #include "STC15W.h"  k( {% n+ t6 Y+ B4 ~

  3. ! _: m' b% j: P  R! _) W! R
  4. ( T7 A9 z2 W; `4 g/ \& i
  5. /*2 o/ x" x4 M& q1 J: T9 w
  6. 9 j# A, X; w. n6 A: g
  7. *---------------------------*
    * S, f, H9 [2 n1 J+ B6 m
  8. |1 (GPIO2)         \__/  (GPIO1)16|, D3 x* A+ S$ a0 P$ W
  9. |                                                        |6 Y8 t$ K& B* i6 w
  10. |2 (GPIO3)                   (GPIO0)15|
    6 D/ ?; [% L" T  m9 l8 p1 ~
  11. |                                                        |3 Z1 A- L0 K( ?, k! t1 @* g0 `
  12. |3 (GPIO4)                                  14|
    ! W3 Q! |/ h3 U. e9 g
  13. |                                                        |
    0 T, p3 u1 L* D) j
  14. |4 (GPIO5)                        (DATA)13|9 H; M8 E8 C7 K  W
  15. |                  STC15W204S                |6 s) \/ {% g% u) T3 R6 h
  16. |5 (GPIO6)                   (LATCH)12|; L( Q+ C1 [+ w+ X' h
  17. |                                                        |9 Q+ {$ i& V, X+ d: v
  18. |6 (VCC)                         (CLK)11|
    * I* u% R+ m# B8 Y
  19. |                                                          |
    * u. I6 |8 F4 D. d, i* [8 ]9 Y3 S  Z
  20. |7 (GPIO7)                         (TXD)10|+ I7 ^0 o$ m; Q5 \& ?: @+ e
  21. |                                                        |
    % p# s* E6 T; A# _3 \
  22. |8 (GND)                         (RXD) 9|
    - j! q/ [: ~; k
  23. *---------------------------*
    1 E4 m$ k! a- N3 v
  24. Fosc = 12MHz
      h# O) a; K4 t
  25. ) I* f' [& ?# K% t7 G" y
  26. P1.0 -> 上
    0 g7 m9 f) l/ |- }
  27. P1.1 -> 左3 i# y) g# P4 N4 y
  28. P1.2 -> 下
    ) c* h2 m. B$ x  O4 h
  29. P1.3 -> 右3 l- h; x2 w$ [; J9 y
  30. P1.4 -> SEL+ q! I* K: i, Y
  31. P1.5 -> STA
    ! z% c0 `* t1 Y8 {$ }. y
  32. P5.4 -> B  }: ~; [6 t8 u  `
  33. P5.5 -> A, R8 C- g* c1 j# k* G

  34. / o! A# [( b# A( w' W9 h
  35. */
    0 `% C+ G7 y( Z+ P, [4 F
  36. ; C2 K: p1 @( Q9 ]# `

  37. 3 ~0 O% P. X4 V7 U  C
  38. sbit CLK        = P3^2;
    2 D  h. c- k5 J. g9 y
  39. sbit LATCH        = P3^3;
    ( K1 b  j. J0 l6 i+ ?! y+ i( y# u- @
  40. sbit DATA        = P3^6;: ?& k0 q& S2 m# }7 h

  41. % X- `! Z1 w, J) b5 b: n" M
  42. bit isReady = 0;
    / J4 y: F/ Y/ K) ?( b
  43. static unsigned char key = 0;3 T  Q5 p9 T$ x1 K
  44. static unsigned char buf = 0;        // 双缓冲。这个缓冲区保存从P1和P5组合而来的键值
    ) v  i# G) H$ _9 a' ]
  45. static unsigned char bufReady = 0;        // 双缓冲。这个缓冲区保存上面那个缓冲区的备份
    . {: Y, s( S# H  `; {9 n
  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 P/ u8 C/ q8 P, l
  47. static unsigned char idx = 0;  M8 _$ m' S! b% g/ j

  48. & u, h: ~& n- d: P) j  i0 F  d
  49. " [& }' k! p2 B: L! w4 [: }% Q% y
  50. static void GPIO_Init(){6 W( V$ ?  ^& X5 x
  51.         // P1口和P5口用于接收并行信号,全部初始化为准双向,依靠内部弱上拉输出高电平
    ( U/ q8 K4 ~& I* Z" x6 g/ e, J
  52.         P1M0 = 0;3 _7 l& i  b7 h0 D% e* s7 R% g5 Z
  53.         P1M1 = 0;
    - z1 }. J6 Z5 j0 _' ]" ]2 _. J' N
  54.         P1= 0xFF;2 |! q+ i+ h& E; W) Q" v/ S
  55.         P5M0 = 0;
    8 z. q1 [, Q  X( S" ]7 f
  56.         P5M1 = 0;# x; v: z5 g" ?# d' y
  57.         P5= 0xFF;) K. U* |8 `1 }4 C, T
  58.         // P3口初始化为准双向$ a  @; T" k" l
  59.         P3M0 = 0;
    0 o, i$ s0 j- U. q
  60.         P3M1 = 0;0 c0 Q9 R# F. E+ T* t4 a) O
  61.         P3 = 0xFF;4 R5 a: C( O9 f" ?! q4 _
  62. }6 `/ f( Y  x& D) Z+ j7 U
  63. 3 g  D/ E  |" k( [  |( e/ C' P$ k. H
  64. static void Interrupt_Init(){
      E- M: }" ?( S
  65.         // INT0中断(CLK)触发类型为上升沿+下降沿
    0 c7 k: v: X" G) ~% F
  66.         IT0 = 0;
    # m, k9 W2 G8 I0 l- a
  67.         // 允许INT0中断2 ]( _1 `$ t& w( |( r8 R
  68.         EX0 = 1;
    % z" r& H1 j* [1 z+ D0 u  r6 [8 Y
  69.         // INT1中断(LATCH)触发类型为上升沿+下降沿
    ' ?: v8 y; O7 M3 X9 M4 y3 e
  70.         IT1 = 0;
    9 c* H5 [: S/ F& q9 G; ]
  71.         // 允许INT1中断
    : O. P! `3 d6 J% V
  72.         EX1 = 1;
    - t+ j; G: Y& h( _! x
  73.         // 开启全局中断
    ( @+ W+ ^: R) X) o
  74.         EA = 1;
    ; y& d7 t  J0 i8 j& S$ Q
  75. }
    6 c1 r1 s" g) J1 h
  76. 7 D! j$ G0 _$ w6 M! i. K
  77. static void INT0_Isr() interrupt 0{
    5 k) r/ X, S6 i6 j5 E' M! c' T8 k2 v: J
  78.         // 只有已经成功锁存才允许CLK移位) b' l  \# d0 l8 h+ s2 C
  79.         if(isReady == 0), c$ M3 r2 y5 {
  80.                 return;1 u! O/ Z- z) e. ?
  81.         // 读当前引脚电平,如果是低电平则说明是下降沿,此时直接忽略该中断
    1 \7 [' g" n( a3 f" Z/ Q
  82.         if(CLK == 0)
    2 F" C; c; ~# T% [' @, D
  83.                 return;
    2 c" ?; R$ x. Q9 S( c4 a2 l
  84.         // CLK上升沿到来的时候,取锁存值的下一位输出' P4 [5 {/ C! N6 }
  85.         idx++;3 Z3 ~3 {5 n; l7 K- ?. m; b
  86.         DATA = key & mask[idx];  h8 y# o0 I. b& m5 ~1 j) Y. n
  87.         // 如果已经完成7次移位,则一轮读取完成
    , p/ k# A( p! u
  88.         if(idx >= 7)6 A6 c  F$ r! Y+ Z7 U
  89.                 isReady = 0;) X5 U$ D8 B, S, f" f: f$ z
  90. }; f# r# I% F+ D. c+ y! Q* {
  91. # A$ i. B! z$ p7 w9 E% U
  92. static void INT1_Isr() interrupt 2{
    ' G6 Z: G% \7 x( n
  93.         // 读当前引脚电平,如果是低电平则说明是下降沿,此时直接忽略该中断: H, Y% ?% v1 I- i) U$ e  ]. ?" B9 M
  94.         if(LATCH == 0)5 {$ y* a4 {9 N" d4 ?
  95.                 return;/ `! Z8 L% M2 }+ z- V: k5 n) {5 j+ c( z
  96.         // 当LATCH上升沿到来的时候,锁存所有按键状态,同时把键值A输出到DATA# o& e2 T7 s, b" l
  97.         key = bufReady;
    8 U9 j2 R2 V! a3 f; n; ~
  98.         DATA = key & 0x80;//mask[0];        // 为了加速运算,直接取表中的值而不是读表
    6 j0 ~" R- F$ {
  99.         idx = 0;7 g( A% M! t& h/ v: R. ]$ J
  100.         // 允许CLK进行移位
    7 l- U0 D5 r* i
  101.         isReady = 1;
    0 V$ V/ t) R, |3 O
  102. }0 L1 M- @& d3 g; i
  103. # J4 z. L9 s8 Y$ H9 h0 o
  104. void main(){
    + ^9 w3 O# y2 M5 m" O
  105.         GPIO_Init();
    # C4 B6 m: p$ i
  106.         Interrupt_Init();
    % R; o+ W& o9 L2 L5 I* M5 X9 p
  107.        
    1 F0 F+ z. K. X( |, y
  108.         while(1){, E4 ]8 T4 y' I. J! ^( ?. `: k
  109.                 //PCON |= 0x01;        // 进入省电模式& J4 Z7 ?6 W2 T
  110.                 //_nop_();
    / H7 ?9 y3 P9 h0 o
  111.                 //_nop_();
    3 z0 n. D- g1 U" ~8 M
  112.                 //_nop_();
    . `( {* z2 R4 O, l0 \8 {( W7 V) }3 f
  113.                 //_nop_();, y+ I" [! `( Q) w  t
  114.                 buf = ~((P1 & 0x3F) | ((P5 << 2) & 0xC0));
    + U' w- g0 c) \# O* U8 h+ A& |
  115.                 bufReady = buf;9 M5 R" C# s4 Q: J& I
  116.         }
    9 v5 H7 i, _$ n; m' x
  117. }
    % X* N" g5 G5 C5 L2 W" b
复制代码
& ~" i7 a. X7 L0 p& b1 _; K, v! A
硬件参数配置无特殊要求,晶振频率选择12M即可。
4 g7 g( ^) D% p  [  F* u8 d% D' ^! t# A6 m
这是编译好的固件。

本帖子中包含更多资源

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

×

评分

参与人数 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, G# `: s* s7 e0 z3 L" o
不错的设计,想问一下楼主,FC的15针公头怎么解决?普通的公头太短了,插不进去FC的扩展接口。 ...

" S8 P3 _/ Y6 |, @6 y7 s7 z7 a' c. B坛友的改造方案
回复

使用道具 举报

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

使用道具 举报

发表于 2019-5-25 12:07:18 | 显示全部楼层
精彩,楼主动手强,也写得很详细。
7 F8 }6 i$ _( }' R/ t; {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
$ f* U- C7 o! `* J: x精彩,楼主动手强,也写得很详细。$ k; A& V3 m, V$ e
2.4G方案是目前无线的最低延迟吗?

. w( l' Z0 V4 \1 E" ]1 x我没用过其他无线手柄,所以实在不知道我自己做的这个手柄到底是不是最低延迟。. r' P$ _" j9 j6 z& @; _+ ?
不过根据网上的说法,延迟高低主要是由通信协议的复杂程度,以及数据传输速率决定的。这个模块虽然是2.4G无线模块,但由于协议很简单,所以延迟比较低。
; z! f5 Y& E( l9 y$ \- g* Y8 o! _( y) r我用这个手柄玩一些ACT游戏,比如超级马里奥、忍者龙剑传、热血系列,完全感觉不到延迟,和游戏机自带的手柄没有任何区别。唯一的区别就是这个手柄是用火花山寨手柄改造的,外壳是垃圾回收塑料,粗糙+脆弱,导电橡胶弹性不佳,手感不是一般的差。1 W) ?; l; V" `+ a! G, v. u; t
我手里还有十几张板子,等我有空了我再做一套,到时候买一个好一点的手柄改造。
回复

使用道具 举报

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

使用道具 举报

 楼主| 发表于 2019-5-29 17:00:34 | 显示全部楼层
孙大师 发表于 2019-5-28 18:554 z' d) N$ e3 A( W$ L* l8 o, k( ?
非常好,楼主是技术帝,到目前我都还没开发fc的无线套件,等空了,开发一套套件,等玩家自己组装。 ...
- a( o9 o2 g* n7 e( E( s; }
能得到孙大师的赞誉,不胜荣幸!, C% i5 t8 s+ O) u: i
不如开发一个多功能手柄,比如用SFC手柄改造,L/R键配合其他组合键可以用来切换2P~4P、调节连发速度、软重启等各种功能。接收端插到15PIN扩展口。
回复

使用道具 举报

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

本版积分规则

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

GMT+8, 2026-3-27 17:14 , Processed in 0.117917 second(s), 14 queries .

Powered by Discuz! X3.5

© 2001-2025 Discuz! Team.

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