找回密码
 注册

QQ登录

只需一步,快速开始

查看: 24336|回复: 32

自制FC无线手柄

  [复制链接]
发表于 2019-5-22 14:16:45 | 显示全部楼层 |阅读模式
本帖最后由 雷精灵2046 于 2019-6-14 09:28 编辑 0 x0 |% u5 @: B# _

$ x$ g0 y  r- N1 U. C7 |没有用复杂的分立元件搭建发射接收电路,直接用的现成的2.4G无线模块jdy-40。6 X  R& w. S' ?( g

' f$ q; j/ s- b, o5 O0 u$ a1 f% M8 h1 b
发射端靠3.7V锂电池供电,用了一片SOP8封装的STC单片机,负责产生连发脉冲,同时负责检测电池电量,电压低于3V左右的时候触发低压中断,低压指示LED就会亮起来告知该充电了。平时发射模块和单片机均处于睡眠状态,有按键按下才会唤醒,从而实现省电。实测睡眠状态下整机电流约1~2uA。板子洗了一下稍微干净了一点。因为对于微功耗设备来说,焊接残余的助焊剂可能会增加漏电流。! q1 m2 A8 O5 {! r% t5 o8 L
6 b: z3 J0 G5 X
买了一个火花的FC山寨手柄,去掉里面的牛屎板子,并修正一下塑料挡板,把锂电池和充电模块装进去。
1 r( f; s% J4 d" N* Q为了减少体积,充电模块裁剪得十分小,并且更换了充电电阻使之适应这个小小的锂电池。这么小容量的电池,也不需要多么大的充电电流是吧?
2 ]8 T2 }) G+ M1 p/ O. U3 |% p' u然后统统用热熔胶粘上。充电电流比较小,所以发热很少,不会熔化热熔胶。
2 C% v; R& U: F' h% o. B' \5 f1 k. V
7 Y! f4 ^/ g; b& S1 w
  N8 |9 e8 X5 w- D% c/ Q2 c; j. T% p8 f4 I' g
8 B# b- ]2 h$ \; g6 k/ C/ t. r) u; C最后把按键、导电橡胶和电路板装上去。1 [5 w* n! f! c: M) y
精心裁剪了电路板,正好扣上,不会阻碍其他元件,也不会影响后盖和拧螺丝。
% `1 S! R  Q: D* @9 k
. Y; P! I9 [; b$ x( H6 z* e4 I- X; V- j: J& a4 B9 Y0 ~- r; [
完工!& m# ?" n1 j- c* u! i8 q8 N

1 w& z. h/ Q! Y3 b
0 Q2 O7 N+ c* k) \! Q+ P这是充电的MicroUSB插座。旁边的小孔用于透出低压报警LED的光线。1 X* m0 D1 U2 `9 f
* A2 B. o# ~1 a  @4 }, R% j% _  S
9 r/ N) G0 J4 A5 \5 U9 W3 Q
接收端用一片DIP16封装的STC单片机模拟CD4021。为啥要用单片机模拟而不是直接用CD4021?因为jdy-40模块接收端在有按键按下的时候输出高电平,无按键按下输出低电平,和普通手柄正好相反。当然我也可以用两片74HC00或者74HC04之类的逻辑门进行反相,但那就增加了芯片的数量。对于FC手柄这种工作频率并不高的设备来说,STC单片机完全可以胜任模拟工作。. s) M+ G4 k5 f3 T9 U: b9 ^
6 X, p4 R( Q8 a7 b% |

2 }6 _3 k/ d9 ~  O3 t$ s( J" M2 Y. B
, g. Q, l8 C, G$ E/ T0 H电路设计有点小小的错误,所以有几根飞线。原本设计使用低压差LDO是XC6206,结果在做这个接收模块的时候,买的LDO居然找不到了!无奈只好用了AMS1117。幸好对于接收模块来说是5V降到3.3V,1117可以胜任。要是发射端手柄的话,3.7V降到3.3V,那就非得用6206不可了。
8 D+ g! O+ T9 a" r+ u0 X0 ]/ I
% c2 c# l2 a0 X! G+ r  ?实测十分灵敏,延迟极小几乎感觉不出来。可惜这山寨手柄的手感并不佳,尤其是方向键,软塌塌的。看来我得买个剪线手柄改装。
3 \! l) h+ y6 X- e( R0 j6 w8 g8 Y6 w1 R7 t9 q5 G
这是电路图,有兴趣的朋友可以参考。, l2 e* |) G- O0 w" m( e

$ W3 I' }$ [1 {( l( b
  [' ?) D1 G- m% [6 [0 k" r5 ?我信奉开源主义,十分痛恨把技术藏着掖着。好东西大家分享嘛!所以两个单片机的源代码大公开!2 M& R( ^( z  D2 y5 N- b7 t
编译器:Keil 51。
% A- s" i7 R& t( i) M, T/ W8 @
3 U2 I5 }' u4 h& x: Q3 {发射端:0 H- }3 x7 y8 }( N# @6 P
  1. #include <INTRINS.H>
    9 ^& K, [& D; D. G$ R) j0 @9 L
  2. #include "STC15W.h"
    7 ]! X& f0 s, r* @
  3. , [; l9 L% j; }+ C! G
  4. ) A  }9 @; l2 r# P5 y
  5. /*
    2 P# g4 l8 h) d/ G0 B; P+ U
  6. --------------------------8 s( r; ~0 v- c) q. e1 R; s
  7. |1 (OUT)        \__/   (INT1) 8|
    ; z5 w( n# F; m/ J( m3 M7 B& i
  8. |                                                   |3 ]$ R0 [" z6 E& F( X. q
  9. |2 (VCC)                   (INT0) 7|
    ( |- p. ?8 K3 H1 `  i" X# D
  10. |                 STC15W204S                   |
    8 \, b8 {% c+ _6 x4 H0 t
  11. |3 (LED)                         (TXD) 6|3 Q/ e1 `5 n0 w! K- Q2 B0 F
  12. |                                                   |+ h5 y6 c4 g* x! p
  13. |4 (GND)                         (RXD) 5|* D* o" X( n/ K) S4 W, H$ C
  14. --------------------------5 T3 A  {( y9 o6 I3 K3 r" [+ b( s
  15. 2 O* `2 d& c! |, t* O
  16. LED ---|<|---[===]--- VCC0 e- D  I& `: H' G6 @$ a! u7 K! }
  17.            Red          3309 y6 r9 W$ u! w% U) D. U4 u3 u9 D

  18. ' S, a9 |, a+ G9 g" m# p) P; ~% U
  19. Fosc = 6MHz
    " p1 u  f0 `, X4 g
  20. */
    # x5 r* e. N5 H  V) O3 |

  21. * L0 d/ p+ L$ f
  22. / N$ F- s8 d& e+ D
  23. // 矩形波输出脚
    % j. v; k6 A" H3 n2 c
  24. sbit OUT = P5^4;
    - r3 ^. W5 ~) Q
  25. // 低压指示灯引脚8 Q! j8 X+ f$ n. K0 @& ]! v; s
  26. sbit LED = P5^5;
    7 ?' I% x9 H( G0 }9 O
  27. 2 o5 s* i8 Z2 z# I9 U% L
  28. // 停机标志位
    ; W* l  S2 n6 Z' T
  29. bit isReadyToHalt = 0;/ t5 h1 f4 o( f3 H
  30. 3 w4 l3 [+ ]/ {( w; F
  31. // 矩形波次数累计
    0 T6 r, M. }+ p+ F
  32. static volatile unsigned char count = 0;4 ^' J2 x/ X6 _
  33. / w* {# d/ Y9 G9 P1 l

  34. + Q& U  G- ^2 M  Y4 v# b" j' A
  35. static void GPIO_Init(){  D6 w# V4 {1 h3 Y
  36.         // P3口设置为准双向,默认靠内部弱上拉输出高电平6 T; G6 b  _4 o! |: z# k! A; U4 z8 a
  37.         P3M0 = 0;+ w, r. R( g7 w/ B& q$ K
  38.         P3M1 = 0;8 A1 e+ v! q8 \! n" Y+ k
  39.         P3 = 0xFF;
    ) o) I1 n8 m8 z( S$ P
  40.         // P5口设置为准双向,默认靠内部弱上拉输出高电平
    3 g- ]* S* f4 o3 i5 g
  41.         P5M0 = 0;
    ' R$ v5 a3 u/ j) K
  42.         P5M1 = 0;! ?: q3 ?: h3 L$ }
  43.         P5 = 0xFF;
    ! p- |1 `$ j6 |* o3 F7 R
  44. }% N4 p- [' b4 u4 o0 o( @1 O
  45. / G1 b9 `: w+ z9 y
  46. static void Timer0_Init(){: m( J' D; X; L) q& G2 D- y
  47.         // 16毫秒@6.000MHz
    6 o4 O& C0 d" r
  48.         AUXR &= 0x7F;        // 定时器时钟12T模式
    5 @" s, Y7 j  R! T  b. N6 b
  49.         TMOD &= 0xF0;        // 设置定时器模式
    / G4 d  P( ]" E2 N" e
  50.         TL0 = 0xC0;                // 设置定时初值9 i0 A5 s" {+ Q
  51.         TH0 = 0xE0;                // 设置定时初值
    & p$ ~# e' x  k, B6 t8 u' n
  52.         TF0 = 0;                // 清除TF0标志
    6 X. [7 \: N, d1 i- O
  53.         TR0 = 1;                // 定时器0开始计时. F" O. C* i' [1 j# b
  54. }* ?' Y3 l  V( o0 N
  55. & w9 {3 y( s* Q: [: Z! y8 G/ E3 t
  56. static void Interrupt_Init(){: Z" Q  \4 H' ]/ D* w/ [! R, ~
  57.         // INT0中断触发类型为下降沿触发
    , `& f* P3 S5 ^: \! q
  58.         IT0 = 1;4 x4 P* {7 Z$ N2 B  \) M
  59.         // 允许INT0中断! y; s' ]' b  e, Z. u+ B
  60.         EX0 = 1;$ \  Z+ n8 `" b7 I5 j# Y
  61.         // INT1中断触发类型为下降沿触发3 u( Q8 N' X" A6 }- r, h" w
  62.         IT1 = 1;
    ) X& ^- L7 S/ T. _) O( |. s$ Z' N
  63.         // 允许INT1中断3 r* r9 q7 m7 I7 q" |& g- b6 Z! R
  64.         EX1 = 1;
    5 x) v7 z9 N3 L; \& A
  65.         // 允许定时器0中断
    & K/ W, M! ^! ?9 K# u/ X* _
  66.         ET0 = 1;
    4 Y* h4 V8 n$ g  f0 v6 i3 T, @
  67.         // 允许全局中断
      t9 G8 K, X2 P; t( N0 p
  68.         EA = 1;* Y8 D& X7 C; [9 F7 R
  69. }
    ' d0 I7 z5 _. J6 R8 I- B9 q
  70. 4 Z5 o( W; W# C7 a1 f
  71. static void INT0_Isr() interrupt 0{
    3 n& K1 o; J6 V$ v
  72.         // 矩形波次数累计归零: M2 h0 z. ?, s: j2 h! B
  73.         count = 0;
    ' P5 v7 h2 J$ a
  74.         // 重开定时器0中断5 _, \& s% z; s6 \/ S$ q8 B
  75.         ET0 = 1;1 T; H6 [; ~  q' ~! ~/ G
  76. }
    : X4 o' M* Q9 \

  77. 4 M( T1 t3 q0 a6 v: [3 ?
  78. static void Timer0_Isr() interrupt 1{- b& f. C0 f  c1 N/ W0 p
  79.         // 输出矩形波
    9 d2 Q$ Q, ~4 g
  80.         OUT = ~OUT;
    8 ^8 ]" [; K: k) ?$ F
  81.         // 累计矩形波次数
    6 S) @( t7 d. d6 [
  82.         count++;8 K9 I6 b8 O0 I0 }' T# a
  83.         // 超过250个矩形波,准备停机  b9 T4 Z5 y' |4 }; d' ?
  84.         if(count > 250){
    , H  h1 N; M9 J% q+ `
  85.                 count = 0;/ u& ^' H0 B2 M7 @* x, N, N0 w& N
  86.                 isReadyToHalt = 1;
    ) t( B# N% L8 T( c% C/ u! w
  87.         }
    " \+ x, u/ B* m; Y+ @+ `& i( @5 _! a
  88. }
    ! B# H; b- f* E, }
  89. , F" ~9 H' w* J; c4 t9 F9 W
  90. static void INT1_Isr() interrupt 2{% T* m: j9 {& [# B+ H7 Q
  91.         // 矩形波次数累计归零2 o) Z' u7 c+ M" W2 N( {
  92.         count = 0;/ U" q* x# D- Q3 m: [1 S
  93.         // 重开定时器0中断
    3 n2 t! [1 C. P1 N. ]; p
  94.         ET0 = 1;
    / w; g# b6 {( h; S) r
  95. }2 K# D* K; k& L0 A$ d' V6 J
  96. # J/ Q+ K' A: g1 Q' J

  97. 3 |7 A8 z2 r! m* B3 s7 m
  98. void main(){( \* e. i- n; k  z6 o
  99.         // 初始化P3和P5口
    ' o- O+ z1 I/ ~0 N  i- N2 j! e
  100.         GPIO_Init();
    , `& q6 Y) B2 d7 @& a, m
  101.         // 初始化定时器0" d6 V. d8 F& D4 u2 p- [' e
  102.         Timer0_Init();
    3 I$ Q7 I4 _8 B+ x
  103.         // 初始化中断+ v: r$ e) Z4 f4 L* B$ ^# J
  104.         Interrupt_Init();
    - |0 ~, N6 I3 u5 n! t. l
  105.        
    1 X" O4 N1 @0 U* I5 v0 {" S
  106.         while(1){
    4 L; W1 M  r& Y) [/ {% H
  107.                 // 检测电量
    " N7 a8 {( ~8 P: l2 O3 b% H
  108.                 if(PCON & (1 << 5)){
    ! z9 j7 J( e( U8 k( M/ d
  109.                         // 如果电量低,低压指示灯亮
    ! ^) f; a4 k9 q. ^; H
  110.                         LED = 0;/ e0 y; H2 r4 x! ]! |& Y# {
  111.                         // 清电量检测硬件标志位# T! V/ z5 T( N; H- j  l
  112.                         PCON &= ~(1 << 5);
    / R: C8 v' D) Q7 |$ n4 I
  113.                 }else{
    8 B2 R& v1 {% o- |* O- r
  114.                         // 电量正常,低压指示灯灭
    ; O% q+ k( C( R0 O
  115.                         LED = 1;
    * p  ]  |$ {" ~8 x$ f
  116.                 }( D! y. j: x; U% A- I& o8 ]/ i7 G( c

  117. ) w& ?! _' x" R6 y* g, m: h% o5 t
  118.                 // 检测到停机标志
    4 s% V/ B$ n) ?( J$ B2 h; P
  119.                 if(isReadyToHalt == 1){$ D" o& f# d* Z* G( K
  120.                         // 暂时关闭定时器0中断
    0 m8 [7 h4 n: d9 ?1 i$ e9 D  A) U
  121.                         ET0 = 0;% a) q# }, L* Y# g4 i1 a
  122.                         // 停机之前先把矩形波输出脚置低电平,以方便INT0和INT1唤醒CPU8 i9 d% W+ f# o6 L9 A
  123.                         OUT = 0;
    ; r. |+ z7 `& v, `* l7 p
  124.                         // 停机之前先把低压指示灯灭掉,以省电
    + Z0 p$ U; a4 S6 Y3 u4 _) D4 a
  125.                         LED = 1;
    / K  @7 y  C1 r1 Y* u, D
  126.                         // 进入停机模式
    ( y% Q) y4 Y" p( A; r
  127.                         PCON |= 0x02;
    : I! P6 _! E, @& k: E" m
  128.                         _nop_();
    2 Q4 z1 U  |; V
  129.                         _nop_();
    6 N2 ^( j) N  Q" m
  130.                         _nop_();
      |- L$ c& a8 [
  131.                         _nop_();
    * l$ l% L' V* r! U5 J, R
  132.                         // 唤醒,清标志位
    ' t$ }: U* X6 e: H
  133.                         isReadyToHalt = 0;1 f. c" Z8 k1 w; X. x, I
  134.                         // 重开定时器0中断
    7 N& k9 J& x+ R; Z! M
  135.                         ET0 = 1;
    1 H: {5 n4 ]: P! Y/ a" j7 m1 a
  136.                 }
    : d9 {- ^! b$ G6 z+ ~8 W" C
  137.         }
    1 `( f4 u9 }9 q# [% @9 q
  138. }
    # ~+ ^9 b1 v4 l9 O8 P- H% [7 J
复制代码

6 w: e: ]0 [9 h8 P& W4 g8 X5 p硬件参数配置:. i8 H. @! i" }2 v( j9 a3 N

' Z4 k1 j3 O2 Z, D; W
' x& ~) ~1 n) L2 U接收端:& r1 S9 \5 }- s0 X% ]. i
  1. #include <INTRINS.H>
    2 k, _" `; D$ D/ @' P
  2. #include "STC15W.h"
    , l& R7 Z$ A( L. _! _( n# \
  3. * a- t" n% ?: }8 o+ f7 K7 e7 |- c" D  r
  4. 7 i8 S* L# L9 U4 _. i: N( [: }
  5. /*
    * F; N' R8 P: W" q
  6. & x) ]3 r7 u. }7 y$ u$ {1 n3 e
  7. *---------------------------*
    ) `% `. A* k" f4 }8 D+ V& D
  8. |1 (GPIO2)         \__/  (GPIO1)16|
    4 `, V4 T1 k' u) K1 p" C: ~. o
  9. |                                                        |
    3 a6 x/ M6 C+ K, T% ~
  10. |2 (GPIO3)                   (GPIO0)15|+ D8 A$ n" `# M1 T2 K* k! G. c
  11. |                                                        |* s- L  k. f! U9 N1 C9 D1 [! E
  12. |3 (GPIO4)                                  14|, L" o( t6 N" u. v/ m& b
  13. |                                                        |, d5 W. b, V, I$ p* O  t# c6 e
  14. |4 (GPIO5)                        (DATA)13|
    ) g) f- c$ m/ t- F, Y+ D# K) C
  15. |                  STC15W204S                |; _1 K  M" {7 D  ]
  16. |5 (GPIO6)                   (LATCH)12|8 ~0 ~: y+ f1 f. ?
  17. |                                                        |3 m% Y4 g9 a3 [0 I9 n
  18. |6 (VCC)                         (CLK)11|3 e9 P1 v/ }* j  H. H
  19. |                                                          |$ J: Y2 r7 W" _' S9 o& o
  20. |7 (GPIO7)                         (TXD)10|
    + w1 g2 X' k5 H/ U* d& c
  21. |                                                        |7 Q* X" ^! Q+ s7 L# [' l) g
  22. |8 (GND)                         (RXD) 9|
    % B& i1 s7 q3 a$ b2 Y% {
  23. *---------------------------*% W5 n! ~. Q  F4 y* c  r; S
  24. Fosc = 12MHz6 F& v1 Q) f/ P

  25. * ^) S0 R# r0 Y) e9 K* R
  26. P1.0 -> 上
    % O: M3 `2 y6 [4 a
  27. P1.1 -> 左
      [9 H  h* S& w4 m. t( ]+ F5 S$ g9 e4 B- S
  28. P1.2 -> 下
    " b% J" T8 U, [! h- K# z2 L0 }
  29. P1.3 -> 右
    ' V9 Y# {) Y3 T( T! v
  30. P1.4 -> SEL
    # h/ d9 I2 F- m& Z1 Z
  31. P1.5 -> STA
    ( J4 `8 M% s8 b
  32. P5.4 -> B$ Q+ l# R1 L9 S3 u: B. G& I% d
  33. P5.5 -> A6 Y( D1 }; q5 y& n# F' U& O

  34. 9 ~* T$ T6 z5 m  z1 S6 ~& f
  35. */
    , f5 s: {5 v' A% y3 b

  36. 1 P3 E+ ?# C; ^

  37. . y& [4 \( W# k& l& I, `
  38. sbit CLK        = P3^2;
    # d$ m) y% n9 Q% q1 f/ I8 u% i2 R% Q
  39. sbit LATCH        = P3^3;: i2 z  k0 L8 o/ S
  40. sbit DATA        = P3^6;
    7 Y! ~9 f* n+ L

  41. ) Z& m1 B2 ?9 @' a
  42. bit isReady = 0;
    % ~- f, o' U. L" y4 S0 O
  43. static unsigned char key = 0;' V2 w; P- u7 B$ Z# j6 |
  44. static unsigned char buf = 0;        // 双缓冲。这个缓冲区保存从P1和P5组合而来的键值6 [$ o0 `1 Z) ]
  45. static unsigned char bufReady = 0;        // 双缓冲。这个缓冲区保存上面那个缓冲区的备份
    " X& k8 o3 E$ T$ z+ V- |9 F
  46. static const unsigned char data mask[] = {0x80, 0x40, 0x10, 0x20, 0x01, 0x04, 0x02, 0x08};        // A B SELECT START UP DOWN LEFT RIGHT。为提升速度,这个表放到RAM中8 m8 M- ?3 J' f4 L( e9 S
  47. static unsigned char idx = 0;
    ' Z9 f9 [8 F1 W  `

  48. : w4 X% \- I9 ?5 l+ ~5 W3 J
  49. 2 L* _7 x0 D$ J0 k4 Y9 M1 c
  50. static void GPIO_Init(){1 {! I% j5 R$ G
  51.         // P1口和P5口用于接收并行信号,全部初始化为准双向,依靠内部弱上拉输出高电平
    5 ?* g, R& t: E0 U, S  m; v
  52.         P1M0 = 0;
      m# w) f& ?# W4 X
  53.         P1M1 = 0;
    3 ~. K! w4 w7 {8 k. c8 I
  54.         P1= 0xFF;2 M# ]; y0 H; E% E9 Y! a: u. P* f
  55.         P5M0 = 0;3 q/ Q) o8 L8 S% t: P1 S; d+ y
  56.         P5M1 = 0;
      {1 T: V2 s4 d$ y7 e9 T
  57.         P5= 0xFF;
    2 T9 P! k- w2 P( ]$ _5 {+ W. @; W
  58.         // P3口初始化为准双向
    1 p8 N7 U# N/ R
  59.         P3M0 = 0;
    ! b- X, }  q( h+ t
  60.         P3M1 = 0;% z/ [6 a; R+ s( r$ z5 p, n; D
  61.         P3 = 0xFF;6 g" X# u  x* ?  N, t. Q1 l0 C$ v
  62. }
    2 W3 c( B! s9 ]. |4 r

  63.   S3 x# I. C8 ]- K) }, `
  64. static void Interrupt_Init(){
    7 L. [) c, f, l* {4 `% M$ m3 _% N! @
  65.         // INT0中断(CLK)触发类型为上升沿+下降沿5 |7 u6 N0 ]2 i( e+ G6 L4 u! Z
  66.         IT0 = 0;8 A2 H2 z6 l( D( {
  67.         // 允许INT0中断8 v1 S* L" M. s8 h' }
  68.         EX0 = 1;
    8 E8 ~  m. X2 I# G
  69.         // INT1中断(LATCH)触发类型为上升沿+下降沿
    : x" Z5 a8 o' B' U& A. N+ h" A
  70.         IT1 = 0;
    ) g2 i9 e+ s, q6 y5 U. ~. r
  71.         // 允许INT1中断
    + L- q: }) v! L' d% O, E/ m( R8 [
  72.         EX1 = 1;
    1 i' m2 a  u& J4 O) |8 y* D4 E
  73.         // 开启全局中断
    + W9 b, g1 u  o
  74.         EA = 1;& }/ N4 E$ k. P  d6 {. a( y* Z  ]
  75. }( d/ O9 o# ]2 R

  76. 0 P9 [4 S# T2 L5 {8 }
  77. static void INT0_Isr() interrupt 0{
    9 B. `1 f0 |6 A! b
  78.         // 只有已经成功锁存才允许CLK移位2 B* A; V8 r  p( i' ~
  79.         if(isReady == 0)  F0 w; t) A) }8 F
  80.                 return;
    4 Z5 X; F2 V2 s: j! q  v% S: F
  81.         // 读当前引脚电平,如果是低电平则说明是下降沿,此时直接忽略该中断
    + u& [0 z7 [% Z& F/ v) c' ^9 P* C
  82.         if(CLK == 0)' N, b% b) F2 C6 k0 d" z; B
  83.                 return;0 X% \" R9 M6 Y8 k
  84.         // CLK上升沿到来的时候,取锁存值的下一位输出
    + I/ b+ y1 O. }9 }
  85.         idx++;0 ?1 a- I. L7 Z$ M2 p6 ~
  86.         DATA = key & mask[idx];
    # C% r* F; ]9 F" \8 y, P! X0 K1 d% U
  87.         // 如果已经完成7次移位,则一轮读取完成" ^' P& j$ x. z; q( X
  88.         if(idx >= 7)
    - R' B0 {/ S5 |
  89.                 isReady = 0;& _& {& X" W: a! W; G
  90. }
    . R5 i0 w" c9 U; p& i! p" a
  91. # k5 F6 G7 h8 B, q7 D. W4 _/ C" u3 A
  92. static void INT1_Isr() interrupt 2{
    $ l8 t0 ~0 K9 A) E
  93.         // 读当前引脚电平,如果是低电平则说明是下降沿,此时直接忽略该中断: {' G. b, m! l" H- C6 c
  94.         if(LATCH == 0)1 k# g7 Z' h- C1 p' {8 ~1 c
  95.                 return;
    - K' n0 q4 z" d. b& l
  96.         // 当LATCH上升沿到来的时候,锁存所有按键状态,同时把键值A输出到DATA
    6 l+ }. G) j. T, g; @$ X; \& [
  97.         key = bufReady;
    ! s  k) ~5 F8 }2 E' m  ?
  98.         DATA = key & 0x80;//mask[0];        // 为了加速运算,直接取表中的值而不是读表
    7 D1 d$ T! R( z  h. x
  99.         idx = 0;
    7 ?9 U$ D& Q8 E3 s3 S. Y; s' J
  100.         // 允许CLK进行移位& u8 @0 T. O4 S
  101.         isReady = 1;2 y8 H4 O, Y: n& K  m
  102. }
    , D9 S: [/ N$ [2 x
  103. 2 b/ K2 G9 u8 J( u
  104. void main(){
    7 J  _3 l' M( C2 E# M2 a# ?  K
  105.         GPIO_Init();! y7 N5 [* G' h  s* Q* X4 @% w0 p
  106.         Interrupt_Init();
    % m: T/ i+ i& p7 Q. @
  107.           m+ R# B2 K! x$ W, ^% Z$ i
  108.         while(1){0 j% {0 q9 S- V9 b. ]: n
  109.                 //PCON |= 0x01;        // 进入省电模式/ y$ N1 a  o) a2 {
  110.                 //_nop_();
    9 W& g. w* e7 X" `
  111.                 //_nop_();& A7 I8 V6 [, y4 ~6 ]
  112.                 //_nop_();
    ; w6 x' Z; J( Y1 X% x1 }
  113.                 //_nop_();) h0 t! `9 i/ j! ~$ N$ f! X
  114.                 buf = ~((P1 & 0x3F) | ((P5 << 2) & 0xC0));: l  b. J+ j" E3 p  P2 S9 i
  115.                 bufReady = buf;2 l1 ]' @$ k$ Q8 ?) c8 E; b# Y* g
  116.         }& d/ Y& M% U1 t' h, n. \
  117. }
    . v; S/ p; Q: M) Z1 \
复制代码
+ c2 v# q3 D5 m5 [: v" Z
硬件参数配置无特殊要求,晶振频率选择12M即可。
) ~4 ^/ q- M0 @, t4 I: A  s+ j* S* R* e, r$ e
这是编译好的固件。

本帖子中包含更多资源

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

×

评分

参与人数 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, y9 q4 {7 D: H; w) K
不错的设计,想问一下楼主,FC的15针公头怎么解决?普通的公头太短了,插不进去FC的扩展接口。 ...
, m# W* f! `) K. A; W. Y' j" U2 K
坛友的改造方案
回复

使用道具 举报

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

使用道具 举报

发表于 2019-5-25 12:07:18 | 显示全部楼层
精彩,楼主动手强,也写得很详细。9 F3 c8 L5 p3 {- N* G
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% a/ C& u& n, @. |. x- a; B9 D
精彩,楼主动手强,也写得很详细。
  r& M+ a2 Z% z8 c+ r+ R% s) g0 ]2.4G方案是目前无线的最低延迟吗?
6 m% y" a: Q4 {+ Y7 {. z  @9 Y
我没用过其他无线手柄,所以实在不知道我自己做的这个手柄到底是不是最低延迟。  d! p; H/ A# `3 g3 z( E# I( B: a( ^/ c
不过根据网上的说法,延迟高低主要是由通信协议的复杂程度,以及数据传输速率决定的。这个模块虽然是2.4G无线模块,但由于协议很简单,所以延迟比较低。
- w4 E3 H$ O: O/ R! K4 X; |7 i1 Z' U我用这个手柄玩一些ACT游戏,比如超级马里奥、忍者龙剑传、热血系列,完全感觉不到延迟,和游戏机自带的手柄没有任何区别。唯一的区别就是这个手柄是用火花山寨手柄改造的,外壳是垃圾回收塑料,粗糙+脆弱,导电橡胶弹性不佳,手感不是一般的差。
4 ]) D9 h1 E% d$ S6 k) y* N2 Z我手里还有十几张板子,等我有空了我再做一套,到时候买一个好一点的手柄改造。
回复

使用道具 举报

 楼主| 发表于 2019-5-29 16:56:14 | 显示全部楼层
ppad 发表于 2019-5-28 17:27
1 {2 d5 \  Z3 h0 e! X给技术帝赞一个,有半成品发布吗,自己焊接改造就可以,编程实在不会啊 ...
% {$ v9 {0 A6 M* Z- W
很可惜,我手里没有多余的单片机了,LDO也找不到了,锂电池以及充电模块更是没有了。反正就是该用到的元件基本都没了,所以没法发布半成品。$ Z$ j1 c- E/ ^" e) s
两个板子倒是有十几张剩余。" n+ k# E  @; ?* u- G- w2 Y
你要是有USB转TTL串口板,完全可以自己买这两种单片机,然后我给你编译好的固件,你自己用串口板下载到单片机里面就行了。两个2.4G无线模块也得通过串口板用AT命令设置参数,不过好在我在设计电路的时候就已经预留好了串口,可以直接在线下载和在线设置参数。总的来说并不麻烦。
回复

使用道具 举报

 楼主| 发表于 2019-5-29 17:00:34 | 显示全部楼层
孙大师 发表于 2019-5-28 18:55% K' |* P! V# g0 A/ A: A9 Y: s
非常好,楼主是技术帝,到目前我都还没开发fc的无线套件,等空了,开发一套套件,等玩家自己组装。 ...

: O6 q5 ~0 N& @9 f' w" q能得到孙大师的赞誉,不胜荣幸!3 y9 V9 w6 Z: [! n+ `8 d8 w4 @$ u/ H, W
不如开发一个多功能手柄,比如用SFC手柄改造,L/R键配合其他组合键可以用来切换2P~4P、调节连发速度、软重启等各种功能。接收端插到15PIN扩展口。
回复

使用道具 举报

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

本版积分规则

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

GMT+8, 2026-3-27 18:54 , Processed in 0.112587 second(s), 14 queries .

Powered by Discuz! X3.5

© 2001-2025 Discuz! Team.

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