找回密码
 注册

QQ登录

只需一步,快速开始

查看: 26163|回复: 32

自制FC无线手柄

  [复制链接]
发表于 2019-5-22 14:16:45 | 显示全部楼层 |阅读模式
本帖最后由 雷精灵2046 于 2019-6-14 09:28 编辑
. Z4 f6 X: `! M1 b/ {3 V+ i4 Z& _' e: h& R$ U* e* w4 W
没有用复杂的分立元件搭建发射接收电路,直接用的现成的2.4G无线模块jdy-40。
! q5 L# w4 q2 P- o% {; [4 i3 L0 U6 f0 l
6 \0 f; l! _! J: a! l
发射端靠3.7V锂电池供电,用了一片SOP8封装的STC单片机,负责产生连发脉冲,同时负责检测电池电量,电压低于3V左右的时候触发低压中断,低压指示LED就会亮起来告知该充电了。平时发射模块和单片机均处于睡眠状态,有按键按下才会唤醒,从而实现省电。实测睡眠状态下整机电流约1~2uA。板子洗了一下稍微干净了一点。因为对于微功耗设备来说,焊接残余的助焊剂可能会增加漏电流。4 B8 ]1 B& |9 _2 ~  u5 f
, r8 T7 b& F1 h( H* `% m5 b& U, g' ^
买了一个火花的FC山寨手柄,去掉里面的牛屎板子,并修正一下塑料挡板,把锂电池和充电模块装进去。6 c2 ]5 L# ~; R7 k4 s. \
为了减少体积,充电模块裁剪得十分小,并且更换了充电电阻使之适应这个小小的锂电池。这么小容量的电池,也不需要多么大的充电电流是吧?
, i; N$ \$ X6 a/ q然后统统用热熔胶粘上。充电电流比较小,所以发热很少,不会熔化热熔胶。# b6 U- z5 E; ]
/ c  m5 _) q2 E

1 S% |- H* {1 {  q4 ~$ X/ m7 G! T0 @) h
最后把按键、导电橡胶和电路板装上去。3 c0 Y) p; v* U9 X
精心裁剪了电路板,正好扣上,不会阻碍其他元件,也不会影响后盖和拧螺丝。, K# F/ u8 l% `& P+ d; P

% T$ R9 T4 H6 ~+ N+ B7 ^3 m+ V2 l0 A5 u+ j- P9 W: t: Z
完工!7 ?: F. g* t6 k. i
  S" c* ?, r8 i0 c
: G8 L5 t! T) s; D  r& j
这是充电的MicroUSB插座。旁边的小孔用于透出低压报警LED的光线。5 U" P1 s% q7 c+ d) C) J

' V: J) @) x5 P; i3 z. n# \+ {1 n; y: P5 ~# t8 T6 p# m- F
接收端用一片DIP16封装的STC单片机模拟CD4021。为啥要用单片机模拟而不是直接用CD4021?因为jdy-40模块接收端在有按键按下的时候输出高电平,无按键按下输出低电平,和普通手柄正好相反。当然我也可以用两片74HC00或者74HC04之类的逻辑门进行反相,但那就增加了芯片的数量。对于FC手柄这种工作频率并不高的设备来说,STC单片机完全可以胜任模拟工作。
4 Z0 s. o: L+ `! r. O! F
) o7 M* H) C7 ~/ p" y% g! i5 s1 `6 l) z9 j0 _, Y
2 ?# E5 U  K4 m; K0 R1 e* j
电路设计有点小小的错误,所以有几根飞线。原本设计使用低压差LDO是XC6206,结果在做这个接收模块的时候,买的LDO居然找不到了!无奈只好用了AMS1117。幸好对于接收模块来说是5V降到3.3V,1117可以胜任。要是发射端手柄的话,3.7V降到3.3V,那就非得用6206不可了。2 ?  `& h; a8 y+ a
1 F+ T/ D* a2 A+ Q1 i+ ]
实测十分灵敏,延迟极小几乎感觉不出来。可惜这山寨手柄的手感并不佳,尤其是方向键,软塌塌的。看来我得买个剪线手柄改装。' Z1 M& |4 R. C& K0 a/ a  S

0 ]4 P: i" j2 a5 U这是电路图,有兴趣的朋友可以参考。3 {+ k. M9 M& T2 H

8 z+ @9 t/ O/ T& L' v- u" M( t! h/ s8 [( ^: _. |. t
我信奉开源主义,十分痛恨把技术藏着掖着。好东西大家分享嘛!所以两个单片机的源代码大公开!3 ]0 I) q( i3 h; y* ^
编译器:Keil 51。3 t. O1 s" P! y/ R1 X9 ]+ J* ]2 O

, E7 t$ ^3 ]+ H发射端:
% d0 x2 g3 q/ y' ?$ y* a0 m
  1. #include <INTRINS.H>' x' _& o; q! P4 h4 P+ |( Q+ v
  2. #include "STC15W.h"
    ) v0 w$ S9 b$ M1 G
  3. 8 |- }& W- h, t' K8 I

  4. 3 u2 H: Q& O0 P* A& E% Y
  5. /*
    9 G+ R" V# a$ B8 n8 _5 k
  6. --------------------------6 x9 R$ B5 L9 H0 Q
  7. |1 (OUT)        \__/   (INT1) 8|
    0 q; |9 d2 \2 D) U9 H- J$ @
  8. |                                                   |
    9 ^# D; x& k( \9 A" K. o# x
  9. |2 (VCC)                   (INT0) 7|1 V/ J* G, y9 N0 l4 @
  10. |                 STC15W204S                   |
    ! q% y% Z0 y* U- ?1 N
  11. |3 (LED)                         (TXD) 6|. n0 S; a" B. d5 @5 s
  12. |                                                   |
    ; n4 a3 M) J+ H. R
  13. |4 (GND)                         (RXD) 5|$ t0 r1 R% W. M4 S* l
  14. --------------------------1 W7 w% y+ B  J! G% H! k

  15. ! n; o+ i, ?/ |  D9 h, |
  16. LED ---|<|---[===]--- VCC# @( @3 ?" s/ X" S3 P) z  I
  17.            Red          330
    0 ]$ G$ u( g$ O6 e
  18. , |- H+ Z" w/ v( ]  f. \6 P
  19. Fosc = 6MHz! f% _- u0 I4 O7 [# O$ Y
  20. */! y/ f6 ?0 e. z. R2 E- L) x
  21. 8 w/ n" l4 _+ W) j

  22. 1 L& H! _( m4 K% _) x4 D9 U+ ]
  23. // 矩形波输出脚
    5 ]" G; K1 K; S. _% W- s% G6 W/ u
  24. sbit OUT = P5^4;
    7 w9 X0 n  H3 t$ \$ G
  25. // 低压指示灯引脚6 l' }$ r* I, {2 C
  26. sbit LED = P5^5;' s" ]) e% L9 |. X0 D) D9 O8 s' i

  27. 6 i: S6 e0 h; t
  28. // 停机标志位
    $ _6 v8 O' g' O+ e; T
  29. bit isReadyToHalt = 0;4 ~5 A( y/ G  M4 A/ P1 w3 J
  30. 2 |9 l) \  T  x, z" g5 _1 f- e
  31. // 矩形波次数累计4 X0 x# _; k3 p' D  X! b5 n5 E' s
  32. static volatile unsigned char count = 0;
    + ^# A3 ]9 E4 H7 N3 }/ `
  33. - `& A5 s# _2 S. C4 C7 t

  34. 2 }5 @. S0 Z- }4 ^- r3 n8 L" V) y% U
  35. static void GPIO_Init(){
    9 l. p& O& H* Y8 m8 T
  36.         // P3口设置为准双向,默认靠内部弱上拉输出高电平
    0 A: L0 f+ {2 z
  37.         P3M0 = 0;
    8 X2 I9 A; ^3 B
  38.         P3M1 = 0;% Q; X+ R, [, K$ j
  39.         P3 = 0xFF;. b+ V  T0 w1 }' m1 T1 Y
  40.         // P5口设置为准双向,默认靠内部弱上拉输出高电平
    + S3 q6 q+ C& H
  41.         P5M0 = 0;
    % I- E1 `/ \4 ]) d% [
  42.         P5M1 = 0;
    4 i/ `% w7 E0 B; ?* G5 ^) J
  43.         P5 = 0xFF;
    ) T# {. m0 H3 s9 t2 c3 K* ~
  44. }
    # K+ t  P- G, |

  45. 0 q1 V6 [) E- B* ~* |; ?. Z# U( {
  46. static void Timer0_Init(){& u  S6 y* n" \8 g; y6 {. y
  47.         // 16毫秒@6.000MHz
    0 q2 `8 ]) r# ~# r1 h/ \
  48.         AUXR &= 0x7F;        // 定时器时钟12T模式
    5 v& ?/ V* D* T  k) n
  49.         TMOD &= 0xF0;        // 设置定时器模式6 s& \9 q- |7 X9 a( V/ `
  50.         TL0 = 0xC0;                // 设置定时初值
    ( h# U8 r, e: s2 J: P) W$ f% T
  51.         TH0 = 0xE0;                // 设置定时初值2 y8 }+ F; @, q7 R0 G
  52.         TF0 = 0;                // 清除TF0标志& g  ?1 x* y( t( Y$ e! b# ]  k, C
  53.         TR0 = 1;                // 定时器0开始计时
    / G, C. M- L+ u
  54. }
    ' w  x9 r5 U+ ^

  55. ) _# a2 V: B' w( x) j" n7 z
  56. static void Interrupt_Init(){
    % W' v- g! b! H; m2 h- l! `
  57.         // INT0中断触发类型为下降沿触发
    " o, c# h! x& e; E
  58.         IT0 = 1;
    . _$ T8 F9 `4 ?
  59.         // 允许INT0中断/ n4 i9 O+ P. Y3 M7 I; Z
  60.         EX0 = 1;. E3 U8 U! ~* z. ?7 q+ z" n
  61.         // INT1中断触发类型为下降沿触发. X7 _4 S$ g1 @& C+ |0 h
  62.         IT1 = 1;/ _/ Q9 A4 K9 X, x; ~* v
  63.         // 允许INT1中断  a% A4 n0 Z( k' K& \1 Q' d- ~+ j
  64.         EX1 = 1;
    1 t: y4 \$ e- p) m( ?- c3 u& J
  65.         // 允许定时器0中断$ k  d" i2 P; s- d& B& ^7 h
  66.         ET0 = 1;
    / k9 G$ h7 ?, P% s3 q) Z" f" a
  67.         // 允许全局中断
    5 {1 \' B2 Y  }8 w# F
  68.         EA = 1;
    0 \; `5 j1 n0 P
  69. }
    " j7 S4 F3 {2 d! L

  70.   o% i* C, Y4 L
  71. static void INT0_Isr() interrupt 0{6 n5 z$ x( n2 |; `0 I+ E
  72.         // 矩形波次数累计归零, U5 L! }/ N4 m; G+ G
  73.         count = 0;% \" X9 C6 U' M% @- T
  74.         // 重开定时器0中断' ]! U( z3 T! P  \7 |
  75.         ET0 = 1;) q5 n9 X* x" g0 e
  76. }! _" x5 }1 G+ \; p  F7 _& w
  77. 8 [6 `3 I$ U6 E: n; J- k1 c
  78. static void Timer0_Isr() interrupt 1{/ \, @1 U# ?/ Q# i2 M! }; T. e
  79.         // 输出矩形波5 w  p6 U. ?! D7 X0 E9 x
  80.         OUT = ~OUT;
    ' E' C6 w& I8 q' M3 j. q
  81.         // 累计矩形波次数1 a6 J/ n1 D  ?
  82.         count++;$ X) Y) O' G" Q, i+ W
  83.         // 超过250个矩形波,准备停机5 X! y: s, L7 {6 m" |. Q! {
  84.         if(count > 250){: a% _" k' k0 c3 p( r7 ]4 t! v. N2 ^
  85.                 count = 0;
    # [- @. _' S1 B% L/ O7 i
  86.                 isReadyToHalt = 1;0 a. N- F8 L2 |* |5 P
  87.         }$ m2 z- @- M, t+ q  F
  88. }) W3 ]& W' t" G1 q: F5 V

  89. 6 v  V4 I2 I4 w! b; m4 d# U
  90. static void INT1_Isr() interrupt 2{: f3 l' c' {* e! h- {- {
  91.         // 矩形波次数累计归零
    5 F. g, @/ C* I4 V8 P0 X
  92.         count = 0;% I6 s0 ~! r* o3 s/ d5 M6 ]) u; D3 E$ R
  93.         // 重开定时器0中断5 v7 Z5 h# }* q- _3 F8 b3 y
  94.         ET0 = 1;% Q% }- V8 M& ^+ G
  95. }
    % R% w! B5 A$ U

  96. . M- S: C7 m, c8 ]/ k2 j2 [/ C. D. s9 ]

  97. 9 H, Z* H9 g4 v' r# o
  98. void main(){
    * A7 G; m. M6 Q+ U2 _, }: l
  99.         // 初始化P3和P5口( [' q' G8 x- G
  100.         GPIO_Init();
    2 r, F" r; q" ^/ c. o0 i
  101.         // 初始化定时器0
    3 U# E; l2 J+ G( D0 ~
  102.         Timer0_Init();; h# H# o0 x- G3 Q! ?. q
  103.         // 初始化中断
    " m) l2 {# U7 p+ [# o
  104.         Interrupt_Init();1 ~" \& h+ I- O; w9 T
  105.         % N3 W. f0 f# J6 [
  106.         while(1){
    8 m, s" U6 D  v# A% N7 j
  107.                 // 检测电量: G. H2 v# A! Y
  108.                 if(PCON & (1 << 5)){
    ( w  R+ S$ r0 P4 d& D
  109.                         // 如果电量低,低压指示灯亮- I0 R# i- j& e: s: L8 f9 h9 B8 H( ~
  110.                         LED = 0;" e( V/ N! {# {' q. p
  111.                         // 清电量检测硬件标志位! }3 a9 n: T4 p/ j) P' ~
  112.                         PCON &= ~(1 << 5);
    4 _; A" E, M$ V/ d' x/ m  `. y
  113.                 }else{) A" I3 ^8 k, {3 ]; U1 S8 Y! [
  114.                         // 电量正常,低压指示灯灭8 H; }( B6 u" I5 |* T9 b
  115.                         LED = 1;
    ! j9 {. ~! I! H# E1 P1 n
  116.                 }
    8 M; X5 s. X$ s
  117. . k  N  j5 N0 d4 d
  118.                 // 检测到停机标志
    ! Z3 S( U/ Q' w" y% N0 W
  119.                 if(isReadyToHalt == 1){
    ( V9 u7 h& a8 j% n$ m
  120.                         // 暂时关闭定时器0中断" N3 d( r1 k* U8 Z: H
  121.                         ET0 = 0;
    . k! i+ s8 f# E: F7 M$ T) N
  122.                         // 停机之前先把矩形波输出脚置低电平,以方便INT0和INT1唤醒CPU
    ' _# C4 C" f, ?5 u+ @" ^- p9 Q7 K
  123.                         OUT = 0;2 J- }3 t  F- H1 ^) \& w# z& h2 k
  124.                         // 停机之前先把低压指示灯灭掉,以省电
    3 D0 T% r- |! g
  125.                         LED = 1;
    4 u) S; U* x$ I4 R! K
  126.                         // 进入停机模式; A9 Y5 h. q) G4 A7 _) e
  127.                         PCON |= 0x02;! d3 U9 f( P3 V  X0 a
  128.                         _nop_();
    6 T2 {* s) q/ Y
  129.                         _nop_();0 ~6 K; G$ R7 j" F' M
  130.                         _nop_();0 J0 B# n9 u0 C3 Z5 v7 a* M( v
  131.                         _nop_();
    5 {! L5 C9 U, v: ?0 X
  132.                         // 唤醒,清标志位) i5 a! y- `8 c
  133.                         isReadyToHalt = 0;+ G4 |4 u% E6 a% b& G
  134.                         // 重开定时器0中断3 |" W/ S  t4 h& D/ n: e1 b
  135.                         ET0 = 1;
    ) [( ]' ]) [! w% d6 w
  136.                 }7 Z* w# h. i* i* I; K
  137.         }; A3 c) }4 H' T0 S
  138. }$ y# }9 R: y. A
复制代码
/ j+ o( v" ?1 f- ]4 p" e+ ^
硬件参数配置:+ d5 ?+ H- z/ M; ]+ X$ O+ g$ j

- w4 Z" `2 C  \0 a
; \* H' s% m" ^* o* O; i# a0 e接收端:
* c: \8 H" |- _8 z. T' o0 }
  1. #include <INTRINS.H>
    / o+ G3 N' i+ q4 ?2 C- T, U  C! A
  2. #include "STC15W.h"
    / y0 m* q& j% W$ D% J9 K5 u5 E
  3. ! U/ x$ |- o1 `2 c' U
  4.   x5 `4 t, V+ g4 Q/ V9 Q
  5. /*
    " i+ u* g/ \( E8 H7 ?; u' l

  6. 0 O- \" ~. t; }- x- q+ S
  7. *---------------------------*
    6 K2 g# i8 m6 J/ H; L* D; S
  8. |1 (GPIO2)         \__/  (GPIO1)16|
      O$ ?! H" T3 _3 E
  9. |                                                        |
    * K0 ^( U/ }) t: j
  10. |2 (GPIO3)                   (GPIO0)15|! [5 W3 g3 H2 {, c2 A7 ]" M/ j5 U
  11. |                                                        |8 i4 G( Q( g( \) T' J. V$ T( ]7 _& l
  12. |3 (GPIO4)                                  14|9 `2 f' L6 z0 z
  13. |                                                        |5 p8 ~, k" H8 X; \
  14. |4 (GPIO5)                        (DATA)13|
    8 w; W4 b9 f" _& y) [# w
  15. |                  STC15W204S                |
    + D" _7 k+ Q) s$ h; |" I* A( p
  16. |5 (GPIO6)                   (LATCH)12|- r2 P  A# m5 a# Y6 W
  17. |                                                        |/ w' l- R+ `6 P) j: L
  18. |6 (VCC)                         (CLK)11|. C9 E- B( V6 v# k1 V
  19. |                                                          |
    7 ^' e- S4 K9 I- _1 X4 B( g; c
  20. |7 (GPIO7)                         (TXD)10|8 V. S6 Q- p/ i! X3 Q
  21. |                                                        |9 d! j" [5 x7 Z" s7 e
  22. |8 (GND)                         (RXD) 9|3 u: L7 E$ \8 A6 K  ]+ w
  23. *---------------------------*
    2 B# A0 k& j4 Z# t4 ?
  24. Fosc = 12MHz
    7 l# f/ A! l( @( N+ ^! Y3 E

  25. ( _& @& ^7 p5 a6 G
  26. P1.0 -> 上
    : ]) N+ K2 v2 S4 B  Q
  27. P1.1 -> 左
    * Y( w: ^% R7 S1 ~( i% h1 T$ M( v
  28. P1.2 -> 下" i" d# ^1 y3 @$ e6 C& i$ l
  29. P1.3 -> 右1 L, @4 ]; G% \( ?% G, V& }
  30. P1.4 -> SEL+ u/ r2 E! T. g) Z
  31. P1.5 -> STA
    $ j1 c/ {; C) Q6 p% X
  32. P5.4 -> B5 D( d5 w5 S2 N0 n4 e
  33. P5.5 -> A+ [3 X6 k# @- s9 Q

  34. ( W6 a* t/ ~" {
  35. */
    . D) T% ]1 A" X3 N. T

  36. 2 ^$ J! D4 h/ Y( R- Z
  37. 7 m9 L4 A* c8 g
  38. sbit CLK        = P3^2;9 x- D. y& M9 T7 V! ?* c4 Y7 `
  39. sbit LATCH        = P3^3;# n9 y! Y. P2 o8 q$ X
  40. sbit DATA        = P3^6;
    + h1 \% f9 U3 f
  41. ' s" m3 D* B( c. ?7 H- M" m
  42. bit isReady = 0;' ^3 {" R! Q" M1 |/ \. I
  43. static unsigned char key = 0;
    ) a6 F: `4 a. P, y) N% N) t
  44. static unsigned char buf = 0;        // 双缓冲。这个缓冲区保存从P1和P5组合而来的键值3 z- \& M+ R% e) [) f0 ~
  45. static unsigned char bufReady = 0;        // 双缓冲。这个缓冲区保存上面那个缓冲区的备份" s) z0 P# I( [4 t
  46. static const unsigned char data mask[] = {0x80, 0x40, 0x10, 0x20, 0x01, 0x04, 0x02, 0x08};        // A B SELECT START UP DOWN LEFT RIGHT。为提升速度,这个表放到RAM中% A# W3 i: Z% H1 F
  47. static unsigned char idx = 0;
    * Q* e5 ^" w0 ~& R  |2 m7 D6 T

  48. 0 I5 P! z# H9 h2 s7 R
  49. % r* s. w+ I# O" A9 s
  50. static void GPIO_Init(){1 P' q& l2 l1 _% J0 t' H
  51.         // P1口和P5口用于接收并行信号,全部初始化为准双向,依靠内部弱上拉输出高电平# Q2 e5 t; i" w, K' F' A
  52.         P1M0 = 0;) ~0 L% O+ S6 O- [* m, W
  53.         P1M1 = 0;' n* X* C/ R* C* x9 B7 E
  54.         P1= 0xFF;6 Q" O. a7 Q% z" n1 q1 [8 i" m
  55.         P5M0 = 0;' s( n, [6 P* j+ W9 Y
  56.         P5M1 = 0;
    5 [0 O+ t* |0 k2 [
  57.         P5= 0xFF;: D8 m% z9 h+ a. s0 @" e  E) l
  58.         // P3口初始化为准双向$ r# L# b$ v2 `+ |
  59.         P3M0 = 0;
    + H5 R/ x1 m; W. q9 ?  ?6 x  ~! a
  60.         P3M1 = 0;6 [$ i5 @; X3 z" z6 H& R; b4 [; Q, F
  61.         P3 = 0xFF;  W3 l* S% U) o7 F% n
  62. }$ e& g# @1 d! o8 H) \8 G
  63. & |0 Y4 V' I4 {* V
  64. static void Interrupt_Init(){
    , a! R0 y5 y% R1 z
  65.         // INT0中断(CLK)触发类型为上升沿+下降沿
    " o( `$ V( ?( M; f
  66.         IT0 = 0;# a! U* Y: p$ p. L* S0 w8 d# r
  67.         // 允许INT0中断
    . n0 B/ j4 B, h) T
  68.         EX0 = 1;/ n) J. h  i. L- j& V
  69.         // INT1中断(LATCH)触发类型为上升沿+下降沿; o5 |$ p3 u5 f2 x6 u5 `% u$ K7 r5 d
  70.         IT1 = 0;
    & k# i7 J! k7 z: `3 l/ d
  71.         // 允许INT1中断
    . C% y* P; J4 @" D9 }. k$ ^
  72.         EX1 = 1;- t; k# ?+ u5 E8 z9 r2 O
  73.         // 开启全局中断
    0 s1 k' r2 d9 v
  74.         EA = 1;8 _, ]$ ]3 |* n
  75. }
    0 p) W3 u- D, X& f% v$ p
  76. 0 K. `; d. q) @& D/ D( I  n
  77. static void INT0_Isr() interrupt 0{
    ! p, j$ B0 H, C, r( K! {$ o" x
  78.         // 只有已经成功锁存才允许CLK移位
    , g, ~, g5 A! X, c- E, P4 A' ~
  79.         if(isReady == 0)6 `6 k8 h7 v* D7 i
  80.                 return;! s/ m! N0 [$ u4 u* E
  81.         // 读当前引脚电平,如果是低电平则说明是下降沿,此时直接忽略该中断
    9 E- F- R& B: i7 h
  82.         if(CLK == 0)
      W( d/ e* E' \
  83.                 return;
    # ~' S! ~* L8 H& u# t1 A1 W7 D8 ]+ v
  84.         // CLK上升沿到来的时候,取锁存值的下一位输出& ^$ ?+ C7 o# ^; R& d5 E9 k
  85.         idx++;5 r) i2 q- M1 R  W& E  M4 Y
  86.         DATA = key & mask[idx];
    ! Q" I, e# g, {1 }
  87.         // 如果已经完成7次移位,则一轮读取完成2 o: z' e. g0 ?8 S6 V! [! |
  88.         if(idx >= 7)
    * y7 I, c# m8 M! R3 k) u
  89.                 isReady = 0;- X" z8 l: n& R  {- b, _4 c
  90. }- H% N9 z( v8 s- p  C

  91. 2 t+ e3 v; v: x9 T) M/ a6 c9 p8 M
  92. static void INT1_Isr() interrupt 2{
    ' J+ Q; w% l  `  ?5 l% z
  93.         // 读当前引脚电平,如果是低电平则说明是下降沿,此时直接忽略该中断* G3 X! U, X. k; I7 V$ |- D% h
  94.         if(LATCH == 0)
    # a+ I: L; }/ m% L! ?
  95.                 return;
    ( P& H7 s9 h" C4 Y, B
  96.         // 当LATCH上升沿到来的时候,锁存所有按键状态,同时把键值A输出到DATA
    , ^' w, f" l' {. f3 }" ]- M+ r# \
  97.         key = bufReady;8 y9 p; J1 ?9 s& ?
  98.         DATA = key & 0x80;//mask[0];        // 为了加速运算,直接取表中的值而不是读表
    ' G2 ?, ~6 E. e8 ?$ p
  99.         idx = 0;
    0 }! x5 Z8 R( b3 G
  100.         // 允许CLK进行移位
    ; X! s: t9 r% W) }2 A2 |1 j
  101.         isReady = 1;% P4 q, N% s: V5 |& |0 X, O1 o
  102. }. C$ r" r8 B% k9 k
  103. 3 j8 v* b- _& A: a/ Y9 H9 v
  104. void main(){8 L4 F) P4 W/ \% t+ h5 O
  105.         GPIO_Init();
    . m4 c9 P3 e6 H- n  X# R3 I9 j2 R
  106.         Interrupt_Init();( l/ I) a; X- J$ E1 k! P. v
  107.        
    / V4 T/ V5 o" J) ~" [
  108.         while(1){
    1 G* c) s' Q6 r% a5 m1 {5 A
  109.                 //PCON |= 0x01;        // 进入省电模式" v( q) B1 ^; L$ {! T
  110.                 //_nop_();
    ) `( v( u$ q6 O( k3 l1 J( N; {
  111.                 //_nop_();- S4 i6 A" I7 S
  112.                 //_nop_();
      ~2 b; K) ?- t6 B
  113.                 //_nop_();
    9 ~/ F+ ]0 `) x* X8 q/ W1 F
  114.                 buf = ~((P1 & 0x3F) | ((P5 << 2) & 0xC0));
    ' L) R* \: t5 F/ U
  115.                 bufReady = buf;
    0 C0 p4 A9 ]0 \
  116.         }# u9 y: G8 |2 e6 L  B" b
  117. }
    , I3 S. x) Q" W( }
复制代码

9 J+ |# w- ^# a; T硬件参数配置无特殊要求,晶振频率选择12M即可。* H& }# r2 p; W$ J* D
: b; |+ w  z, N& C
这是编译好的固件。

本帖子中包含更多资源

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

×

评分

参与人数 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:057 @, X& N& A0 I
不错的设计,想问一下楼主,FC的15针公头怎么解决?普通的公头太短了,插不进去FC的扩展接口。 ...

  Y, j# _7 W! H0 e% z- I坛友的改造方案
回复

使用道具 举报

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

使用道具 举报

发表于 2019-5-25 12:07:18 | 显示全部楼层
精彩,楼主动手强,也写得很详细。$ I" Q; q$ R- {5 z; q
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
* j, x. I) z. T2 \2 `3 T+ ^1 L) Q精彩,楼主动手强,也写得很详细。
' E8 S0 ]( y3 F) j2.4G方案是目前无线的最低延迟吗?

, s) Z% P1 y, ]( s( S5 y% }+ [我没用过其他无线手柄,所以实在不知道我自己做的这个手柄到底是不是最低延迟。
' W3 ?5 ~* ]1 y( I" `7 {不过根据网上的说法,延迟高低主要是由通信协议的复杂程度,以及数据传输速率决定的。这个模块虽然是2.4G无线模块,但由于协议很简单,所以延迟比较低。' k8 Y0 b/ K1 Z  w- U  I
我用这个手柄玩一些ACT游戏,比如超级马里奥、忍者龙剑传、热血系列,完全感觉不到延迟,和游戏机自带的手柄没有任何区别。唯一的区别就是这个手柄是用火花山寨手柄改造的,外壳是垃圾回收塑料,粗糙+脆弱,导电橡胶弹性不佳,手感不是一般的差。  X* \7 o, p4 I0 f: F, ^3 O
我手里还有十几张板子,等我有空了我再做一套,到时候买一个好一点的手柄改造。
回复

使用道具 举报

 楼主| 发表于 2019-5-29 16:56:14 | 显示全部楼层
ppad 发表于 2019-5-28 17:27
: Z# E2 S+ E+ \- d, m4 w6 y( A给技术帝赞一个,有半成品发布吗,自己焊接改造就可以,编程实在不会啊 ...

( {8 a: O: D! L- k) L& M8 R- ^$ a很可惜,我手里没有多余的单片机了,LDO也找不到了,锂电池以及充电模块更是没有了。反正就是该用到的元件基本都没了,所以没法发布半成品。
7 Q  v1 P6 a: \+ x) Z  L" S两个板子倒是有十几张剩余。4 y2 U& c$ f, y
你要是有USB转TTL串口板,完全可以自己买这两种单片机,然后我给你编译好的固件,你自己用串口板下载到单片机里面就行了。两个2.4G无线模块也得通过串口板用AT命令设置参数,不过好在我在设计电路的时候就已经预留好了串口,可以直接在线下载和在线设置参数。总的来说并不麻烦。
回复

使用道具 举报

 楼主| 发表于 2019-5-29 17:00:34 | 显示全部楼层
孙大师 发表于 2019-5-28 18:55: k3 e2 f- @& |0 h
非常好,楼主是技术帝,到目前我都还没开发fc的无线套件,等空了,开发一套套件,等玩家自己组装。 ...

: O, G* L' E% K" W, ?能得到孙大师的赞誉,不胜荣幸!
- h7 k% K7 ~+ V2 |! Z5 Y不如开发一个多功能手柄,比如用SFC手柄改造,L/R键配合其他组合键可以用来切换2P~4P、调节连发速度、软重启等各种功能。接收端插到15PIN扩展口。
回复

使用道具 举报

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

本版积分规则

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

GMT+8, 2026-8-5 14:51 , Processed in 0.464112 second(s), 15 queries .

Powered by Discuz! X3.5

© 2001-2025 Discuz! Team.

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