找回密码
 注册

QQ登录

只需一步,快速开始

查看: 26773|回复: 33

自制FC无线手柄

  [复制链接]
发表于 2019-5-22 14:16:45 | 显示全部楼层 |阅读模式
本帖最后由 雷精灵2046 于 2019-6-14 09:28 编辑 & Z0 ~1 Z; N* v. e) X0 Y& ^
: C* V5 _* Z1 t% d1 e
没有用复杂的分立元件搭建发射接收电路,直接用的现成的2.4G无线模块jdy-40。, S' S$ h5 v, V! {2 h- ], B6 l- w4 B; H

! O* f2 I, ]# N) K
; [; @: i0 F; W4 O发射端靠3.7V锂电池供电,用了一片SOP8封装的STC单片机,负责产生连发脉冲,同时负责检测电池电量,电压低于3V左右的时候触发低压中断,低压指示LED就会亮起来告知该充电了。平时发射模块和单片机均处于睡眠状态,有按键按下才会唤醒,从而实现省电。实测睡眠状态下整机电流约1~2uA。板子洗了一下稍微干净了一点。因为对于微功耗设备来说,焊接残余的助焊剂可能会增加漏电流。
5 j/ w4 [% y6 `  j5 P0 R/ ^7 S# b9 v; z. O# l
买了一个火花的FC山寨手柄,去掉里面的牛屎板子,并修正一下塑料挡板,把锂电池和充电模块装进去。2 ^  C/ W# q7 i( n
为了减少体积,充电模块裁剪得十分小,并且更换了充电电阻使之适应这个小小的锂电池。这么小容量的电池,也不需要多么大的充电电流是吧?
/ D, e  L& _9 e然后统统用热熔胶粘上。充电电流比较小,所以发热很少,不会熔化热熔胶。6 J& _8 S8 K6 g6 g3 D0 t
9 F: D6 S) j& `

6 v* h6 f8 w% i! k$ Y  i
0 a5 y7 i$ j, d) g2 k' W  U最后把按键、导电橡胶和电路板装上去。$ J9 s2 M6 T5 e# O
精心裁剪了电路板,正好扣上,不会阻碍其他元件,也不会影响后盖和拧螺丝。
, k6 O3 ^: Z. K, ~2 e" ^1 ^9 a( Q: h4 F! ]2 S
- j1 T1 H! g( N) d) {- P
完工!8 V1 B; m2 Q, Y( [
0 L+ W7 l5 z  K# v* x1 g

& f2 \) d/ A; p这是充电的MicroUSB插座。旁边的小孔用于透出低压报警LED的光线。, ~# x6 h& r$ @( e# y* w+ y
; m: P8 I2 Y& d6 n% I1 R
/ f3 Z$ [: k! v) q7 `
接收端用一片DIP16封装的STC单片机模拟CD4021。为啥要用单片机模拟而不是直接用CD4021?因为jdy-40模块接收端在有按键按下的时候输出高电平,无按键按下输出低电平,和普通手柄正好相反。当然我也可以用两片74HC00或者74HC04之类的逻辑门进行反相,但那就增加了芯片的数量。对于FC手柄这种工作频率并不高的设备来说,STC单片机完全可以胜任模拟工作。
& G) N# x$ l. C3 ~3 E0 U, i5 m( Y4 H. Y$ C3 B; k
1 K' P! v9 W$ r1 q( E. t0 U
! s! ^- {; y: n  ]. J2 F
电路设计有点小小的错误,所以有几根飞线。原本设计使用低压差LDO是XC6206,结果在做这个接收模块的时候,买的LDO居然找不到了!无奈只好用了AMS1117。幸好对于接收模块来说是5V降到3.3V,1117可以胜任。要是发射端手柄的话,3.7V降到3.3V,那就非得用6206不可了。
, J3 _2 i6 Y3 @0 U  G. @# W' K+ a$ s2 P. r
实测十分灵敏,延迟极小几乎感觉不出来。可惜这山寨手柄的手感并不佳,尤其是方向键,软塌塌的。看来我得买个剪线手柄改装。
: E1 I! w* Z) F7 m
; j& F- p6 n$ P4 W5 M这是电路图,有兴趣的朋友可以参考。
2 Q* h0 N! ]- t, N+ B8 E6 K; P3 j
0 j9 ~' x) ?( S2 [- \4 l
我信奉开源主义,十分痛恨把技术藏着掖着。好东西大家分享嘛!所以两个单片机的源代码大公开!
1 x7 [& J2 i5 D- ]9 S, k6 t编译器:Keil 51。, o5 ]4 v0 `" b' \1 ?1 H& W5 V
- ^8 t; I3 U9 v7 |. n% F0 {( G
发射端:
  C4 c& U6 y5 {2 J1 h( X
  1. #include <INTRINS.H>1 X% O0 |* L5 [- d! e3 Z
  2. #include "STC15W.h"
    5 j  f; x3 k1 x" O
  3. 6 B. N, g, l. U" @3 c( p8 D/ r
  4. 0 v5 ]2 ?& D; ~* u2 _1 N: L
  5. /*- a* E; C( u7 Z) c3 r7 H! O
  6. --------------------------# G- }; e, o3 T/ {) s% O2 u. b) e  u( H% w
  7. |1 (OUT)        \__/   (INT1) 8|! }" u, j: l5 i+ b8 X  b
  8. |                                                   |
    % a! l3 B0 U8 h0 |, s
  9. |2 (VCC)                   (INT0) 7|
    $ D9 Z" V$ F' |' G# k
  10. |                 STC15W204S                   |
    6 W5 c: t, O5 a
  11. |3 (LED)                         (TXD) 6|
    6 p6 }' @2 C! l* ^! `; ~9 E2 [) h
  12. |                                                   |
    ' ?' O: J4 X4 l
  13. |4 (GND)                         (RXD) 5|( m, \! z- [. P3 J* @" z' C
  14. --------------------------
    ( Z+ t4 V! x& X8 k
  15. 5 X2 l" n, [2 p5 ~$ _* G5 `- H
  16. LED ---|<|---[===]--- VCC
    : Z/ Q" b* F$ }1 E$ M7 x: q# V
  17.            Red          330; [  a" u9 w* ~6 [+ V9 I7 I
  18.   Z" V7 o: g, h6 K4 B
  19. Fosc = 6MHz* g  I9 d, p% ]; B6 q: e/ s
  20. */' Q/ ?' ~, A8 O6 @8 q& X) |0 l! g

  21.   f* t! y5 c; I

  22. 4 `, D3 z# f0 Y4 h1 g
  23. // 矩形波输出脚
    $ p4 g- j9 B' p- t
  24. sbit OUT = P5^4;
    5 y8 G) ?8 h% x; a+ h
  25. // 低压指示灯引脚
    ( J! a5 z  c& q9 R9 p
  26. sbit LED = P5^5;, h4 s6 v5 H+ l! d

  27. . A; c4 s+ c2 q5 D8 _$ [# Y* m
  28. // 停机标志位1 k# H/ r4 C8 f$ S) W: _+ ]9 l9 J: {2 _
  29. bit isReadyToHalt = 0;3 c) d& E0 K) q9 ]
  30. 3 G) U5 {  g9 e6 Y0 A
  31. // 矩形波次数累计
    ) e+ d7 `/ b  q2 ?) `
  32. static volatile unsigned char count = 0;
    ! G% U1 e) ^% O- Z' I/ g! p
  33. 5 j% l' A1 P% @' {* E
  34. ' O) ~2 C" p3 K* u2 X; S
  35. static void GPIO_Init(){% X# ^' d4 I0 ~5 G  m1 n3 J* m0 B
  36.         // P3口设置为准双向,默认靠内部弱上拉输出高电平9 m2 ]9 y* k8 H- v5 n' z: o
  37.         P3M0 = 0;
    5 K+ K3 X! B2 k. e. J
  38.         P3M1 = 0;" o0 s+ [& E& ?, K
  39.         P3 = 0xFF;9 t4 x1 C% z. ?4 p
  40.         // P5口设置为准双向,默认靠内部弱上拉输出高电平  \& V6 ^/ e/ `$ \  R
  41.         P5M0 = 0;
    * X5 |( J. S* }
  42.         P5M1 = 0;
    - h- W# c9 b* z( H
  43.         P5 = 0xFF;
    : K4 m: n! P$ H
  44. }! Q3 q: p# U5 x. W
  45. 5 t6 }4 F7 p; E2 a) x7 z9 R
  46. static void Timer0_Init(){! S) v& X% }, t0 f9 ]0 B
  47.         // 16毫秒@6.000MHz
    - _' x" k; r$ H
  48.         AUXR &= 0x7F;        // 定时器时钟12T模式
    3 [" |4 T, r  B  b; L9 U
  49.         TMOD &= 0xF0;        // 设置定时器模式, q% B% H7 Y. F  a0 v
  50.         TL0 = 0xC0;                // 设置定时初值$ @5 U" S# L4 N/ I6 m2 O( N! Y8 r* A
  51.         TH0 = 0xE0;                // 设置定时初值
    # l) x) s" F; N7 a0 [- B9 q
  52.         TF0 = 0;                // 清除TF0标志  K$ n, i5 X/ O# d! |
  53.         TR0 = 1;                // 定时器0开始计时
    $ w& a) B, m2 v3 }) f8 Y
  54. }
    - Z! v+ e& g1 o; X

  55. ! u: d" a2 w' `; k- C2 i& S  n. Y4 K
  56. static void Interrupt_Init(){
    ( W: l4 @  ~) T& B7 s1 S9 i7 Z. O# V
  57.         // INT0中断触发类型为下降沿触发
    1 a1 A& ~% i; v; T
  58.         IT0 = 1;+ w$ M1 g  ^8 O- }' `
  59.         // 允许INT0中断6 _1 z$ r4 b3 J! Z
  60.         EX0 = 1;
    # }' S" t/ H6 F' C# L3 j. X# o
  61.         // INT1中断触发类型为下降沿触发
    / _5 I& @5 w& H; h( j" ]8 n0 \
  62.         IT1 = 1;
    / o  X% N8 M" {4 z- q
  63.         // 允许INT1中断
    $ j: _$ p: Z0 J& z; a5 u0 O' Y
  64.         EX1 = 1;. l8 {) s" R+ P* P! s9 j( e
  65.         // 允许定时器0中断* S- e6 H* e0 y
  66.         ET0 = 1;
    4 {& q: y- B$ i
  67.         // 允许全局中断
    & h) a) X, \; o1 m/ |
  68.         EA = 1;
      X. P# f! J- F5 C
  69. }- n; l  r* G5 f1 U

  70. 4 ^9 E9 _9 R& }- B1 u
  71. static void INT0_Isr() interrupt 0{3 p) ^" z7 b* a, c
  72.         // 矩形波次数累计归零# L8 O' V) y/ ^$ Y
  73.         count = 0;7 }# d0 g4 [; x# c, W& B
  74.         // 重开定时器0中断
    4 K+ L7 s$ }7 V* c6 Z, J& N
  75.         ET0 = 1;
    & z& z. u" b! ?2 w
  76. }$ W3 p; K+ Q6 t) }: h' E4 M( P  v
  77.   {* q3 \& _: g' O5 W9 I* z) ~
  78. static void Timer0_Isr() interrupt 1{
      k+ N  ]/ U/ Y# ^+ t
  79.         // 输出矩形波
    % Z+ T- C' q4 m( O: _0 p$ P
  80.         OUT = ~OUT;6 m" |( ~! {+ w; a/ F
  81.         // 累计矩形波次数% J. N; k8 s" l! G1 ^; J, V' h- O
  82.         count++;
    * a% W+ p+ w' p9 A( p
  83.         // 超过250个矩形波,准备停机  D, W6 d7 x- J- `' O/ l' w
  84.         if(count > 250){
    & [8 s; R8 u+ k' b1 _
  85.                 count = 0;
    ) D, X6 D+ T/ q! \' J" }7 y* j
  86.                 isReadyToHalt = 1;, r" u  G# k+ b; g) L; Q
  87.         }; V& u! m! Y4 m+ b
  88. }+ F9 k" K; K8 M
  89. ( f* H6 r5 p8 [" b7 o+ b/ v9 e
  90. static void INT1_Isr() interrupt 2{2 b1 ^$ _1 J5 W# C9 v
  91.         // 矩形波次数累计归零  ]. _8 p" _/ ]2 Z- q% e. g$ ?' g
  92.         count = 0;# m: R' Q) y* W) o1 e1 ~
  93.         // 重开定时器0中断0 T* X9 a( Z! T
  94.         ET0 = 1;# v+ N7 B( i, K3 F$ K( N. h
  95. }
    2 o4 x% r3 o! A- j7 O# |
  96. ; j: B7 [* T  J: ?' k6 ~1 u' [
  97. 0 C+ w& o8 d' U3 a" l
  98. void main(){- k$ J! C& ]: P  V& \, ]4 n$ N8 L
  99.         // 初始化P3和P5口
    ; \) g' E& [+ c3 G+ }' U6 N& `
  100.         GPIO_Init();
    , J" P& @8 _2 b8 k
  101.         // 初始化定时器0
    % g0 j2 S' K# z; ^7 h* u5 p
  102.         Timer0_Init();
    , M: [, J% C& w2 p- X7 {
  103.         // 初始化中断
    5 F: g- B+ S* U7 O' v) n& v
  104.         Interrupt_Init();
    7 E1 h. a" d$ B" B. s3 F: g
  105.        
    $ l0 @& _  D* Y$ J4 j
  106.         while(1){0 X. x6 B) R( v7 y! q/ p$ L
  107.                 // 检测电量
    1 K5 H  `, u2 e+ u9 H
  108.                 if(PCON & (1 << 5)){
    5 K2 u# y1 s/ K1 C
  109.                         // 如果电量低,低压指示灯亮' Q% L0 `' L; ?. N. i5 ^
  110.                         LED = 0;' s7 c: K8 n0 _- `8 u6 \
  111.                         // 清电量检测硬件标志位- P& @* s+ q; k  ]* m( V+ ?
  112.                         PCON &= ~(1 << 5);
    + G! g  c0 t2 S. `& Y: |% L
  113.                 }else{
    * U$ [) C3 ~. ]1 i7 @) ]3 a- x
  114.                         // 电量正常,低压指示灯灭
    ) ^8 l* C5 j  J6 y/ b+ V1 i- D9 E- ?
  115.                         LED = 1;  |3 g& P+ Q0 T* u, d
  116.                 }' l: B1 R# o' a/ I

  117. ( }1 C3 w) D- M" f4 T7 }+ i8 W# {
  118.                 // 检测到停机标志
    0 w8 p9 ]2 t+ P, i- T
  119.                 if(isReadyToHalt == 1){
    ' d# q7 U9 u5 l! h! q$ ]
  120.                         // 暂时关闭定时器0中断! x4 z& i( C1 O. t2 z; b
  121.                         ET0 = 0;4 o1 j5 a5 w8 l
  122.                         // 停机之前先把矩形波输出脚置低电平,以方便INT0和INT1唤醒CPU
    ' \9 W8 L. H% D; u$ _7 _/ r4 W2 h
  123.                         OUT = 0;: v1 a0 Z% Q# W) x2 C1 x
  124.                         // 停机之前先把低压指示灯灭掉,以省电
    4 f: K% {4 I/ ?0 b( O
  125.                         LED = 1;. \" k/ F$ z, O
  126.                         // 进入停机模式
    4 M" V( L4 P) a) c/ E3 ?
  127.                         PCON |= 0x02;
    7 c7 m9 f; J9 U" b
  128.                         _nop_();5 s" p- S/ C% J
  129.                         _nop_();
    / D7 h1 o3 }+ |* D" G3 r; ?
  130.                         _nop_();
    ' H1 ]) P: e9 @$ w5 |) i8 N' |
  131.                         _nop_();5 F) z, w7 B, ]+ j1 c2 |
  132.                         // 唤醒,清标志位
    2 x5 s9 L# H" f: U7 ^* }2 Z
  133.                         isReadyToHalt = 0;  ~8 }8 \- V% O" U8 p; p+ I
  134.                         // 重开定时器0中断7 b9 e' M' X/ Y9 }* l" S: S# ?
  135.                         ET0 = 1;# D! @$ i6 T/ e9 _
  136.                 }
    . W2 p6 p) e5 ~2 H" G* e
  137.         }
    - m! m) o8 H: K7 M0 N+ P7 o
  138. }
    5 \- ^8 y+ k# C7 u  i2 j8 q1 ~
复制代码
. A  ?; V3 C" R; `9 v6 Z; l4 x# @
硬件参数配置:
# X- k! [9 c! i- U. F: @6 I( D! w7 v; U$ ^  P

' o4 d& T; g" r) u* H接收端:! R$ Z, r( L/ e3 V4 n' Z6 w( w
  1. #include <INTRINS.H>
    " ?1 y# S$ D  o
  2. #include "STC15W.h"
    : U7 e( p7 |$ X, t! l+ Q

  3. ' E& U# Q$ l4 g6 J( H* j
  4. % s. i8 q2 Y9 _( E
  5. /*! x) o* p; M! H% H! Q' K: {
  6. 2 U5 ?: I/ _, }3 L! K1 F
  7. *---------------------------*
    $ c" _1 S( N7 k3 z# c: O2 Q
  8. |1 (GPIO2)         \__/  (GPIO1)16|
    ' u* ^6 Z. f8 X  p% k/ ?
  9. |                                                        |& W; Y7 V: S8 X3 K  {9 l9 U
  10. |2 (GPIO3)                   (GPIO0)15|
    + s$ w) t& _1 o& O  A
  11. |                                                        |' b9 q4 W9 Y. y9 f
  12. |3 (GPIO4)                                  14|
    4 G# l; R& x9 o3 J5 D4 D  n
  13. |                                                        |
    ' H. |- c9 y- ^9 m0 c1 s2 R
  14. |4 (GPIO5)                        (DATA)13|
    6 u) ]  t% @/ E
  15. |                  STC15W204S                |4 z3 T& Q( V6 D% A! i, i7 A$ u4 y8 T
  16. |5 (GPIO6)                   (LATCH)12|
    $ i* |, H6 ~3 r
  17. |                                                        |
    4 u/ i/ D- J) _+ F3 S0 X
  18. |6 (VCC)                         (CLK)11|
    , J9 {0 Q* |& A0 A1 h
  19. |                                                          |
    $ \$ {5 O; x4 ~$ r0 x8 R6 X$ j
  20. |7 (GPIO7)                         (TXD)10|
    - i4 \7 g& H- r. g2 ~
  21. |                                                        |
    1 `" C# [! B* q9 i: G: O2 I9 e9 X
  22. |8 (GND)                         (RXD) 9|
    5 s# ~' _8 }1 M# X! h. g& s7 w1 j; j
  23. *---------------------------*% G# j' y7 V- t2 I1 U: L
  24. Fosc = 12MHz
    " w/ ^0 V- _  [" H0 Z

  25. / ^# G1 b) j% G' w
  26. P1.0 -> 上$ `7 Y* T2 E5 @, `" [
  27. P1.1 -> 左* P- @+ s9 \3 f) Y: o* o
  28. P1.2 -> 下
    " \. @  @1 z8 c
  29. P1.3 -> 右8 ?" F  E. c: _) o4 K( T, k
  30. P1.4 -> SEL3 T( Z3 O: ~+ o8 ^+ N, B. e
  31. P1.5 -> STA+ ]: C; }# j- y  X
  32. P5.4 -> B
    * U" P8 `# v% L
  33. P5.5 -> A( ^4 E4 r( P% y  H* l

  34. . ]$ G: C. e7 @. Y  g, b
  35. */5 l% b" a# Z$ Y7 A8 n2 q2 v

  36. % u* T0 I+ G# w7 Q6 b" ?

  37. 9 b. U: E% ]# g$ u
  38. sbit CLK        = P3^2;
    ' r  ^0 A: F0 l% W- y- l
  39. sbit LATCH        = P3^3;( F' x4 p- C* h! T$ m5 o8 \
  40. sbit DATA        = P3^6;
    5 x. c5 W: N3 B3 Y2 ?& h8 C5 j1 `
  41. " g& G6 H, a  M. [9 O& m: D
  42. bit isReady = 0;
    & O3 D: B( S2 `, `% O
  43. static unsigned char key = 0;) A9 B$ b/ g  J! G" N0 W
  44. static unsigned char buf = 0;        // 双缓冲。这个缓冲区保存从P1和P5组合而来的键值
    ) v9 r& c) Z1 O+ f' ~% F
  45. static unsigned char bufReady = 0;        // 双缓冲。这个缓冲区保存上面那个缓冲区的备份
    7 N5 V1 W8 t/ h% f' V+ d6 i
  46. static const unsigned char data mask[] = {0x80, 0x40, 0x10, 0x20, 0x01, 0x04, 0x02, 0x08};        // A B SELECT START UP DOWN LEFT RIGHT。为提升速度,这个表放到RAM中+ R* @" b  A: Y' s3 a& f7 I
  47. static unsigned char idx = 0;6 R+ w. B) m0 g) e# A  a

  48. , N- l9 e5 D+ `9 ^+ h# N
  49. # V# [$ h7 T' s6 f5 ^2 y' `2 ?$ {
  50. static void GPIO_Init(){
    8 E6 k* H# N( R
  51.         // P1口和P5口用于接收并行信号,全部初始化为准双向,依靠内部弱上拉输出高电平1 q) j( l- S4 h
  52.         P1M0 = 0;4 d* ^, K) ~& t3 N) M% A4 `; q
  53.         P1M1 = 0;. t- l7 _, ]9 r" R& A
  54.         P1= 0xFF;4 g5 b- S( C7 ^6 y; f+ K
  55.         P5M0 = 0;7 {) w8 k& [- V; k+ \
  56.         P5M1 = 0;& n0 u! E1 }* e) u' h1 ~
  57.         P5= 0xFF;( Y) m8 a$ l1 w5 V. m
  58.         // P3口初始化为准双向
    # Y4 \6 o4 B% G% `7 D- `# @& x/ Y
  59.         P3M0 = 0;
    - ]: Y0 O) K. Z6 t
  60.         P3M1 = 0;
    & _0 l8 z; ]) }) _% a
  61.         P3 = 0xFF;3 E4 N' d5 M# f6 k
  62. }5 }5 I6 u* F( w

  63. % a1 x. ?. u; b6 V2 G% r! Y- b6 r
  64. static void Interrupt_Init(){
    8 n% [) G/ N% N8 e5 f5 G
  65.         // INT0中断(CLK)触发类型为上升沿+下降沿
    " h4 t4 {$ T% m, c% T" ~
  66.         IT0 = 0;, i2 t: s6 ]$ b0 w/ b
  67.         // 允许INT0中断; W, h! q$ }% E7 t+ q& ^4 t+ N
  68.         EX0 = 1;. C, }+ O- \6 t) X' f* v, p8 \
  69.         // INT1中断(LATCH)触发类型为上升沿+下降沿" \1 l. }6 j3 C" @' f
  70.         IT1 = 0;6 Q- @/ E3 F1 ?, U. s* S6 B
  71.         // 允许INT1中断4 V- e% K; u) {; i0 P1 \8 l
  72.         EX1 = 1;( }  T4 \& }: t/ @' Y
  73.         // 开启全局中断
    , V0 n1 w1 P( f+ o" y
  74.         EA = 1;. ]  C+ v8 T% P! F& ?8 [
  75. }
    % o) A' r$ b6 A# x# m
  76. % c; {/ A) x* P
  77. static void INT0_Isr() interrupt 0{" C1 c: G9 C0 u& ~; X8 d8 ^
  78.         // 只有已经成功锁存才允许CLK移位' p, R/ K0 E' @7 k! w  z  K
  79.         if(isReady == 0)3 a# c* o" I4 C5 l  N2 @6 U
  80.                 return;
    $ M' A" F+ L/ ]8 J
  81.         // 读当前引脚电平,如果是低电平则说明是下降沿,此时直接忽略该中断
    8 n1 o; _8 b& K7 s* a& N+ r0 s! l
  82.         if(CLK == 0)* H; O" T* S; x2 j7 L  d% N
  83.                 return;9 `( M0 h3 Y, z  l" |6 P. X
  84.         // CLK上升沿到来的时候,取锁存值的下一位输出
      a- x* O3 E- I+ c) J9 G
  85.         idx++;8 M, V! T( a* @& e! y( _
  86.         DATA = key & mask[idx];
    ( d8 y0 K6 h$ m9 J) T
  87.         // 如果已经完成7次移位,则一轮读取完成
    6 ^  o+ h* d2 `* f
  88.         if(idx >= 7)
    ' Y1 ]; z4 i1 H9 C- c0 R: m
  89.                 isReady = 0;
    4 [0 ]. F. X! c: _2 i& S, A  D
  90. }
    7 W) e' W2 u; k/ \* t9 r+ K- n: m
  91. % U) c( W( ]$ z; t3 t- |
  92. static void INT1_Isr() interrupt 2{
    9 F- [) c' B& L
  93.         // 读当前引脚电平,如果是低电平则说明是下降沿,此时直接忽略该中断
    9 d8 T- d* f' u4 w
  94.         if(LATCH == 0)( ?/ {$ d; R9 S6 s
  95.                 return;  s+ S# V% Y: @6 \0 y
  96.         // 当LATCH上升沿到来的时候,锁存所有按键状态,同时把键值A输出到DATA/ N  C* d0 ~% N* R
  97.         key = bufReady;
    # K" ^" ]) ^; b2 s7 c9 p# d
  98.         DATA = key & 0x80;//mask[0];        // 为了加速运算,直接取表中的值而不是读表, M3 J2 m2 f; [' v4 n9 R4 w
  99.         idx = 0;1 y2 b" w. l" R5 S
  100.         // 允许CLK进行移位: ^; n$ U9 l# n! k1 @* I3 X  T
  101.         isReady = 1;8 v2 |8 B- e$ w& c" Y0 X2 Q% p; @
  102. }5 w% N! t+ R% W5 J8 @
  103. $ i4 J; M; M( i$ o, y
  104. void main(){. m7 Y" p  z, U- U) q
  105.         GPIO_Init();) h9 t. u+ `& d0 v8 `2 s7 p
  106.         Interrupt_Init();+ a, l6 V" o5 S8 \/ ~( l" Y! @
  107.        
    - V& U6 f% J; W1 D4 {( u
  108.         while(1){
    6 v, P1 R% V2 s# b1 `
  109.                 //PCON |= 0x01;        // 进入省电模式
    5 ?( ?7 |5 v# [
  110.                 //_nop_();
    6 B. I. ^3 D5 _$ a8 }& p$ T
  111.                 //_nop_();
    3 a3 q5 d: V* l- J5 {, I
  112.                 //_nop_();7 \. r# ~# F9 V- h2 P9 @
  113.                 //_nop_();! c/ p0 L* P1 t" A
  114.                 buf = ~((P1 & 0x3F) | ((P5 << 2) & 0xC0));
    ; Q3 C" u! q, Z
  115.                 bufReady = buf;
    9 X2 n8 l# R0 m& e0 g" O* N
  116.         }
    . v, g4 V  v* ~' s4 w4 u
  117. }
    ) B0 }: f0 ?" I
复制代码
. u; R% i* R' i( ^- D
硬件参数配置无特殊要求,晶振频率选择12M即可。& B/ b/ U7 k- }" x9 c6 Q
6 P# R& ]4 |0 C4 l
这是编译好的固件。

本帖子中包含更多资源

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

×

评分

参与人数 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
# t) s  R/ l+ O' p- N$ n不错的设计,想问一下楼主,FC的15针公头怎么解决?普通的公头太短了,插不进去FC的扩展接口。 ...
( P1 N. q  c6 L, O5 f
坛友的改造方案
回复

使用道具 举报

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

使用道具 举报

发表于 2019-5-25 12:07:18 | 显示全部楼层
精彩,楼主动手强,也写得很详细。
' B7 b9 K6 Q! G; W" e2.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
: K/ C" e  N9 r9 |+ F& w7 R精彩,楼主动手强,也写得很详细。1 i, {( U: e9 Q
2.4G方案是目前无线的最低延迟吗?
$ Y& u9 p" m4 }. \/ M
我没用过其他无线手柄,所以实在不知道我自己做的这个手柄到底是不是最低延迟。
6 O6 ~) g+ b- ~2 A4 b不过根据网上的说法,延迟高低主要是由通信协议的复杂程度,以及数据传输速率决定的。这个模块虽然是2.4G无线模块,但由于协议很简单,所以延迟比较低。* ^9 |# N$ w: f; Q$ R: N
我用这个手柄玩一些ACT游戏,比如超级马里奥、忍者龙剑传、热血系列,完全感觉不到延迟,和游戏机自带的手柄没有任何区别。唯一的区别就是这个手柄是用火花山寨手柄改造的,外壳是垃圾回收塑料,粗糙+脆弱,导电橡胶弹性不佳,手感不是一般的差。( G# S: c9 H$ k) K
我手里还有十几张板子,等我有空了我再做一套,到时候买一个好一点的手柄改造。
回复

使用道具 举报

 楼主| 发表于 2019-5-29 16:56:14 | 显示全部楼层
ppad 发表于 2019-5-28 17:279 e/ ]- S9 e1 C) G# w! Q) S5 r
给技术帝赞一个,有半成品发布吗,自己焊接改造就可以,编程实在不会啊 ...

4 s2 \& f$ G! O. |" C5 O很可惜,我手里没有多余的单片机了,LDO也找不到了,锂电池以及充电模块更是没有了。反正就是该用到的元件基本都没了,所以没法发布半成品。
) f1 A& j' @# x两个板子倒是有十几张剩余。( Q8 i: ?- b  n% A+ h& \
你要是有USB转TTL串口板,完全可以自己买这两种单片机,然后我给你编译好的固件,你自己用串口板下载到单片机里面就行了。两个2.4G无线模块也得通过串口板用AT命令设置参数,不过好在我在设计电路的时候就已经预留好了串口,可以直接在线下载和在线设置参数。总的来说并不麻烦。
回复

使用道具 举报

 楼主| 发表于 2019-5-29 17:00:34 | 显示全部楼层
孙大师 发表于 2019-5-28 18:55. N1 o6 j: F* ]" j' w2 J7 R( Q  K
非常好,楼主是技术帝,到目前我都还没开发fc的无线套件,等空了,开发一套套件,等玩家自己组装。 ...
# F( M4 l! V4 d7 y
能得到孙大师的赞誉,不胜荣幸!4 x: i8 @* M& C
不如开发一个多功能手柄,比如用SFC手柄改造,L/R键配合其他组合键可以用来切换2P~4P、调节连发速度、软重启等各种功能。接收端插到15PIN扩展口。
回复

使用道具 举报

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

本版积分规则

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

GMT+8, 2026-9-20 23:33 , Processed in 0.100410 second(s), 15 queries .

Powered by Discuz! X3.5

© 2001-2025 Discuz! Team.

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