找回密码
 注册

QQ登录

只需一步,快速开始

查看: 25503|回复: 32

自制FC无线手柄

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

, v$ P0 O" d# Z6 R$ A- r5 l8 Z6 ?  S$ ?0 q2 A% j
# q) K3 }6 a2 i
最后把按键、导电橡胶和电路板装上去。3 |/ m; u% |2 u% \
精心裁剪了电路板,正好扣上,不会阻碍其他元件,也不会影响后盖和拧螺丝。: ^% W, L1 r; c
) P& Y; s5 y. a) t

: Z7 ^$ j9 S# a: U+ x% }4 D% |完工!
2 d! Y0 u. ^) ]; A2 U& t% O" q* Q  L  T- j
& o% f0 y4 A) Q8 y  P. l
这是充电的MicroUSB插座。旁边的小孔用于透出低压报警LED的光线。
: g) i9 d' }  x- X2 j" x* {: a3 X/ @; A

, N' _( R6 V0 p& ]" ]8 n接收端用一片DIP16封装的STC单片机模拟CD4021。为啥要用单片机模拟而不是直接用CD4021?因为jdy-40模块接收端在有按键按下的时候输出高电平,无按键按下输出低电平,和普通手柄正好相反。当然我也可以用两片74HC00或者74HC04之类的逻辑门进行反相,但那就增加了芯片的数量。对于FC手柄这种工作频率并不高的设备来说,STC单片机完全可以胜任模拟工作。
# k8 M( j$ B0 q  A$ g, F' ?9 ~6 z! U- M; [

! w/ A5 x2 }: m" }( O$ U7 z$ b, }2 ]- j( V3 x9 r5 I0 N& ?
电路设计有点小小的错误,所以有几根飞线。原本设计使用低压差LDO是XC6206,结果在做这个接收模块的时候,买的LDO居然找不到了!无奈只好用了AMS1117。幸好对于接收模块来说是5V降到3.3V,1117可以胜任。要是发射端手柄的话,3.7V降到3.3V,那就非得用6206不可了。0 a5 n) j6 `! [# }

% E$ L8 ]- h/ E5 L实测十分灵敏,延迟极小几乎感觉不出来。可惜这山寨手柄的手感并不佳,尤其是方向键,软塌塌的。看来我得买个剪线手柄改装。
) G$ S) _4 ]; @/ K6 w+ [8 V- }4 m, E# D5 w
这是电路图,有兴趣的朋友可以参考。
5 c- W; b3 w* a. w  K8 P: {) P  B- c. |6 e6 C
: `$ p8 r# X& f. A* S7 f1 }  o
我信奉开源主义,十分痛恨把技术藏着掖着。好东西大家分享嘛!所以两个单片机的源代码大公开!& N2 N8 ^5 p* Q$ U
编译器:Keil 51。
, D6 z, O) l1 ~* C: o, a1 F: ]4 A0 |5 N
发射端:
' T% K1 R9 y0 |0 ~8 B* x# D8 N% x" Y% q
  1. #include <INTRINS.H>6 ~9 B  n. T2 z/ g
  2. #include "STC15W.h"
    : l: I; f! C, {: K
  3. + E6 f3 X( }2 m$ L1 H

  4. , _% ]* N+ t6 n
  5. /*
    8 S3 A3 y! r8 E8 R5 q4 P& C3 S+ [
  6. --------------------------
    7 u9 ]$ r) G% `) e
  7. |1 (OUT)        \__/   (INT1) 8|
    1 ~. n6 [3 @( H/ V: w' b
  8. |                                                   |
    - Z) [. j0 r4 ]8 I/ @/ F
  9. |2 (VCC)                   (INT0) 7|8 S- l3 J. o0 v' X
  10. |                 STC15W204S                   |
    $ y( y2 d6 J9 D3 B9 j% ^4 y
  11. |3 (LED)                         (TXD) 6|
    $ f9 \# q8 O& ~: r9 l, ?
  12. |                                                   |, }) W( p8 f1 o
  13. |4 (GND)                         (RXD) 5|
    ! S' f2 o1 }2 J: |
  14. --------------------------
    5 c- d9 y. m- o# ]; e
  15. - V& Z& i: T; _5 _
  16. LED ---|<|---[===]--- VCC
    6 Z2 b* P$ g, L4 w. H
  17.            Red          330
      v6 A0 ^, o9 y0 l* u9 ^) V% s+ [
  18. 1 }# z" w8 X9 S! T
  19. Fosc = 6MHz
    ( n) {& b; r1 H: M; F* Y' o
  20. */
    ! x1 E) G( V* G& w' B( s/ G- M

  21. 9 S) a, X8 z  A5 {5 e

  22. 6 u4 ^  i1 `* F  @; d- v
  23. // 矩形波输出脚% i' s$ T- H5 g# V  L5 W8 K9 y
  24. sbit OUT = P5^4;" [' |& z9 A% y2 y# k  n
  25. // 低压指示灯引脚8 f8 [+ v9 ?4 W  W; B5 [# X
  26. sbit LED = P5^5;8 {+ [2 O# F4 @, |
  27. ' i1 T3 W$ f* ]: ^
  28. // 停机标志位" r4 Q+ S+ V; f0 W' F/ p
  29. bit isReadyToHalt = 0;3 }. o3 r# Z3 P; E
  30. ! a  V5 m# O: W0 V  p+ ]! S
  31. // 矩形波次数累计
    7 s8 t$ \7 u, o$ G! e& ?0 |
  32. static volatile unsigned char count = 0;
    0 B: l  M- v+ c1 v

  33. 3 z$ U5 P1 j% s/ R$ f" v

  34. 6 J. v& z$ J/ N( x4 x
  35. static void GPIO_Init(){
    / ^2 f9 K3 o) [5 l' t, z, V( }
  36.         // P3口设置为准双向,默认靠内部弱上拉输出高电平
    # V" }( V5 f6 V* t9 n
  37.         P3M0 = 0;
    4 a$ j( _& R: p% O. f  i) u
  38.         P3M1 = 0;
    - }  I8 g. i" x; A( k& P
  39.         P3 = 0xFF;
    & [( _7 Z1 O9 |8 e* |. n% i( s
  40.         // P5口设置为准双向,默认靠内部弱上拉输出高电平
    6 v, k; K3 X' f% @- t* r5 G% T" W
  41.         P5M0 = 0;
    $ `- v% w& {( _2 D& l/ N. X
  42.         P5M1 = 0;0 G9 _: K0 S4 ]: |1 C; f
  43.         P5 = 0xFF;
    ; `/ o" e3 Q+ W3 j
  44. }
    ) F, \, N" s7 @6 r, z8 E9 t+ {
  45. 4 j1 K0 e. q8 |- {4 J
  46. static void Timer0_Init(){
    6 Z6 J" z' k2 U3 t
  47.         // 16毫秒@6.000MHz
    : X( l- I  B6 i& i, B) L7 v
  48.         AUXR &= 0x7F;        // 定时器时钟12T模式
      d# R7 ?$ ?/ _+ J2 d
  49.         TMOD &= 0xF0;        // 设置定时器模式
      u) l4 h9 N# Q1 I5 d
  50.         TL0 = 0xC0;                // 设置定时初值) D- T- O3 a9 W7 V! a! x* P
  51.         TH0 = 0xE0;                // 设置定时初值
      F& i1 {$ \4 t2 B
  52.         TF0 = 0;                // 清除TF0标志
    ) S, v7 I1 i+ X2 }- o( f, Z
  53.         TR0 = 1;                // 定时器0开始计时
    8 b  X0 V& u9 i$ J8 }
  54. }
    % b" J  S; w1 `( s& i, x, n
  55. " C# D! }" L2 m8 v( v/ s9 A# y
  56. static void Interrupt_Init(){
    8 k, G( Z9 Q1 e# d* F# |9 c6 B
  57.         // INT0中断触发类型为下降沿触发! M) u- A* _5 V. Z! c
  58.         IT0 = 1;0 p" y$ D6 C) o8 N
  59.         // 允许INT0中断- ^( }3 E" u: t1 `3 e2 o2 W! |+ h) t
  60.         EX0 = 1;
    7 W5 Y6 p5 }- b, M3 l
  61.         // INT1中断触发类型为下降沿触发$ j1 G7 {! P3 f" a' f
  62.         IT1 = 1;
    " C* S5 P2 T1 l6 Z
  63.         // 允许INT1中断1 A& j% u) X  V# B, X9 h
  64.         EX1 = 1;
    ) ~6 k, e6 Q9 k4 {) l  Y4 F7 ]- V2 F
  65.         // 允许定时器0中断
    + F$ k# M, u7 l8 B, Z( v$ ]
  66.         ET0 = 1;  \$ G! J3 H5 O) C, ~
  67.         // 允许全局中断
    $ E) z. S3 i7 U9 @  p
  68.         EA = 1;# m- L" `0 y  t. R
  69. }
    " Z$ }7 |7 T) ]: l

  70. 6 T& z7 T; L, O$ @* _# w& v
  71. static void INT0_Isr() interrupt 0{
    : U# N! j# |% A5 P
  72.         // 矩形波次数累计归零
    7 w% J. w! f& z3 T- ~6 ?; W5 ]4 @
  73.         count = 0;
    & z3 G  F/ F$ w. _2 k& E( ^- A
  74.         // 重开定时器0中断6 A+ ?! T% W$ [( \' ^2 d4 E
  75.         ET0 = 1;
    * l; p* z+ J7 p# R7 l
  76. }0 m( R( z- J3 ~
  77. $ [  c4 _1 U0 K; u# {
  78. static void Timer0_Isr() interrupt 1{6 M4 P3 L7 \) G& ^- P
  79.         // 输出矩形波
    $ W- H+ Y, G4 D0 K' N! n+ n
  80.         OUT = ~OUT;% Q9 @3 |! |" l. z- c9 t
  81.         // 累计矩形波次数
    # F& V" }' _3 \  }$ t
  82.         count++;
    - x! z0 m2 {- P) z% M$ T3 T2 |
  83.         // 超过250个矩形波,准备停机
    " M9 k) G0 \' u+ D
  84.         if(count > 250){) P! O9 _# s1 J/ [
  85.                 count = 0;" w6 j3 ?' k, o& n4 _( T* j
  86.                 isReadyToHalt = 1;
    * W8 Q9 T( R$ V$ m- y
  87.         }/ A' A& C5 I0 V
  88. }
    + s8 U+ A  N! K- o+ K' W

  89. 8 _: U: F/ N/ J/ g+ r2 c0 ]
  90. static void INT1_Isr() interrupt 2{
    7 I! ]# M- |* i9 i
  91.         // 矩形波次数累计归零
    1 n! }1 |  f. E3 v7 k0 M* m
  92.         count = 0;4 j. X0 g! e5 w& n
  93.         // 重开定时器0中断
      m8 u7 S( q% v, ~; R9 y
  94.         ET0 = 1;
    7 D8 L' g# H0 h' i6 j
  95. }
    " p8 ?& n$ [! S. z! H

  96. 6 `( o% D8 A' t% l. R# u
  97. # E+ L: y3 Y1 v( s- x' b4 D
  98. void main(){
    # }: v7 J3 l: F' d& w- j
  99.         // 初始化P3和P5口
    " q' \, ~9 T$ E% Q% R$ K* a1 O
  100.         GPIO_Init();4 I1 V0 U/ r! P9 K
  101.         // 初始化定时器0
    9 d& b1 |. j- G) g" \8 \
  102.         Timer0_Init();+ H' W7 {( {- y: o
  103.         // 初始化中断
    9 c  l( n8 Y$ K& Z; G" i! t
  104.         Interrupt_Init();
    2 w4 A6 U3 g* t) C. @
  105.         - x( ~" \' o+ v7 @, ]
  106.         while(1){$ Q* b+ N( W9 S9 I0 E& S
  107.                 // 检测电量! W+ O2 `0 Y1 s! O
  108.                 if(PCON & (1 << 5)){
    + |9 |/ T! s- l  ^
  109.                         // 如果电量低,低压指示灯亮
    " J+ Z" O; n5 T( H' z
  110.                         LED = 0;- Q# _' x; {$ ^9 I1 c+ R+ @2 v3 K
  111.                         // 清电量检测硬件标志位
    ' E7 I3 K+ o. }) T& B0 @. u
  112.                         PCON &= ~(1 << 5);
    * [' _- w6 w  s4 ~- r( W" a- l2 x
  113.                 }else{$ \$ P8 ?; B5 s. _5 ^
  114.                         // 电量正常,低压指示灯灭
    8 A# r" v; @) S! s; z4 x0 p1 Y
  115.                         LED = 1;+ i9 r$ y1 M5 N) }1 i, e# j1 r
  116.                 }
    : I8 b/ i: ?$ H# k5 E

  117. 7 q( C* {* C& S" v5 u0 S
  118.                 // 检测到停机标志/ m% n! {3 b8 a( {
  119.                 if(isReadyToHalt == 1){* R9 C* y+ E+ h  W* \; h2 P
  120.                         // 暂时关闭定时器0中断4 r1 p8 A5 B9 {
  121.                         ET0 = 0;% k  }) r% N) b7 i% u& a; t' N( e
  122.                         // 停机之前先把矩形波输出脚置低电平,以方便INT0和INT1唤醒CPU' F, L% V- d) n1 B  F2 `
  123.                         OUT = 0;
    ) {$ c) K% U. r: r! f7 ]$ Y
  124.                         // 停机之前先把低压指示灯灭掉,以省电
    6 {: X$ G! H0 k% i" `) Z+ s$ e3 e
  125.                         LED = 1;2 \) q! q; a: O& [6 |/ J
  126.                         // 进入停机模式
    & _! }1 H3 W+ F. M
  127.                         PCON |= 0x02;
    . V0 v0 B% O4 H: @2 G$ \
  128.                         _nop_();
    / U5 @0 x4 m3 L5 T! R7 _
  129.                         _nop_();' }  s* {5 ~4 b" `  U' `" v0 J
  130.                         _nop_();
    " e  S5 ^2 ?5 j4 l  s6 V4 ^( O
  131.                         _nop_();
    * }3 @3 @3 O7 X$ C$ m% [" U
  132.                         // 唤醒,清标志位
    1 o* E& }# ^# q2 t2 x
  133.                         isReadyToHalt = 0;' B0 E( f3 b: Z% S0 k& h
  134.                         // 重开定时器0中断% E6 h' U: X# h+ p- [
  135.                         ET0 = 1;
    7 B- X6 U/ X( }
  136.                 }
    : i5 `9 X- T$ ^' P* ?' J
  137.         }/ M3 f. ?% |. Y$ j: [) L8 T
  138. }) d' z2 T; Z6 x) s
复制代码

& N5 C7 t" v& O# S硬件参数配置:
4 v8 ^9 v# C1 Y) E
2 J+ a% t% v9 P; I& Y' `0 F* v
/ y8 v3 H1 I3 x  L接收端:  k9 i8 z1 Z# T( ^: p) @
  1. #include <INTRINS.H>
    : c" Q! w9 O1 k: J- K3 ~, i
  2. #include "STC15W.h": }: V, I/ P7 p/ w$ r* J" D
  3. ' E2 b  C* e& ]3 A$ @2 f! Z/ a5 d, z
  4. / l+ {3 l4 p' w1 v& @7 ?
  5. /*
    ! j( E! ]9 h* k

  6. ( N$ g' u. d7 ~
  7. *---------------------------*
    $ e  k! V4 ?0 X8 ^
  8. |1 (GPIO2)         \__/  (GPIO1)16|" A; Q; l8 d. [- a) m8 R
  9. |                                                        |
    . A5 d+ Y; v9 N; B/ _, M# U$ g
  10. |2 (GPIO3)                   (GPIO0)15|
    ( f0 f2 y" ]3 T4 Y2 W' [8 Y4 b1 V
  11. |                                                        |% q' I1 P0 j1 k8 W7 [, ]* |
  12. |3 (GPIO4)                                  14|% k, K. p& W' M  ]7 Z9 }4 O
  13. |                                                        |9 D: ^2 b1 C& z7 X* o
  14. |4 (GPIO5)                        (DATA)13|
    ) Q$ ~9 |& z# s: i
  15. |                  STC15W204S                |
    : D8 j2 O2 l0 g$ ~6 t, g2 x+ }
  16. |5 (GPIO6)                   (LATCH)12|
    - F/ p- V! w3 H$ ]3 M9 q6 ?3 t/ _
  17. |                                                        |
    ) z6 \% Z" c6 Q/ T) U
  18. |6 (VCC)                         (CLK)11|2 D0 c! H4 |- }
  19. |                                                          |
    3 Q4 A. {* B. y1 v; a7 w% C
  20. |7 (GPIO7)                         (TXD)10|7 L, _3 J" `7 {. n) M7 C
  21. |                                                        |2 S: T$ G$ ~3 i6 r* {2 B4 A( R
  22. |8 (GND)                         (RXD) 9|
    ; O6 C: t% x/ q" l5 b3 D
  23. *---------------------------*
    " R" ~8 h2 q7 V: R3 Z3 i9 `( o! A
  24. Fosc = 12MHz, s3 d: h; c0 b1 r
  25. 7 Z5 a* v2 ~! V. N
  26. P1.0 -> 上
    5 j# }; x' u% ]$ D! V, Z0 o
  27. P1.1 -> 左
    * W* n+ L! e$ b* t$ R" `
  28. P1.2 -> 下5 g0 U5 X2 `- y: ~) }$ {; r. Z
  29. P1.3 -> 右9 ^  O2 V' F2 S+ V
  30. P1.4 -> SEL, @, b) E' i+ g0 n  g) i0 ^
  31. P1.5 -> STA
    , T6 h$ u  [. n- f+ C: _: Y$ p
  32. P5.4 -> B
    9 k/ K8 E; a) u9 ]5 w
  33. P5.5 -> A
    $ M  n3 v6 c- f& A. I  x% j+ V

  34. $ F9 ^. ?; p& T! f6 G' j4 ~: h7 k
  35. */
    - X6 Z& J3 M! p  J

  36.   O9 U) T( Q. V2 y
  37. ) u# v0 [5 s& J  }, S( y: o4 m6 \
  38. sbit CLK        = P3^2;5 L  Z* r* G2 @; b) C/ o
  39. sbit LATCH        = P3^3;
    3 x2 O" m6 A9 ^7 d! [6 T& f5 g* r
  40. sbit DATA        = P3^6;
    6 o+ ~8 U) i# Y9 O1 K9 s7 n2 n

  41. ' ~: Z8 r0 I) F& ~) I$ s" _
  42. bit isReady = 0;
    + v; c. M+ |1 w8 E  W
  43. static unsigned char key = 0;+ M3 H3 z  C) i- b
  44. static unsigned char buf = 0;        // 双缓冲。这个缓冲区保存从P1和P5组合而来的键值3 z% l1 S/ V1 o6 U6 P  X, @
  45. static unsigned char bufReady = 0;        // 双缓冲。这个缓冲区保存上面那个缓冲区的备份# ?+ W# Q' a8 A& z* \
  46. static const unsigned char data mask[] = {0x80, 0x40, 0x10, 0x20, 0x01, 0x04, 0x02, 0x08};        // A B SELECT START UP DOWN LEFT RIGHT。为提升速度,这个表放到RAM中
    # B* U) q3 d5 Q# u8 C
  47. static unsigned char idx = 0;, L) O* |- `7 z
  48. . o, O% N) T/ I, D8 a! @- d9 o  t

  49. - H- L" K7 b9 z
  50. static void GPIO_Init(){
    4 s: M+ s- Q' s; z4 \$ ^
  51.         // P1口和P5口用于接收并行信号,全部初始化为准双向,依靠内部弱上拉输出高电平6 F  ]3 E2 f" r
  52.         P1M0 = 0;
    3 W  }$ z2 Z$ m9 h( }( N& p# u
  53.         P1M1 = 0;
    ( V/ D; V7 J; B2 B. x7 g; ~( _
  54.         P1= 0xFF;4 Z( O) N6 F' E
  55.         P5M0 = 0;
    5 `4 z; r1 b  u0 L; i
  56.         P5M1 = 0;
    ; c, D0 u8 n3 x: V0 g8 W
  57.         P5= 0xFF;
    % h1 h5 O. `$ K, J
  58.         // P3口初始化为准双向
    : y' u' G! L8 S" L3 I
  59.         P3M0 = 0;* I' Y) t6 Q2 x/ L
  60.         P3M1 = 0;
    + c7 [' Z$ m6 N' M- g' {
  61.         P3 = 0xFF;
    1 o$ c! _2 @0 x
  62. }! h: S* q9 {2 V# t$ n

  63. 1 h" T7 [  ~, Z- r& G
  64. static void Interrupt_Init(){
    ; ]2 F- [% L  J" A5 X; d
  65.         // INT0中断(CLK)触发类型为上升沿+下降沿- v4 S5 J! Z( S" T
  66.         IT0 = 0;
    4 S; o' |. G3 l9 }1 q8 ?
  67.         // 允许INT0中断
    & |' R6 p+ K4 A, q$ x1 b
  68.         EX0 = 1;
    2 G2 E: J$ k4 p. D2 z
  69.         // INT1中断(LATCH)触发类型为上升沿+下降沿
    + `; n5 L$ o) Y: [) t6 E
  70.         IT1 = 0;! ^2 x4 z. w0 C: m5 o; y! |* L
  71.         // 允许INT1中断
    9 r9 J' Y% a0 ?: M
  72.         EX1 = 1;% y; m( T* P; z) i/ i8 M3 u
  73.         // 开启全局中断
    2 R: l0 T# J; i7 l$ N
  74.         EA = 1;
    0 p* h+ L" X. `! A6 g
  75. }
    " D$ d+ Q/ C6 r$ m2 E+ O- F

  76. ; B7 f' P4 s: ?8 z, O1 w
  77. static void INT0_Isr() interrupt 0{
    3 g8 Q- Q  H5 \0 g% P" x8 t5 G( ^
  78.         // 只有已经成功锁存才允许CLK移位$ |, ]* E' ~( y, P. |. w
  79.         if(isReady == 0)
    " G$ W0 K9 R( U( L( \
  80.                 return;& ]" y% e$ u5 k" f' k
  81.         // 读当前引脚电平,如果是低电平则说明是下降沿,此时直接忽略该中断, j# {& Y# L" B$ m
  82.         if(CLK == 0)
    0 q" l) J# P4 B7 L4 s' l
  83.                 return;7 z% t! `% ?  e  H: g' m) a
  84.         // CLK上升沿到来的时候,取锁存值的下一位输出
    ! w" Q/ A3 ]$ {$ e
  85.         idx++;7 |1 r; }1 S0 n4 F6 Q; ~
  86.         DATA = key & mask[idx];
    ; Y' `: h: e' p- S
  87.         // 如果已经完成7次移位,则一轮读取完成! `# ?- W  |$ {
  88.         if(idx >= 7)
      i2 ~2 Q; z# A  g4 G: }6 u
  89.                 isReady = 0;$ E7 S' W9 z! u& p$ }
  90. }
    - C1 ?9 k. n0 s- u
  91. / S, w" z5 K% s, }9 }
  92. static void INT1_Isr() interrupt 2{* m6 X* S+ U8 C+ N9 P
  93.         // 读当前引脚电平,如果是低电平则说明是下降沿,此时直接忽略该中断) n7 t4 B( V' z; m# d
  94.         if(LATCH == 0)
    % z) ~- i9 `# v0 F) J
  95.                 return;
    ' X& J" M! k* a
  96.         // 当LATCH上升沿到来的时候,锁存所有按键状态,同时把键值A输出到DATA# K" f. X$ _# Q# S, z. Q
  97.         key = bufReady;" C3 I* c: K  z% W" G/ k4 h
  98.         DATA = key & 0x80;//mask[0];        // 为了加速运算,直接取表中的值而不是读表
    8 Z/ ]: k( Q9 O0 r  ~9 X
  99.         idx = 0;
    0 G9 M: `. G' O/ n
  100.         // 允许CLK进行移位9 T1 y  `$ ]4 X' L( {
  101.         isReady = 1;+ |1 s7 _- C; V
  102. }
    ) Q) r; I/ D& ?: M" ~: q
  103. + C& M+ j! |% {; c
  104. void main(){( W8 {( i; E$ Q" {
  105.         GPIO_Init();
    4 q" v, F' i8 m, D3 o# b
  106.         Interrupt_Init();9 _& H( P& K+ D
  107.         ! V+ z& r* L2 Z% d
  108.         while(1){
    1 H; e! C( c! R+ m' x4 h0 h
  109.                 //PCON |= 0x01;        // 进入省电模式6 d% F8 H5 g5 O& b
  110.                 //_nop_();5 M' ^& f! P' k9 r* U. R4 O. f
  111.                 //_nop_();
    ! d, X* N. q: \3 C
  112.                 //_nop_();* @4 W+ e+ H- X2 S3 a4 z
  113.                 //_nop_();) o6 A' K9 I9 J9 C3 E) z
  114.                 buf = ~((P1 & 0x3F) | ((P5 << 2) & 0xC0));, c. D! ~) E( u7 h9 }
  115.                 bufReady = buf;
    " l: U# r& G7 c# C
  116.         }
    0 A7 S  C( P* e% d6 n8 u  k
  117. }
    ( ?' [$ x* p2 ^7 C' G
复制代码

1 n0 Q/ w' X- {! i6 a% g硬件参数配置无特殊要求,晶振频率选择12M即可。2 N0 I5 {8 t: b! I$ _) \/ q
- Z( Y' K; b* W
这是编译好的固件。

本帖子中包含更多资源

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

×

评分

参与人数 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
* D% p$ [$ U% f不错的设计,想问一下楼主,FC的15针公头怎么解决?普通的公头太短了,插不进去FC的扩展接口。 ...

! v1 T( x6 `5 c1 |0 i& b坛友的改造方案
回复

使用道具 举报

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

使用道具 举报

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

使用道具 举报

 楼主| 发表于 2019-5-29 16:56:14 | 显示全部楼层
ppad 发表于 2019-5-28 17:27: c  C1 M* R7 P
给技术帝赞一个,有半成品发布吗,自己焊接改造就可以,编程实在不会啊 ...

. X6 a" R4 a4 M* I: i' W2 p, q很可惜,我手里没有多余的单片机了,LDO也找不到了,锂电池以及充电模块更是没有了。反正就是该用到的元件基本都没了,所以没法发布半成品。" r$ J1 v8 n. G: p5 d* E2 A, w
两个板子倒是有十几张剩余。3 T- Y# L6 W; d5 H; l
你要是有USB转TTL串口板,完全可以自己买这两种单片机,然后我给你编译好的固件,你自己用串口板下载到单片机里面就行了。两个2.4G无线模块也得通过串口板用AT命令设置参数,不过好在我在设计电路的时候就已经预留好了串口,可以直接在线下载和在线设置参数。总的来说并不麻烦。
回复

使用道具 举报

 楼主| 发表于 2019-5-29 17:00:34 | 显示全部楼层
孙大师 发表于 2019-5-28 18:553 A8 N: M, {; @6 b
非常好,楼主是技术帝,到目前我都还没开发fc的无线套件,等空了,开发一套套件,等玩家自己组装。 ...

& k+ O6 i6 z; ^# s2 M3 C  s& X能得到孙大师的赞誉,不胜荣幸!
7 H4 x( b1 e- J1 U不如开发一个多功能手柄,比如用SFC手柄改造,L/R键配合其他组合键可以用来切换2P~4P、调节连发速度、软重启等各种功能。接收端插到15PIN扩展口。
回复

使用道具 举报

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

本版积分规则

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

GMT+8, 2026-6-21 13:25 , Processed in 0.095753 second(s), 15 queries .

Powered by Discuz! X3.5

© 2001-2025 Discuz! Team.

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