找回密码
 注册

QQ登录

只需一步,快速开始

查看: 25883|回复: 32

自制FC无线手柄

  [复制链接]
发表于 2019-5-22 14:16:45 | 显示全部楼层 |阅读模式
本帖最后由 雷精灵2046 于 2019-6-14 09:28 编辑
, a8 `9 [6 `6 J: c0 _
7 {* O, t' D* |6 K4 J4 ]# w- d+ F没有用复杂的分立元件搭建发射接收电路,直接用的现成的2.4G无线模块jdy-40。
' U5 C' G, i. ~4 ~6 T* a6 p& U" H5 |' F; T- K) \5 n# |! w
7 n1 z1 b8 c, O5 ?/ P
发射端靠3.7V锂电池供电,用了一片SOP8封装的STC单片机,负责产生连发脉冲,同时负责检测电池电量,电压低于3V左右的时候触发低压中断,低压指示LED就会亮起来告知该充电了。平时发射模块和单片机均处于睡眠状态,有按键按下才会唤醒,从而实现省电。实测睡眠状态下整机电流约1~2uA。板子洗了一下稍微干净了一点。因为对于微功耗设备来说,焊接残余的助焊剂可能会增加漏电流。
  ^( S! ?" g4 q3 a- a
/ w* Y* j$ ?0 a+ T8 V) Z: E" m9 [买了一个火花的FC山寨手柄,去掉里面的牛屎板子,并修正一下塑料挡板,把锂电池和充电模块装进去。9 A: D' g/ G3 M( u, z' w% F9 b
为了减少体积,充电模块裁剪得十分小,并且更换了充电电阻使之适应这个小小的锂电池。这么小容量的电池,也不需要多么大的充电电流是吧?9 y" b3 R% [/ Q/ @6 F
然后统统用热熔胶粘上。充电电流比较小,所以发热很少,不会熔化热熔胶。, x% @7 ^# v( }- B: q, k

1 o$ f, B0 [. I2 R# D4 N* ?- x( }* M2 L& r
3 J0 a8 e" f5 S  Y3 @
最后把按键、导电橡胶和电路板装上去。$ _+ E2 {6 f; B7 H8 [/ P, `
精心裁剪了电路板,正好扣上,不会阻碍其他元件,也不会影响后盖和拧螺丝。
0 h: t- U* t, F
9 p+ I+ d8 T, y8 u/ {. R
( d/ q6 P0 I& n3 F, P7 R. x完工!( s6 [5 T' V- O4 q' c
$ E2 R7 G# K7 }4 Q
  r3 }: s' h6 ]; A& g) ]
这是充电的MicroUSB插座。旁边的小孔用于透出低压报警LED的光线。8 _; p/ F  J5 m- x. K0 M
. T2 W! }% P, |$ `# E

% j6 Q9 k+ L( P3 F2 h1 {接收端用一片DIP16封装的STC单片机模拟CD4021。为啥要用单片机模拟而不是直接用CD4021?因为jdy-40模块接收端在有按键按下的时候输出高电平,无按键按下输出低电平,和普通手柄正好相反。当然我也可以用两片74HC00或者74HC04之类的逻辑门进行反相,但那就增加了芯片的数量。对于FC手柄这种工作频率并不高的设备来说,STC单片机完全可以胜任模拟工作。
1 i  V- _7 j9 I
* m4 m& {* Q( [9 u5 |: t
/ @! S. |! M4 B1 s* z  k6 f7 [8 H1 }7 S2 b! K5 t- i
电路设计有点小小的错误,所以有几根飞线。原本设计使用低压差LDO是XC6206,结果在做这个接收模块的时候,买的LDO居然找不到了!无奈只好用了AMS1117。幸好对于接收模块来说是5V降到3.3V,1117可以胜任。要是发射端手柄的话,3.7V降到3.3V,那就非得用6206不可了。
  P- `. {6 Q, E7 Y. X; T( q( E' d6 L! U, M* E5 U" n
实测十分灵敏,延迟极小几乎感觉不出来。可惜这山寨手柄的手感并不佳,尤其是方向键,软塌塌的。看来我得买个剪线手柄改装。
( ?8 j) D( N8 ?$ n& Q2 ~. F2 E$ D. M- O- f
这是电路图,有兴趣的朋友可以参考。9 C$ H; A7 d" N0 y' e) n% }8 _

: s$ o7 w: w6 ?/ v( s8 u# `3 [' ]. n0 w4 R
我信奉开源主义,十分痛恨把技术藏着掖着。好东西大家分享嘛!所以两个单片机的源代码大公开!" d) G( }8 s4 B
编译器:Keil 51。
' q  A% N) Y4 l% k
! X& @% }8 [6 _  c) z+ X0 y发射端:0 A/ d6 E7 `- }
  1. #include <INTRINS.H>
    # P3 c' K1 E+ \" W; ]
  2. #include "STC15W.h"
    # _9 p3 M( {& S  d1 \+ C

  3. 9 M# ?1 l; n2 Z! B. I9 m' W) c

  4. / r5 k( d) b4 g2 u) u6 e3 r7 k
  5. /*
    " g1 b- U9 _3 C- ?
  6. --------------------------
    6 `0 ~8 w  k( I( y! H, L
  7. |1 (OUT)        \__/   (INT1) 8|
    $ f  }5 M: [6 G( X: X
  8. |                                                   |/ T  L7 g( J" Z% @- `
  9. |2 (VCC)                   (INT0) 7|: g2 [" P4 l, Q- i
  10. |                 STC15W204S                   |% d+ k$ r3 V: A0 j+ l# ~7 c
  11. |3 (LED)                         (TXD) 6|
    7 L/ s4 ^3 k8 t. S2 s; I7 b% E
  12. |                                                   |
    2 z; r) D$ a& Y* |8 Q, j; u+ Q
  13. |4 (GND)                         (RXD) 5|  c. T: ^2 R; j( [; N
  14. --------------------------
    1 ^8 G. C4 s! p2 t$ M

  15. 0 A9 y' J, g' C* n7 c
  16. LED ---|<|---[===]--- VCC
    5 W1 A/ B1 [- Q  K5 M
  17.            Red          330; ^8 w4 P% {6 \2 e# Y
  18. & q8 i- G- }$ C3 e# W
  19. Fosc = 6MHz' j3 {) C) o8 N1 f, u
  20. */
    & S! @5 o" X# N

  21. ) @3 y9 f; @0 ?
  22. - W: S* D9 a9 x% D$ |( L! m1 X
  23. // 矩形波输出脚# @: r/ {. ^# j3 g
  24. sbit OUT = P5^4;5 v' l2 Z+ w" V
  25. // 低压指示灯引脚2 ~9 ?( c' O6 @' O6 |+ z" Z
  26. sbit LED = P5^5;- v) g* ?- G. K8 ]7 r2 v4 ~2 Z

  27. 6 |+ j) e. d6 R' o/ Y7 d
  28. // 停机标志位
    ; ?1 M9 O. c6 h
  29. bit isReadyToHalt = 0;' ?* h  f% l: v$ e) U
  30. / A: b9 N' z/ O2 l# p
  31. // 矩形波次数累计+ h6 s( R, ]9 Z0 n
  32. static volatile unsigned char count = 0;* T/ ^1 ^6 ]9 Y% f, z2 O, ^& ?
  33. ) g( ~! H- w) h9 X
  34. * @  |  A$ h8 {8 r) f9 L6 g
  35. static void GPIO_Init(){' h$ z3 \# D% q) t  k* G
  36.         // P3口设置为准双向,默认靠内部弱上拉输出高电平+ e, }( ?/ V2 k( b5 F
  37.         P3M0 = 0;
    ) \: S+ N0 g! [# _2 I
  38.         P3M1 = 0;
    7 h0 U) S. u- B7 R- s8 M
  39.         P3 = 0xFF;" a7 X* O: `$ l) W; p  |2 W5 L
  40.         // P5口设置为准双向,默认靠内部弱上拉输出高电平
    " r5 N" x; k1 [, y, N+ e5 |, x5 C
  41.         P5M0 = 0;# D: I+ x8 M) T# b0 y
  42.         P5M1 = 0;
    4 ]# I" T) M) U& i
  43.         P5 = 0xFF;" B1 k- A- p" P
  44. }& B2 O* L. W. C$ _
  45. 0 e0 ~" E: l( l. x0 }$ r, l
  46. static void Timer0_Init(){
    * a3 ?1 H9 t3 j/ Q' I( h
  47.         // 16毫秒@6.000MHz, L1 {8 w; Y$ e, g; Y
  48.         AUXR &= 0x7F;        // 定时器时钟12T模式
    + G* w+ @& O" f# s
  49.         TMOD &= 0xF0;        // 设置定时器模式
    6 W, E$ y; Z, K, G2 A. V' Q
  50.         TL0 = 0xC0;                // 设置定时初值
    " H4 @7 \* Q- C- U" i" R
  51.         TH0 = 0xE0;                // 设置定时初值* m+ Z% r  h: O; K6 r7 T
  52.         TF0 = 0;                // 清除TF0标志
    0 f+ j2 i" K! U* n# y5 O0 X
  53.         TR0 = 1;                // 定时器0开始计时! ^$ v6 Z, X. R9 ]9 @0 z
  54. }
    8 O& k( j2 }9 m% F: w3 m

  55. - P; Z; r* o0 n, l4 _: @
  56. static void Interrupt_Init(){
    / U& E  H% L5 x3 o' V; J" F; {
  57.         // INT0中断触发类型为下降沿触发
    - T- B& a* ^1 d8 Y# u" G
  58.         IT0 = 1;% Q% A. {  _, |6 a! B8 M, Q
  59.         // 允许INT0中断$ }' d& j2 v- W- t; H
  60.         EX0 = 1;
    0 @5 B9 w: ^9 j: M6 X" X. K6 p/ T
  61.         // INT1中断触发类型为下降沿触发
    , [$ T& N4 e8 z4 ^/ c; p
  62.         IT1 = 1;. a- o: {; p$ A( t
  63.         // 允许INT1中断2 j- k% z$ ^; l8 t' O
  64.         EX1 = 1;
    ) z& ?6 W% H: X9 \. x
  65.         // 允许定时器0中断7 @$ I7 [9 p! n
  66.         ET0 = 1;3 M1 z9 _. W  W+ s5 `8 o
  67.         // 允许全局中断
    , j0 E2 \) H" F# u4 U6 U
  68.         EA = 1;1 H. Z" I% z$ f3 X: W& g: y
  69. }5 d! v7 F4 J3 x$ n, d0 \
  70. ) _8 d" g6 O1 I6 T; o
  71. static void INT0_Isr() interrupt 0{
    * m2 |+ Y# J3 N# o- w3 _; h( {" ]: [
  72.         // 矩形波次数累计归零) f& c: W1 ?- s
  73.         count = 0;
    5 x( _( O3 K# ~5 k2 A- l
  74.         // 重开定时器0中断4 K% j( r: Q" H
  75.         ET0 = 1;8 V& h- J# x  {1 o% ~6 Q3 f
  76. }
    * ?" x8 p5 f- N. I
  77. * Y& l# y9 C. v$ I4 I
  78. static void Timer0_Isr() interrupt 1{2 m3 g4 d, t8 C+ E7 U
  79.         // 输出矩形波
    & R/ z$ {' n2 D. J+ N& }6 y1 q
  80.         OUT = ~OUT;
    * j  f5 [/ c0 \1 ?. \
  81.         // 累计矩形波次数
    : c: u  ?0 t5 `1 w, K
  82.         count++;7 }9 g" g; \, ]) d: }" p
  83.         // 超过250个矩形波,准备停机
    ( }& X" v/ r1 d7 ]7 W
  84.         if(count > 250){3 c, a4 ]4 |& J% P
  85.                 count = 0;2 W9 n) N7 o1 @4 J& G5 n: `0 @
  86.                 isReadyToHalt = 1;: g/ Z0 [4 u1 u2 G" p: `
  87.         }) R& q* H# L" Z) o: X! r
  88. }
    0 R' q! d$ \9 H  r+ Z7 v

  89. 4 Z) S' y: s0 W1 f$ b% ]3 t  s4 U5 V
  90. static void INT1_Isr() interrupt 2{
    . @$ e1 C3 ?, t3 e1 X
  91.         // 矩形波次数累计归零  l: M- m- V! [( o! U
  92.         count = 0;) U0 B0 ]% w( ^$ r
  93.         // 重开定时器0中断- X, l' D+ E, g1 K1 H. Q
  94.         ET0 = 1;% K) g" t3 D( J$ q6 m* ]9 p6 e
  95. }' y, O3 Z. E4 d5 z

  96. 9 |+ _) k# q7 N' p& @7 X

  97. & K5 t+ q# `( z: n! b
  98. void main(){
    - Q6 R4 ^  g' B) C
  99.         // 初始化P3和P5口5 v0 _* k6 R" e0 D7 a/ H  r
  100.         GPIO_Init();
    8 N$ o' A* @7 g: w  H* C& _
  101.         // 初始化定时器0" K. o% F# U! [7 T) U2 L$ V
  102.         Timer0_Init();
    . O) ^, V  R* D. m6 M+ `
  103.         // 初始化中断: u9 N5 w$ }, ^5 r  B( W
  104.         Interrupt_Init();, U) D% p7 v; a8 `  |
  105.        
    7 p3 e3 J3 Z" b" m' |% Z0 Z
  106.         while(1){
    5 B7 I3 T+ u1 r- n2 u
  107.                 // 检测电量
    3 s# o, J% J3 X: m0 |3 B3 a9 i
  108.                 if(PCON & (1 << 5)){
    9 I$ P7 r: c, p; x; R3 ^
  109.                         // 如果电量低,低压指示灯亮
    4 q* R, @6 @) C- z8 o
  110.                         LED = 0;2 x$ w" p( H) [/ u- d. k7 R
  111.                         // 清电量检测硬件标志位9 Z' `2 e$ t8 z3 X/ h& \3 K: j$ D
  112.                         PCON &= ~(1 << 5);6 A! G" Z/ k* u/ A
  113.                 }else{
    & R8 T' _# a) X
  114.                         // 电量正常,低压指示灯灭/ [1 w) E, G) c# y! X' w5 P
  115.                         LED = 1;
    & d& k( q* a# [3 F8 D, A6 `  ]
  116.                 }
    % Y) b( `' t& u1 o+ J
  117. * T1 x$ ?: y' J0 d( I
  118.                 // 检测到停机标志+ v1 z4 s9 u: F8 J
  119.                 if(isReadyToHalt == 1){
    : K# V  p* R; R2 [: ~4 F+ x
  120.                         // 暂时关闭定时器0中断/ C( _# J, [* Q! B; {7 X# g
  121.                         ET0 = 0;
    + w9 i" d3 n4 X
  122.                         // 停机之前先把矩形波输出脚置低电平,以方便INT0和INT1唤醒CPU& \/ S  Z8 N0 i$ n
  123.                         OUT = 0;8 e8 z/ @6 n9 a+ p" J
  124.                         // 停机之前先把低压指示灯灭掉,以省电
    6 o& z9 m' ~. T+ l( x( ]. [- b7 r
  125.                         LED = 1;
    - N; g4 n% J! t4 O
  126.                         // 进入停机模式8 U( d, s+ i) i; c/ f# _) Z
  127.                         PCON |= 0x02;
    : d! q$ P& Z8 V! `, o6 Z; q
  128.                         _nop_();( B) J9 x3 W+ o) a
  129.                         _nop_();
    - z0 `9 w) f: i+ O) r
  130.                         _nop_();
    - I" Y0 ~4 @! {9 e* c
  131.                         _nop_();- T2 x! g" q5 E4 J4 v
  132.                         // 唤醒,清标志位
    $ g7 A; x2 q" k% E7 u
  133.                         isReadyToHalt = 0;- c' ^' A5 {0 v6 q9 r+ f3 V1 j: P
  134.                         // 重开定时器0中断* c) w, F7 {1 G+ l6 y6 o
  135.                         ET0 = 1;0 `# y* J+ \. }% Y
  136.                 }
    0 i% f% R/ E# e. i  ~. V3 y
  137.         }
    : H  A& S' D# `' n7 H% n# s
  138. }
    7 {, H! y' ]% N; [
复制代码

: H" g9 O6 K" S( q6 v# E硬件参数配置:6 @' s0 ^( _! f9 E& p  K5 q
$ @8 _/ ]7 C- P8 a) N
% c) R& h: K3 N1 q
接收端:  h" Z; J) u1 s( N! ]( N# X1 b
  1. #include <INTRINS.H>
    $ V) B. T% S5 w% ^
  2. #include "STC15W.h"
    $ Z: b* r* f% [: k

  3. 4 N( R( R! W- ]6 C' i$ v" l

  4. 7 i$ F3 ~+ q4 b( j9 m
  5. /*
    % k0 p( ~$ j7 |7 v/ t
  6. 5 m  a/ U, y$ M, y* k' a; A" m
  7. *---------------------------** p% N$ @8 b& w9 |4 ^
  8. |1 (GPIO2)         \__/  (GPIO1)16|0 z2 W' `9 t6 y* s7 P, U3 w! Y
  9. |                                                        |: H0 u: ^) L2 C# ?+ Q' x
  10. |2 (GPIO3)                   (GPIO0)15|. y1 m+ g5 z. E: ~
  11. |                                                        |
    , ~# y# ], W* b5 U" \' U5 I; |/ ~6 P% z
  12. |3 (GPIO4)                                  14|
    $ r' I  w3 a3 y; k9 w
  13. |                                                        |  a5 h. o) ^8 z. J5 C& ?2 a
  14. |4 (GPIO5)                        (DATA)13|: [( `" U  O) g! z- _
  15. |                  STC15W204S                |$ b) q$ Y* W6 y( M' C9 b- Q
  16. |5 (GPIO6)                   (LATCH)12|
    " T6 L  A+ z% e' y7 y! Z5 {
  17. |                                                        |, H3 C' |$ `5 x) M: ?3 e. ~% }
  18. |6 (VCC)                         (CLK)11|
    8 P& x5 A3 s) S' v; f( I
  19. |                                                          |# a3 k5 K5 N) d
  20. |7 (GPIO7)                         (TXD)10|
    1 n4 R8 j8 O. z7 \% Y
  21. |                                                        |: _% {, q& ~/ I7 W9 p
  22. |8 (GND)                         (RXD) 9|
    ( t8 P# H8 z5 u, u. t1 ]1 w0 a( C
  23. *---------------------------*2 P6 z0 R1 U* v3 \* ^0 i. J" Q
  24. Fosc = 12MHz% @9 |4 y- J/ n( w( \# T

  25. 6 t6 u# C8 B* R
  26. P1.0 -> 上
    - D4 g3 ]  X8 v" W7 u6 P, d: u
  27. P1.1 -> 左- E5 T" {8 W" C# x: {; f# y2 L" _
  28. P1.2 -> 下, W# x& b8 t& i8 `# k) V  P6 u
  29. P1.3 -> 右
    ( g. P: v- R  I  O. ~7 D
  30. P1.4 -> SEL' [/ |% Y" o" u: L0 g  E) A8 W$ p
  31. P1.5 -> STA
    / R3 t# T+ h0 {' e# R0 Q) s
  32. P5.4 -> B
    ( L% S9 o7 |  {3 E6 u
  33. P5.5 -> A
    ' e8 ?/ N3 o0 T. m3 i! G

  34. ) D2 G! ~" i1 I/ p: X
  35. */+ c6 Z+ n3 a0 C* M) {8 }- x2 M0 J2 A
  36. . D+ G* e( T/ u1 h5 B
  37. 2 I" w6 v9 v& J! G3 K' d4 E
  38. sbit CLK        = P3^2;
    6 G  R' g; X3 S' b4 w! y. n
  39. sbit LATCH        = P3^3;
    ) S9 S. Y1 o* Q
  40. sbit DATA        = P3^6;9 a' q& o  g$ _. b: k0 W! G
  41. 9 ~2 n. Z( _1 Q1 Z! T
  42. bit isReady = 0;
    ( b; }5 d( ^' E$ _. k6 R
  43. static unsigned char key = 0;4 K  o: A7 H; F. j. z0 D9 K7 M" z
  44. static unsigned char buf = 0;        // 双缓冲。这个缓冲区保存从P1和P5组合而来的键值
    / \6 N  s! x! O- y6 q
  45. static unsigned char bufReady = 0;        // 双缓冲。这个缓冲区保存上面那个缓冲区的备份
    . f" ]6 p" Z" h" D4 B0 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中
    3 z7 N! Y  M# h4 c3 a* O5 x3 c
  47. static unsigned char idx = 0;1 Z. J5 A8 O9 G1 E5 x

  48. / d  e2 d% c! c2 X- c

  49. , `1 D) ^( G* V  K+ A
  50. static void GPIO_Init(){
    ! K9 `3 R+ U; u& k) A# H; B1 r
  51.         // P1口和P5口用于接收并行信号,全部初始化为准双向,依靠内部弱上拉输出高电平
    ' P; J% r. c. t  C1 `# B
  52.         P1M0 = 0;9 D3 `% E. x( ]( o' t8 U- p' f
  53.         P1M1 = 0;3 p! O9 q2 M3 r, ?- [2 ?
  54.         P1= 0xFF;
    * C2 k: A; W+ e) W( v4 o
  55.         P5M0 = 0;7 k8 q6 V' V% Y1 R& n5 |. H# ]( H0 E
  56.         P5M1 = 0;/ @# z: @9 c( K0 p% R* s
  57.         P5= 0xFF;
    ( F2 k* B! y5 k( ^" O# l  ?. D. N
  58.         // P3口初始化为准双向' }2 Q6 N( }, w! V7 V6 t% g4 N
  59.         P3M0 = 0;5 x0 e. ^5 r  A* Z
  60.         P3M1 = 0;! W5 A' j( a+ {  m1 s) g
  61.         P3 = 0xFF;: f7 m& v+ K7 y. _7 K$ ^! q+ _
  62. }+ V( U; T2 P1 E- Z+ a

  63. - l" g" z5 `2 J0 G- v" E* p1 e& H
  64. static void Interrupt_Init(){" b. u* g; D+ z3 M
  65.         // INT0中断(CLK)触发类型为上升沿+下降沿( `, E4 w+ t% W: s" l5 h' ?0 M% C
  66.         IT0 = 0;( ?6 t- T3 K) Z; g) D4 x( D
  67.         // 允许INT0中断
    3 f9 h( B$ \  h
  68.         EX0 = 1;: O4 b5 H8 v  _' ?; |# E) ]# l
  69.         // INT1中断(LATCH)触发类型为上升沿+下降沿
    0 L, f/ g, c5 S* t: W
  70.         IT1 = 0;
    ) r: k; ~- L3 ]& i
  71.         // 允许INT1中断
    / S& @+ b" z: |5 |+ b
  72.         EX1 = 1;
    9 z+ q  f8 L2 _. W% K  T
  73.         // 开启全局中断' g# u# t( \; p1 ]0 F, y( R
  74.         EA = 1;
    ! d  a0 t5 Q9 S& ^  O) U: H$ {9 N- U
  75. }; _+ u$ i. t( w: E* m7 [
  76.   F) F! H5 u6 D. l
  77. static void INT0_Isr() interrupt 0{
    2 d+ {3 ^2 x5 \0 P* J9 ]4 D
  78.         // 只有已经成功锁存才允许CLK移位
    # A% K# [( e3 |9 L, W7 X4 [8 s6 H
  79.         if(isReady == 0)+ u% w) z8 z3 g
  80.                 return;$ J1 T2 g' w! V) X3 [
  81.         // 读当前引脚电平,如果是低电平则说明是下降沿,此时直接忽略该中断) E1 _. X2 l+ h4 ?- R! x% r, V  A
  82.         if(CLK == 0)) B( x& F4 r8 p2 q5 L4 L
  83.                 return;
    * o+ l/ N3 [9 P$ H
  84.         // CLK上升沿到来的时候,取锁存值的下一位输出
    + Q8 b* s- u: i0 y6 M
  85.         idx++;
    2 I0 S0 \: G: y8 c0 I5 A8 v3 q
  86.         DATA = key & mask[idx];
    8 J" B$ f  }; n' G! G) [; ]; ^
  87.         // 如果已经完成7次移位,则一轮读取完成. j: ^/ d& `, Q8 ^# Y0 R
  88.         if(idx >= 7)* z* `7 G" |) u: P( X, {: I
  89.                 isReady = 0;
    4 _. N! h6 ?+ Q& ]+ Z0 Y6 w0 S# a
  90. }0 i  a- f5 i! H; H* `

  91. * i' P5 ]0 B% m
  92. static void INT1_Isr() interrupt 2{
    ; b0 F& w& Q0 \- B1 D
  93.         // 读当前引脚电平,如果是低电平则说明是下降沿,此时直接忽略该中断- y* B0 n) P6 Y+ I3 P6 S
  94.         if(LATCH == 0)
    ( `& u- C: T, v5 l, p. e
  95.                 return;# e4 o. e% y8 O! v5 L
  96.         // 当LATCH上升沿到来的时候,锁存所有按键状态,同时把键值A输出到DATA
    8 Y' @* U8 C' j/ x( r9 }
  97.         key = bufReady;
      j, A9 B$ t3 r3 r* T+ b
  98.         DATA = key & 0x80;//mask[0];        // 为了加速运算,直接取表中的值而不是读表
    " A  W9 U' J2 w% x
  99.         idx = 0;
    6 F5 D+ O1 A7 t+ u* _9 `" [; A
  100.         // 允许CLK进行移位
    % h3 e" F6 A- E. L3 g9 Z
  101.         isReady = 1;
    ) f' x/ Q* q4 I7 `
  102. }2 i. h. O2 s% @- g5 x: I# W

  103. ' S: ?% v) u$ a
  104. void main(){1 G  T; |, U) U2 V% K1 ^
  105.         GPIO_Init();
    , q) W' M# v& n* L+ Y3 a
  106.         Interrupt_Init();, d9 J) b, H  f( P# L  \( n
  107.        
    8 z; g) n5 A  e; v
  108.         while(1){
    , V/ w- [+ s; V# x; W+ L3 k
  109.                 //PCON |= 0x01;        // 进入省电模式
    . Q* d' E' P& @3 y" u7 ]( q' W
  110.                 //_nop_();/ z' @/ J+ u- r, q$ w
  111.                 //_nop_();
    % [9 l2 I; W) p9 c' D: k# Y) h
  112.                 //_nop_();
    ; E! T3 x1 d8 |, m2 M- U
  113.                 //_nop_();
    1 X/ i$ g# G4 o$ _$ a4 p$ e
  114.                 buf = ~((P1 & 0x3F) | ((P5 << 2) & 0xC0));
    : v5 o/ C; z7 ^  W2 Q1 t7 t
  115.                 bufReady = buf;
    , F2 C! J+ i7 W0 z4 Y2 _6 N
  116.         }/ v) x8 x1 u: [; F5 l1 o* L* K
  117. }
    9 r$ i( f4 @- n% N6 a
复制代码
2 [+ I4 X5 E$ g, a+ F6 K
硬件参数配置无特殊要求,晶振频率选择12M即可。
: S, Q. H+ ~& s4 _+ k, D
4 Z! s/ y% t. u2 H) d+ K这是编译好的固件。

本帖子中包含更多资源

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

×

评分

参与人数 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:050 F- U8 ]$ `5 k0 S1 ~  a4 n
不错的设计,想问一下楼主,FC的15针公头怎么解决?普通的公头太短了,插不进去FC的扩展接口。 ...
- N$ e* x, v" S3 f
坛友的改造方案
回复

使用道具 举报

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

使用道具 举报

发表于 2019-5-25 12:07:18 | 显示全部楼层
精彩,楼主动手强,也写得很详细。5 `9 e( U: I' }
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
, }: {) k" X. K5 o; ?精彩,楼主动手强,也写得很详细。
7 d! U& a& j0 f$ i1 }2.4G方案是目前无线的最低延迟吗?

' O1 d/ v$ m5 T' J我没用过其他无线手柄,所以实在不知道我自己做的这个手柄到底是不是最低延迟。1 V; n' i+ C' _" I+ t. \- w' T9 Y
不过根据网上的说法,延迟高低主要是由通信协议的复杂程度,以及数据传输速率决定的。这个模块虽然是2.4G无线模块,但由于协议很简单,所以延迟比较低。1 g: O1 k4 N& M/ w& g" s
我用这个手柄玩一些ACT游戏,比如超级马里奥、忍者龙剑传、热血系列,完全感觉不到延迟,和游戏机自带的手柄没有任何区别。唯一的区别就是这个手柄是用火花山寨手柄改造的,外壳是垃圾回收塑料,粗糙+脆弱,导电橡胶弹性不佳,手感不是一般的差。
- Z5 |: ~8 |' c% x我手里还有十几张板子,等我有空了我再做一套,到时候买一个好一点的手柄改造。
回复

使用道具 举报

 楼主| 发表于 2019-5-29 16:56:14 | 显示全部楼层
ppad 发表于 2019-5-28 17:27
: n1 h7 h. w  [) f/ i- ]! ]给技术帝赞一个,有半成品发布吗,自己焊接改造就可以,编程实在不会啊 ...

% E% e$ |% s! X' J很可惜,我手里没有多余的单片机了,LDO也找不到了,锂电池以及充电模块更是没有了。反正就是该用到的元件基本都没了,所以没法发布半成品。
# }# f  t  E/ E两个板子倒是有十几张剩余。+ z: c: A, ^2 N7 J5 O( d/ p
你要是有USB转TTL串口板,完全可以自己买这两种单片机,然后我给你编译好的固件,你自己用串口板下载到单片机里面就行了。两个2.4G无线模块也得通过串口板用AT命令设置参数,不过好在我在设计电路的时候就已经预留好了串口,可以直接在线下载和在线设置参数。总的来说并不麻烦。
回复

使用道具 举报

 楼主| 发表于 2019-5-29 17:00:34 | 显示全部楼层
孙大师 发表于 2019-5-28 18:552 |* n; e* l( E& ?
非常好,楼主是技术帝,到目前我都还没开发fc的无线套件,等空了,开发一套套件,等玩家自己组装。 ...

% O- ~7 {- j" ]9 A: d能得到孙大师的赞誉,不胜荣幸!
% p2 V' Z! y5 d- y) j1 P不如开发一个多功能手柄,比如用SFC手柄改造,L/R键配合其他组合键可以用来切换2P~4P、调节连发速度、软重启等各种功能。接收端插到15PIN扩展口。
回复

使用道具 举报

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

本版积分规则

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

GMT+8, 2026-7-12 19:13 , Processed in 0.106936 second(s), 14 queries .

Powered by Discuz! X3.5

© 2001-2025 Discuz! Team.

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