找回密码
 注册

QQ登录

只需一步,快速开始

查看: 23177|回复: 28

自制FC无线手柄

  [复制链接]
发表于 2019-5-22 14:16:45 | 显示全部楼层 |阅读模式
本帖最后由 雷精灵2046 于 2019-6-14 09:28 编辑
  b/ C1 D; {# x) q/ ~( j9 |9 b1 c8 }0 W( D4 f" H8 p" n! v' D
没有用复杂的分立元件搭建发射接收电路,直接用的现成的2.4G无线模块jdy-40。
4 N' t" C& f! T4 N8 ~1 a; B9 t& Y( T/ W( Y, G2 ]
. |: t, K  l" ?0 {+ Y/ i
发射端靠3.7V锂电池供电,用了一片SOP8封装的STC单片机,负责产生连发脉冲,同时负责检测电池电量,电压低于3V左右的时候触发低压中断,低压指示LED就会亮起来告知该充电了。平时发射模块和单片机均处于睡眠状态,有按键按下才会唤醒,从而实现省电。实测睡眠状态下整机电流约1~2uA。板子洗了一下稍微干净了一点。因为对于微功耗设备来说,焊接残余的助焊剂可能会增加漏电流。. e# k- x2 K3 R( _0 ^& k2 j7 j

& X8 i& V+ Z3 s9 n买了一个火花的FC山寨手柄,去掉里面的牛屎板子,并修正一下塑料挡板,把锂电池和充电模块装进去。
! f: B# R; f: ?; F为了减少体积,充电模块裁剪得十分小,并且更换了充电电阻使之适应这个小小的锂电池。这么小容量的电池,也不需要多么大的充电电流是吧?6 K5 ^5 A3 f: a% b3 ^3 [
然后统统用热熔胶粘上。充电电流比较小,所以发热很少,不会熔化热熔胶。, M- h5 X5 z/ S$ p; t! v3 Z6 z
9 o% |3 q" h3 G: ~' U

$ Z! Y+ ?: r; F1 n/ S7 r1 [5 v$ e' k  y2 N& j& r6 G1 Z
最后把按键、导电橡胶和电路板装上去。
' R; ?  D3 w9 e# I- ]5 S精心裁剪了电路板,正好扣上,不会阻碍其他元件,也不会影响后盖和拧螺丝。$ e, D$ I. l1 {' \# |# X. W6 \, p2 r
- a! S- D7 k3 R" ]( J

  \2 N4 B* K: o0 }/ g完工!. z  }, E7 q0 p8 |9 I' t
5 H- M& p' \- @3 \

* j( [* @2 {# h, {" I2 p* b这是充电的MicroUSB插座。旁边的小孔用于透出低压报警LED的光线。
1 Y4 \) ?8 u( _& c( |. r6 U, V3 A. v/ I. S
0 i) i0 D6 h' e: C4 Z9 ]' @. @& {9 g9 Z
接收端用一片DIP16封装的STC单片机模拟CD4021。为啥要用单片机模拟而不是直接用CD4021?因为jdy-40模块接收端在有按键按下的时候输出高电平,无按键按下输出低电平,和普通手柄正好相反。当然我也可以用两片74HC00或者74HC04之类的逻辑门进行反相,但那就增加了芯片的数量。对于FC手柄这种工作频率并不高的设备来说,STC单片机完全可以胜任模拟工作。
- l9 F3 N. C' x2 Y: p. y  v$ X1 W
9 Y2 g  P% W1 N# C/ J
1 L, O4 A2 K+ X
2 d8 f9 N2 p$ D: w) K电路设计有点小小的错误,所以有几根飞线。原本设计使用低压差LDO是XC6206,结果在做这个接收模块的时候,买的LDO居然找不到了!无奈只好用了AMS1117。幸好对于接收模块来说是5V降到3.3V,1117可以胜任。要是发射端手柄的话,3.7V降到3.3V,那就非得用6206不可了。; Y7 R: j0 Z; C* }# j/ N8 g
# l6 U) G+ {# G0 M* x8 x
实测十分灵敏,延迟极小几乎感觉不出来。可惜这山寨手柄的手感并不佳,尤其是方向键,软塌塌的。看来我得买个剪线手柄改装。9 w. i& ]: n7 D2 Y

- S+ n4 s$ b* L! N- w这是电路图,有兴趣的朋友可以参考。$ A3 V6 z# W" I6 m8 c

0 B3 y! n; i( _/ Q, ]& {
# H% r6 ]9 b% j5 }( _* G我信奉开源主义,十分痛恨把技术藏着掖着。好东西大家分享嘛!所以两个单片机的源代码大公开!
3 W' Z  r3 }; B2 d) h$ R2 r编译器:Keil 51。
" F+ Z6 {3 P" s
4 w5 w" _  q" l! C% h: ^发射端:
9 a& \$ ?- ?5 P7 _0 \; m
  1. #include <INTRINS.H>( W$ f% E3 o" y  k
  2. #include "STC15W.h"* [) w& ~6 g& l( G) f
  3. " @/ U% I4 k0 S2 X
  4. - A# L4 d; L2 B+ w0 \& |# z
  5. /*
    9 S4 J" n) m7 S8 |2 T0 s% C" B
  6. --------------------------
    " P/ B) @! N1 f, P' K2 z
  7. |1 (OUT)        \__/   (INT1) 8|
    5 `* d$ E6 J& i# H* _5 Z; w
  8. |                                                   |
    0 p+ p1 z7 \, L* Y9 E
  9. |2 (VCC)                   (INT0) 7|& f3 c& G8 L5 y4 F: g1 I9 K# a
  10. |                 STC15W204S                   |* C  G1 \# D; z; l! U
  11. |3 (LED)                         (TXD) 6|  c% m' _5 X6 [5 p- l3 i
  12. |                                                   |
    " I- T# \9 P7 @: Q6 P
  13. |4 (GND)                         (RXD) 5|1 w7 J+ @4 U( b! T! s
  14. --------------------------8 K  r1 L/ u9 G, h" X
  15. ; v- A/ Y/ b. M. e) Q, p* Q
  16. LED ---|<|---[===]--- VCC
    ! d% u( ]6 g& g/ J7 L  b
  17.            Red          330
    4 f. B! T4 r; r- N* E
  18. 1 {8 _4 \) L. X/ J" ~: r
  19. Fosc = 6MHz
    8 z; |0 N, `, H  h$ D
  20. */
    " g3 B8 {' m, ^0 Z) v( P
  21. - @5 @$ b% m1 m1 I$ n

  22. ; d/ B% E+ s  f/ Z: X9 ?. {0 _
  23. // 矩形波输出脚! @* Y4 T1 z7 l  k$ C6 `
  24. sbit OUT = P5^4;
    ! ?& {8 P* Q9 J) h' t
  25. // 低压指示灯引脚# }( Q6 u8 w. m
  26. sbit LED = P5^5;
    + Y+ v8 f4 q. B
  27. * g  {5 n) p& X4 t: ^/ b  x
  28. // 停机标志位! p. S) z0 b  s! k) `' U; _; Y
  29. bit isReadyToHalt = 0;0 ^. b0 Q/ j3 i2 C

  30. " [5 v; @1 n2 {# I: g* G
  31. // 矩形波次数累计  U! I: Z! G( T! }6 h2 L
  32. static volatile unsigned char count = 0;/ F2 Y' N0 q* m7 [0 Y9 p8 D
  33. ( e9 s$ i9 E6 k: ]

  34. 6 z1 a7 p% o. s: D
  35. static void GPIO_Init(){
    % M7 K2 k8 T7 u* s
  36.         // P3口设置为准双向,默认靠内部弱上拉输出高电平
    3 N5 N8 K# a  c# g. w+ W; ]0 Z
  37.         P3M0 = 0;
    ; m2 h$ e% ?% s" T6 y: h7 x
  38.         P3M1 = 0;
    9 L7 h  e: H' o* L' E) @9 ?
  39.         P3 = 0xFF;
    ( }$ i( |, s( L( }! T, b
  40.         // P5口设置为准双向,默认靠内部弱上拉输出高电平
    $ x& j1 b( o+ A( |! p0 e0 ?
  41.         P5M0 = 0;
    7 i- U/ _& h! _6 ?# @- V
  42.         P5M1 = 0;
    - _$ E3 w: d) n/ a4 s
  43.         P5 = 0xFF;
    ; {  B& g) `: s2 A) x$ i
  44. }, k) {$ E1 G9 c- b2 G# c

  45. * g/ i5 w4 G" d
  46. static void Timer0_Init(){6 y0 o& C  ^1 @2 X
  47.         // 16毫秒@6.000MHz1 W8 ]! f7 @' K. z2 K+ E2 g
  48.         AUXR &= 0x7F;        // 定时器时钟12T模式
    / N+ m! i2 ~6 e5 X2 F9 d
  49.         TMOD &= 0xF0;        // 设置定时器模式3 F3 ?% Z8 X' j0 L7 X' y4 c
  50.         TL0 = 0xC0;                // 设置定时初值4 w) p( @+ I1 ~6 t9 M- ]1 y7 X
  51.         TH0 = 0xE0;                // 设置定时初值
    % V6 I2 P, m3 _% z
  52.         TF0 = 0;                // 清除TF0标志0 V" H7 m4 r7 H! g
  53.         TR0 = 1;                // 定时器0开始计时
    $ o2 I  Y: G& ?  `
  54. }+ @1 j' Q; @, s7 _
  55. , m- H6 L. z: i, X) X& i/ i
  56. static void Interrupt_Init(){. E+ e0 |8 ~1 g( L, X
  57.         // INT0中断触发类型为下降沿触发0 ?  F( n+ U. Q7 Y
  58.         IT0 = 1;! Z) @3 F* J! J6 I; z
  59.         // 允许INT0中断
    9 e( j9 W' h( A9 w- Y7 K9 Y
  60.         EX0 = 1;* U# c8 D) c4 c" f% A$ e
  61.         // INT1中断触发类型为下降沿触发; G6 V4 K6 R6 a% `# i
  62.         IT1 = 1;0 c; E8 F9 w, f# g, c9 \1 x( O
  63.         // 允许INT1中断; \; k# J; Y! q
  64.         EX1 = 1;
    & b+ v; ^- h$ I# f5 b7 V
  65.         // 允许定时器0中断
    4 \4 v0 {! q/ `$ I6 E7 x' O4 T2 l
  66.         ET0 = 1;
    . d: i# w) M+ c
  67.         // 允许全局中断
    3 S* k2 D- S* }% s
  68.         EA = 1;
    % e4 b' z& |( e- P, }1 \" Y0 m# L
  69. }( T) K3 d6 O! k+ j

  70. 4 P2 g) B5 k/ K2 Z
  71. static void INT0_Isr() interrupt 0{
    3 N5 ~( c8 o, y3 @/ n4 H, v
  72.         // 矩形波次数累计归零. \5 T8 h5 d# q8 h" {$ h
  73.         count = 0;( U% o2 I9 a5 ^, W
  74.         // 重开定时器0中断
    ( t* X3 y( W; w
  75.         ET0 = 1;5 {& i0 t+ J6 o9 ~. Y
  76. }* k4 a  b% g0 G  z. F5 r9 Z9 l
  77. & s( p! [% q. Q5 R& C' m7 G5 q* T
  78. static void Timer0_Isr() interrupt 1{
    " ^1 [% D# w9 B& \  E- [
  79.         // 输出矩形波  z% w  G2 h; x3 n- ~
  80.         OUT = ~OUT;
    . V! ?/ W; Q* _
  81.         // 累计矩形波次数
    * p6 k( K4 n9 s9 @2 h1 u, T' W
  82.         count++;, q$ B2 {' }+ V- c/ T! y
  83.         // 超过250个矩形波,准备停机
    8 r1 m' r* i& K3 G
  84.         if(count > 250){9 }+ R  [+ q! X. s9 Y5 B4 G3 \' G
  85.                 count = 0;" a8 O, c5 `; S6 j& M9 R' M% P
  86.                 isReadyToHalt = 1;. `" a( M5 [, b5 f, M8 p
  87.         }
    3 }) e. d2 F; j
  88. }
    ) `0 v" ]. [- h" K

  89. / t, t4 _; E; r3 E
  90. static void INT1_Isr() interrupt 2{! B  m$ Z3 a8 Z6 P: B: k" G1 }! T
  91.         // 矩形波次数累计归零
    + A- m/ b# S# k; b% @  h
  92.         count = 0;
    5 X( m# A) X7 j, x  L
  93.         // 重开定时器0中断
    - P% w: B( P9 |9 g5 d" m) V
  94.         ET0 = 1;
    * _0 B$ w+ w3 i' `* k4 k1 L( P
  95. }
    % \9 e  f2 X" s5 z) T( d# u
  96. 3 D* B5 Z3 z) l+ X' F4 O) H* t

  97. + W! f2 Q- {+ s  y: x8 s5 X4 L
  98. void main(){8 }* H" e0 L% s1 V2 u, D
  99.         // 初始化P3和P5口5 h8 a% z1 u  `! I# m
  100.         GPIO_Init();3 H+ Z( E0 F" O  a) G5 u
  101.         // 初始化定时器0. H- j8 k% k4 h) F1 A
  102.         Timer0_Init();9 F* M" b4 R2 D! x
  103.         // 初始化中断
      J+ s$ x( y, a+ O4 V1 ?
  104.         Interrupt_Init();  {+ k# x5 R4 f4 E6 O9 L
  105.        
    , V1 k: }6 U9 |9 l
  106.         while(1){* x5 `" n" u# y
  107.                 // 检测电量
    3 u# T4 ]8 D' v8 k- s5 z. Q% w+ B
  108.                 if(PCON & (1 << 5)){& x0 j) r4 Y' z
  109.                         // 如果电量低,低压指示灯亮
    ) o" S: p* H+ f* Y1 C4 U" J9 N
  110.                         LED = 0;' {1 S* o( ?/ o& h- X  ?
  111.                         // 清电量检测硬件标志位
    # K9 Q5 n& W+ ?1 V# B/ c
  112.                         PCON &= ~(1 << 5);. b( Q! f- y1 Y/ a6 _9 W
  113.                 }else{
    , D) e8 N) |* N: \% w  q( L
  114.                         // 电量正常,低压指示灯灭
    1 W1 Q' m1 ?% u1 A$ @8 c
  115.                         LED = 1;
    4 C9 p; W, l# F- i) p2 Q
  116.                 }
    * q3 e6 ^) b$ N) I7 q  L

  117. 3 W& z! G/ G7 X( F2 m9 H- p  a
  118.                 // 检测到停机标志
    1 O& [$ O, _2 e  G* a
  119.                 if(isReadyToHalt == 1){5 Y% _, V1 E! T2 |
  120.                         // 暂时关闭定时器0中断
    , f7 ]1 c# A3 o& r0 B  P
  121.                         ET0 = 0;2 K$ R8 x2 u! I) Y8 q2 m4 j5 O
  122.                         // 停机之前先把矩形波输出脚置低电平,以方便INT0和INT1唤醒CPU
    + I# x, I/ f0 W/ S+ {
  123.                         OUT = 0;6 v2 H- \9 a+ u. x
  124.                         // 停机之前先把低压指示灯灭掉,以省电. Q; m9 g' x9 D# I' {
  125.                         LED = 1;* }( V2 a! R6 s
  126.                         // 进入停机模式
    . h/ m; ^0 e# N; S% I
  127.                         PCON |= 0x02;
    * n; ]" I. c! U8 `+ e0 G
  128.                         _nop_();
    1 W7 R$ Z" a6 _) a
  129.                         _nop_();
    - |/ X  B; D9 \1 N! h
  130.                         _nop_();
    " [; t" P; l/ H0 D: L
  131.                         _nop_();
    # o1 X3 u& r; |9 G. u; j
  132.                         // 唤醒,清标志位
    7 R  N( h! j! }5 u( `9 ^
  133.                         isReadyToHalt = 0;& x0 }' @4 I2 H. ~) s5 m( T
  134.                         // 重开定时器0中断
    1 h* b$ b- M: ]3 y. X1 Q. E" V. C
  135.                         ET0 = 1;2 P9 E$ C: {3 `( y+ p4 C% [
  136.                 }
    ; x* Y) i2 ?0 n' m' a+ q
  137.         }
    + P$ U2 J: t$ r
  138. }5 q: E) y& S3 ]( G9 s  j8 q/ I) C- f
复制代码

' R! F" c' I7 k  F! L1 I% h硬件参数配置:
, v; {& e+ Y* s& r1 T0 ?. p5 d% i7 b1 N5 p& u

2 ?% ~+ p, u5 N% T* T1 X) ]接收端:' [) |  X6 ]5 S# a# D6 @' b
  1. #include <INTRINS.H>
      O) @: E) u, e8 \& H
  2. #include "STC15W.h"  B& m" W' W4 \, }& e" I
  3. 1 R: V3 d# B1 M6 c
  4. 3 B5 p3 h2 v; d( `
  5. /*
    + e2 a" B. |3 i0 U8 O# d( s3 O
  6. " i" d8 Z% ^& ~
  7. *---------------------------*
    ' v0 ^7 v; l; R" p3 q
  8. |1 (GPIO2)         \__/  (GPIO1)16|4 {8 N* c3 u9 E0 ^; [5 Y
  9. |                                                        |+ u4 n1 c0 d$ C
  10. |2 (GPIO3)                   (GPIO0)15|$ I! j! |; L1 U
  11. |                                                        |
    , Y( `1 z/ M; S
  12. |3 (GPIO4)                                  14|7 a; F* t) p. n1 |, [3 a) N
  13. |                                                        |
    / [7 `% i$ B- X- H. h+ T
  14. |4 (GPIO5)                        (DATA)13|( _$ K9 ?3 o3 g4 f
  15. |                  STC15W204S                |
    ! Y4 R3 }: [" y, o
  16. |5 (GPIO6)                   (LATCH)12|
    " |, x. v2 B. `9 k8 n5 |
  17. |                                                        |4 A1 J- U* n$ v% l3 L
  18. |6 (VCC)                         (CLK)11|8 p. ^3 A/ t! z2 d2 j
  19. |                                                          |
    4 Z  e8 D0 {4 }! y9 a
  20. |7 (GPIO7)                         (TXD)10|
    # _. Y# v8 T* ~  K* r. a, ^  ^
  21. |                                                        |/ E% E, X# Z' `! e
  22. |8 (GND)                         (RXD) 9|
    / v, V, t) g3 I2 i
  23. *---------------------------*' r, ]1 z0 g/ |
  24. Fosc = 12MHz
    , V: e, j( U5 s5 `
  25. 4 C  h" ]5 P9 ?; e# N* O' u( y5 G
  26. P1.0 -> 上/ a+ j0 v: W8 H; h7 B+ N
  27. P1.1 -> 左, E% o, w$ o. I$ b
  28. P1.2 -> 下4 d) @8 H2 `- F9 v3 j
  29. P1.3 -> 右
    4 d% T4 @6 V0 S4 ?. x- x4 p' N
  30. P1.4 -> SEL
    / C: T) Q, P4 o0 A: h" n( a- t
  31. P1.5 -> STA1 F( d: S5 s0 Q( O3 k. i
  32. P5.4 -> B, ^# Z3 ^+ U7 L/ v% g& S) f
  33. P5.5 -> A
    $ N3 L2 x. d7 V+ v* h. M
  34. ) w" C' w- M1 X
  35. */
    : o8 l$ R  p4 J! E8 W0 U

  36. $ a$ Q- j8 f9 E* ^. l/ c% K, E
  37. 4 U" l# x: g+ E6 ?
  38. sbit CLK        = P3^2;7 R1 Z. L$ z( u; Q
  39. sbit LATCH        = P3^3;
    - z# G: ^  U6 S- p" ?
  40. sbit DATA        = P3^6;( D  ?$ S- v. R* a& Z

  41. : ~) j9 [3 d% s: [. ~
  42. bit isReady = 0;2 V, b* U- \2 K+ X( m$ S
  43. static unsigned char key = 0;
    " e! @- X; s) z$ J. g: x
  44. static unsigned char buf = 0;        // 双缓冲。这个缓冲区保存从P1和P5组合而来的键值
    $ b& H& a) p* `
  45. static unsigned char bufReady = 0;        // 双缓冲。这个缓冲区保存上面那个缓冲区的备份7 M9 I" T  B# L6 \6 I  C$ m$ k, W. s
  46. static const unsigned char data mask[] = {0x80, 0x40, 0x10, 0x20, 0x01, 0x04, 0x02, 0x08};        // A B SELECT START UP DOWN LEFT RIGHT。为提升速度,这个表放到RAM中
    & m4 M; f) ]" L( B: c, j
  47. static unsigned char idx = 0;0 I# N4 j) p0 X* ]% ~0 @4 A
  48. ! j9 b' G, t$ A9 i% @' ^4 W4 K& X

  49. 5 J1 W$ n! A6 t: D: n0 l/ d
  50. static void GPIO_Init(){
    4 B# ^' c$ p0 k1 }
  51.         // P1口和P5口用于接收并行信号,全部初始化为准双向,依靠内部弱上拉输出高电平
    3 j2 a2 c! {; l2 |( q; N0 g
  52.         P1M0 = 0;
    ! T/ f8 W+ S+ U% k1 z% d1 y
  53.         P1M1 = 0;$ f6 G2 |5 X, O
  54.         P1= 0xFF;
    ( I( U: c4 T: j
  55.         P5M0 = 0;
    - H! P; O0 ^% u, z- q, F, G
  56.         P5M1 = 0;# g- _1 P0 A. z! d$ }5 {
  57.         P5= 0xFF;
    3 ^2 h  X5 F: l6 E4 d" E
  58.         // P3口初始化为准双向/ p5 e% ~% c, J) H' [5 T
  59.         P3M0 = 0;# r9 K: X# }; f
  60.         P3M1 = 0;- P" R* w) Z2 O" D
  61.         P3 = 0xFF;2 x; x+ f+ P6 I& H' f# f
  62. }
    1 K4 b" J! ^* Y- w3 a
  63. # y9 g- l, D& L4 c! s" g
  64. static void Interrupt_Init(){$ e5 o" O& x7 o. g' {
  65.         // INT0中断(CLK)触发类型为上升沿+下降沿
    ! r2 t8 K0 K* F6 s0 Q) d
  66.         IT0 = 0;+ P4 |  T' L: p6 y/ J2 @
  67.         // 允许INT0中断
    8 ~) ?% f5 e6 m) W. ^$ H$ w9 V
  68.         EX0 = 1;
    ; c, w; I! ?0 _7 [; P/ |; o
  69.         // INT1中断(LATCH)触发类型为上升沿+下降沿
    ! T% {$ w' _" |; ]
  70.         IT1 = 0;+ p% d: o$ N* B$ f
  71.         // 允许INT1中断5 K- C: {$ q- o( H0 F
  72.         EX1 = 1;) O; c0 t( G7 I  d0 u$ h" u4 J
  73.         // 开启全局中断' j3 P3 g9 d5 e7 V' \
  74.         EA = 1;
    / f1 w; O. W' m3 n0 |; @
  75. }: R6 X3 b: t5 |; B) J5 O6 V
  76. ( }1 y+ g, k9 n5 r  R( O
  77. static void INT0_Isr() interrupt 0{
    ) b3 s5 H( `% y, `7 d- j1 @& X
  78.         // 只有已经成功锁存才允许CLK移位
    5 [" L6 _1 T2 J8 w
  79.         if(isReady == 0)
    3 E5 H9 b9 b7 I$ b0 ^# z8 \. y
  80.                 return;5 D% U7 c' [5 L) R) x) b
  81.         // 读当前引脚电平,如果是低电平则说明是下降沿,此时直接忽略该中断. J/ k5 ~* v' o8 O! z# W
  82.         if(CLK == 0)
    ) o3 B7 k/ [5 u& n9 h7 p1 j$ e
  83.                 return;
    - I5 ?" o7 Q' V
  84.         // CLK上升沿到来的时候,取锁存值的下一位输出
    " S5 D+ U3 {5 a% w( a' L
  85.         idx++;
    9 b+ ^; S* [/ I
  86.         DATA = key & mask[idx];
    6 q7 X. o% G+ c: i+ C
  87.         // 如果已经完成7次移位,则一轮读取完成
    , {; e6 c( n+ y7 g
  88.         if(idx >= 7)
    & Y& Y- Z, I) x& V& \
  89.                 isReady = 0;
    ! t; H" |. }4 Z  S
  90. }4 ~  P/ K: C, |! d# C' y# f

  91. - G. G8 P, B9 ?
  92. static void INT1_Isr() interrupt 2{1 k+ N( v: p$ H+ T
  93.         // 读当前引脚电平,如果是低电平则说明是下降沿,此时直接忽略该中断6 t) Q* m0 j3 e
  94.         if(LATCH == 0)
    ( C4 o2 D, A, s& I6 q. w; i5 v6 D+ T
  95.                 return;
    ' J' S4 J: z4 C
  96.         // 当LATCH上升沿到来的时候,锁存所有按键状态,同时把键值A输出到DATA! ~4 T- r) R% t$ n* ?; z( e0 N
  97.         key = bufReady;
    2 P  ^8 p  {% D+ S- ]
  98.         DATA = key & 0x80;//mask[0];        // 为了加速运算,直接取表中的值而不是读表
    5 c: m$ F5 [* T- ?
  99.         idx = 0;# C9 l! c1 b9 r" u
  100.         // 允许CLK进行移位
    : ?% j; g& A$ ?  o
  101.         isReady = 1;
    & L) }# k( \: s5 E
  102. }6 D" `) X" G% J$ x: y( i8 }
  103. " w( e* D: w" g: x6 ^/ v( P
  104. void main(){
    ( G% s* L; a" U* }- R$ k* r
  105.         GPIO_Init();
    $ ?. u: n2 ]* i( \# r
  106.         Interrupt_Init();
    1 F- o7 I3 c" K' r  k
  107.        
    # J6 y% K! N0 A- P2 C
  108.         while(1){0 i$ S! r6 P; Y/ `
  109.                 //PCON |= 0x01;        // 进入省电模式, v. M" r( G7 q( j3 ^
  110.                 //_nop_();
    * m( o( o6 c+ g9 X% ~7 W
  111.                 //_nop_();8 j/ Z8 ], i8 X. p+ k# B! W& r
  112.                 //_nop_();7 B( Q- Y9 _; S7 ?
  113.                 //_nop_();
    7 b& _4 x5 b! _7 E3 \3 Z
  114.                 buf = ~((P1 & 0x3F) | ((P5 << 2) & 0xC0));1 |: f/ _; X$ p# e, F% d
  115.                 bufReady = buf;
    5 o  b) S$ O/ |( {/ B& h( K1 \
  116.         }  W9 j6 a/ `* v$ e3 H
  117. }
    5 M3 m( Y( c1 m4 @$ f. L) U
复制代码
" H4 w6 S% w7 y; J: m
硬件参数配置无特殊要求,晶振频率选择12M即可。
6 v6 F8 v- e0 ^& q. G& X( S0 u7 t) `6 j* r' 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
2 `/ |' T! ?& }不错的设计,想问一下楼主,FC的15针公头怎么解决?普通的公头太短了,插不进去FC的扩展接口。 ...
0 A* Z! W3 O0 ?: W( a& w& B( f7 I
坛友的改造方案
回复

使用道具 举报

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

使用道具 举报

发表于 2019-5-25 12:07:18 | 显示全部楼层
精彩,楼主动手强,也写得很详细。8 t. Z8 K) ~; b
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:079 x, h3 a. w& j  d! H4 P
精彩,楼主动手强,也写得很详细。
8 M5 O/ S2 f, E) q+ m2.4G方案是目前无线的最低延迟吗?

+ c8 H6 Y# z, }" p! K7 o我没用过其他无线手柄,所以实在不知道我自己做的这个手柄到底是不是最低延迟。
) `# Y( h/ E5 Q* }- x/ i不过根据网上的说法,延迟高低主要是由通信协议的复杂程度,以及数据传输速率决定的。这个模块虽然是2.4G无线模块,但由于协议很简单,所以延迟比较低。3 p/ m6 }0 Y# c. U5 N
我用这个手柄玩一些ACT游戏,比如超级马里奥、忍者龙剑传、热血系列,完全感觉不到延迟,和游戏机自带的手柄没有任何区别。唯一的区别就是这个手柄是用火花山寨手柄改造的,外壳是垃圾回收塑料,粗糙+脆弱,导电橡胶弹性不佳,手感不是一般的差。9 C3 n0 [( M# p
我手里还有十几张板子,等我有空了我再做一套,到时候买一个好一点的手柄改造。
回复

使用道具 举报

 楼主| 发表于 2019-5-29 16:56:14 | 显示全部楼层
ppad 发表于 2019-5-28 17:276 [& P4 w& i0 Z; _7 f: _( O. a) L* J3 g$ v
给技术帝赞一个,有半成品发布吗,自己焊接改造就可以,编程实在不会啊 ...

9 n+ `1 H  ?" N; A" D, V很可惜,我手里没有多余的单片机了,LDO也找不到了,锂电池以及充电模块更是没有了。反正就是该用到的元件基本都没了,所以没法发布半成品。+ B/ }' E: L/ ~2 n% i
两个板子倒是有十几张剩余。5 A/ {+ w5 o* M' t6 `+ |
你要是有USB转TTL串口板,完全可以自己买这两种单片机,然后我给你编译好的固件,你自己用串口板下载到单片机里面就行了。两个2.4G无线模块也得通过串口板用AT命令设置参数,不过好在我在设计电路的时候就已经预留好了串口,可以直接在线下载和在线设置参数。总的来说并不麻烦。
回复

使用道具 举报

 楼主| 发表于 2019-5-29 17:00:34 | 显示全部楼层
孙大师 发表于 2019-5-28 18:551 D8 |, ]9 w' _9 {2 _, j5 G
非常好,楼主是技术帝,到目前我都还没开发fc的无线套件,等空了,开发一套套件,等玩家自己组装。 ...
/ R/ U6 p  K% ?0 m3 [% j
能得到孙大师的赞誉,不胜荣幸!2 O) S( u0 A; |; ^& h6 x
不如开发一个多功能手柄,比如用SFC手柄改造,L/R键配合其他组合键可以用来切换2P~4P、调节连发速度、软重启等各种功能。接收端插到15PIN扩展口。
回复

使用道具 举报

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

本版积分规则

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

GMT+8, 2025-11-19 17:45 , Processed in 0.122503 second(s), 17 queries .

Powered by Discuz! X3.5

© 2001-2025 Discuz! Team.

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