找回密码
 注册

QQ登录

只需一步,快速开始

查看: 26019|回复: 32

自制FC无线手柄

  [复制链接]
发表于 2019-5-22 14:16:45 | 显示全部楼层 |阅读模式
本帖最后由 雷精灵2046 于 2019-6-14 09:28 编辑
  I% ?! j* }" @. |& R
1 N6 A8 S8 h1 s  d( K; [* z0 j8 t2 e6 a没有用复杂的分立元件搭建发射接收电路,直接用的现成的2.4G无线模块jdy-40。! \" a; Y$ T0 h2 I) D; u/ E( a* @* q$ h

) I" r% t8 S5 U5 j
- p% e+ D  }, z' U& N发射端靠3.7V锂电池供电,用了一片SOP8封装的STC单片机,负责产生连发脉冲,同时负责检测电池电量,电压低于3V左右的时候触发低压中断,低压指示LED就会亮起来告知该充电了。平时发射模块和单片机均处于睡眠状态,有按键按下才会唤醒,从而实现省电。实测睡眠状态下整机电流约1~2uA。板子洗了一下稍微干净了一点。因为对于微功耗设备来说,焊接残余的助焊剂可能会增加漏电流。$ S3 ?$ i$ G" ?7 ^6 J
; K5 K0 ]1 o1 \) @( X) ]. Q2 g
买了一个火花的FC山寨手柄,去掉里面的牛屎板子,并修正一下塑料挡板,把锂电池和充电模块装进去。
; e  W5 q* y! h1 {为了减少体积,充电模块裁剪得十分小,并且更换了充电电阻使之适应这个小小的锂电池。这么小容量的电池,也不需要多么大的充电电流是吧?) b2 Z) Q& q  Z$ L( v7 A0 d
然后统统用热熔胶粘上。充电电流比较小,所以发热很少,不会熔化热熔胶。  D7 k( _5 \$ g$ G5 P  ~
! R9 O- R3 j9 g! U* @/ [1 a$ ~
2 h: r0 U2 S5 ?4 U

( ~' Q  ~% |1 K% w2 t+ ?最后把按键、导电橡胶和电路板装上去。
4 _7 t0 J/ _5 S6 b1 A4 l9 r* I精心裁剪了电路板,正好扣上,不会阻碍其他元件,也不会影响后盖和拧螺丝。
$ [! Y2 t) p: o0 u9 V9 Z) x) I
6 d% i+ n  Z) v7 r9 V  B0 E+ N, A4 ^
完工!
7 t0 j! ~0 r1 r6 L8 f8 a0 Y$ i9 b" h/ [$ X  N3 i  s; G
% ]* o. W" w3 U
这是充电的MicroUSB插座。旁边的小孔用于透出低压报警LED的光线。6 P1 P' s' S' ?7 B
2 e) h6 S5 e( S# {) e0 u0 z

; _  F' |4 v( w8 a- R6 s接收端用一片DIP16封装的STC单片机模拟CD4021。为啥要用单片机模拟而不是直接用CD4021?因为jdy-40模块接收端在有按键按下的时候输出高电平,无按键按下输出低电平,和普通手柄正好相反。当然我也可以用两片74HC00或者74HC04之类的逻辑门进行反相,但那就增加了芯片的数量。对于FC手柄这种工作频率并不高的设备来说,STC单片机完全可以胜任模拟工作。
$ D% U' U$ V1 ^5 e' Y
  L& F1 f6 f& R* ?# u/ o2 g* E4 t8 ]. t6 D6 m9 W
* `( F" ^, f. f) b' ?) R
电路设计有点小小的错误,所以有几根飞线。原本设计使用低压差LDO是XC6206,结果在做这个接收模块的时候,买的LDO居然找不到了!无奈只好用了AMS1117。幸好对于接收模块来说是5V降到3.3V,1117可以胜任。要是发射端手柄的话,3.7V降到3.3V,那就非得用6206不可了。6 u# O: P  k4 h. u2 g) q9 h0 o
. X2 O; F2 z! E' G7 X: G" D6 X
实测十分灵敏,延迟极小几乎感觉不出来。可惜这山寨手柄的手感并不佳,尤其是方向键,软塌塌的。看来我得买个剪线手柄改装。
7 u/ W# E- c. O1 a2 V0 q" M7 f3 E) @% v2 R( c  B2 q& [+ U
这是电路图,有兴趣的朋友可以参考。0 L' y, K& P* P& w
9 j& M% r4 _" F' J; z7 p

) m! i, `' t' Z0 F! Q3 }, L我信奉开源主义,十分痛恨把技术藏着掖着。好东西大家分享嘛!所以两个单片机的源代码大公开!  ^" V# Z! [4 K3 ?+ @8 M( s& @1 B
编译器:Keil 51。
+ G) `4 E" ~0 i/ y
0 N5 |* U6 D, F" o发射端:( c3 A! M  e: N' w
  1. #include <INTRINS.H>6 S' d7 X) c+ m( ]7 e  m
  2. #include "STC15W.h"4 K8 ~5 h4 M% o  A1 q, |3 z! a

  3.   B; M  `8 ]* s# u# Y
  4. 3 D: @) x# k. i$ s
  5. /*, B9 f) b3 ^" B9 e. ^( I5 J* _* ?; u
  6. --------------------------' Q0 B- X5 e! `/ z2 y
  7. |1 (OUT)        \__/   (INT1) 8|
    * N2 H' P/ C- S+ @$ s
  8. |                                                   |* d3 K# M) @; Q: r. T7 ?
  9. |2 (VCC)                   (INT0) 7|9 [; I" ~+ P/ e8 z! [0 }, a. k
  10. |                 STC15W204S                   |
    9 }8 u7 R' l/ n2 V! Y
  11. |3 (LED)                         (TXD) 6|5 A+ D9 ~& ]  g1 y+ t! X
  12. |                                                   |/ d! ?- L2 p, `
  13. |4 (GND)                         (RXD) 5|
    6 f; A' K: q& P6 N& F
  14. --------------------------
    4 l1 i7 I9 S3 D' ~
  15. - g' d, u; e0 j* x1 V
  16. LED ---|<|---[===]--- VCC# N0 B0 \% ~- i7 _8 Z' o( D8 O0 n
  17.            Red          330! R! e3 ]& P0 O0 H8 s/ J6 [# D
  18. , W! @4 E9 |' [  A" @) `$ M7 x
  19. Fosc = 6MHz: M5 g0 W$ F: h% J) B9 Y
  20. */
    % Q4 f; A$ R& K( l0 s
  21. 2 p. }4 w9 ^: x6 V- s0 [  v

  22. , w" l. P7 d: }+ l1 t* D: [4 }
  23. // 矩形波输出脚2 J; S2 v# U9 _! v- `- T8 M
  24. sbit OUT = P5^4;& K* J  ?4 L/ N7 K/ i6 u
  25. // 低压指示灯引脚
    $ [6 H0 {4 {6 D/ R0 U# d* s
  26. sbit LED = P5^5;( a. Q: }" i" i6 E4 x
  27. % F/ L1 t4 o3 S
  28. // 停机标志位, S: E6 Z  D! x. O
  29. bit isReadyToHalt = 0;
      K# |9 d) J9 J4 E! \
  30. % v8 Z. o# k7 f, e  t
  31. // 矩形波次数累计
    ! @, Z2 f. g# f5 v! D, B2 f! j' D
  32. static volatile unsigned char count = 0;
      P! g6 @' d! O  b! ~' u
  33. + n3 k  M$ b8 E3 u; h, ?  v) }  ~+ t

  34. ) P& A0 C. S9 o1 q+ r
  35. static void GPIO_Init(){& n$ V$ i$ g# T
  36.         // P3口设置为准双向,默认靠内部弱上拉输出高电平
    * q, d6 E' N9 r
  37.         P3M0 = 0;
    # c, D9 A6 X$ p: b$ C
  38.         P3M1 = 0;  E% ]7 O6 `: A; B5 [' {# O
  39.         P3 = 0xFF;' w" o# ?9 ?" S7 s! `- h7 S
  40.         // P5口设置为准双向,默认靠内部弱上拉输出高电平8 k% E$ j; ?5 P( y( F
  41.         P5M0 = 0;$ b! @" F3 u; `/ u% m# d
  42.         P5M1 = 0;
    9 P" {& X7 G3 ?
  43.         P5 = 0xFF;
    ' W6 k$ G# K" y3 d. b* W8 o  a
  44. }
    : w/ \' r: z* ~7 l) V

  45. 5 ]# t6 \9 E$ |  @2 {, F) _  I
  46. static void Timer0_Init(){
    . K  A& Q- Y7 F: ~
  47.         // 16毫秒@6.000MHz
    7 G1 z# Q+ v, c! H, R
  48.         AUXR &= 0x7F;        // 定时器时钟12T模式8 S" I, z$ x. L5 g: `* Q$ b' b
  49.         TMOD &= 0xF0;        // 设置定时器模式
    ) q& H0 P7 E$ H2 Q9 t9 T
  50.         TL0 = 0xC0;                // 设置定时初值% n# R5 b; J5 d
  51.         TH0 = 0xE0;                // 设置定时初值
    2 @* _  H1 @9 |" {2 U+ O
  52.         TF0 = 0;                // 清除TF0标志
    ( U( h+ v. R; a+ U. C$ y) c8 w
  53.         TR0 = 1;                // 定时器0开始计时
    3 H( O+ H6 E0 ]* z3 I# T
  54. }
    3 ^) a  T) X% Q& ?% L# J2 J2 W
  55. ; i8 p4 A' T/ i& F% `
  56. static void Interrupt_Init(){+ {8 o( s! C& K: }# E" F
  57.         // INT0中断触发类型为下降沿触发
    * j/ D* L3 {, r6 ?6 i. c7 v. s
  58.         IT0 = 1;( I+ W- Y* [7 h5 n) p
  59.         // 允许INT0中断& ^& p4 M9 [( e7 t- [
  60.         EX0 = 1;, s' @7 V8 U7 t" ^& R- r% L1 Z7 T
  61.         // INT1中断触发类型为下降沿触发9 S  a; G: {7 N) \
  62.         IT1 = 1;/ a- h+ M4 Y, c! k
  63.         // 允许INT1中断
    1 h4 s/ s+ g0 B& b9 \8 ~" {5 i
  64.         EX1 = 1;" n  R: n8 e# K2 k& W
  65.         // 允许定时器0中断
    7 Z! r$ @6 g) J3 Y$ Y" F. P+ {9 n3 z
  66.         ET0 = 1;' y! l" l& F. A; u
  67.         // 允许全局中断9 E1 U5 n8 r0 j
  68.         EA = 1;
    ; }4 i; J% I. O4 h# H
  69. }
    # a$ W4 [6 g" {- U
  70. 1 y3 q( b# g/ D" ?# x
  71. static void INT0_Isr() interrupt 0{
    * C' p3 v7 E6 v9 u3 I# f" n/ i% ~
  72.         // 矩形波次数累计归零
    ; O" f# H" k8 N) B
  73.         count = 0;
    2 o( c* k0 e7 I2 \
  74.         // 重开定时器0中断  p) Q! d9 P4 Z4 n9 S
  75.         ET0 = 1;
    # G! L: o. o! ?4 A% Q
  76. }# O0 u6 @% I8 l% ?2 Z

  77. ) K0 ~/ x# F; |  D$ ~6 }
  78. static void Timer0_Isr() interrupt 1{/ v  Z# D. n+ W+ c  I" z
  79.         // 输出矩形波6 p% F0 g9 s) ^! l# j
  80.         OUT = ~OUT;, r+ e8 |& e' R8 c5 k7 S- [; _
  81.         // 累计矩形波次数
    + P* |" |. i; B
  82.         count++;
    " L4 y9 {6 o9 o* f  n0 k+ U
  83.         // 超过250个矩形波,准备停机& e2 y& x/ Z3 k' e5 I
  84.         if(count > 250){! `; E/ O" R1 r  Z3 }
  85.                 count = 0;  Y7 j3 A$ K1 z- ~5 M  x) b/ h
  86.                 isReadyToHalt = 1;
    ' h; \9 s6 F) R: ~0 S
  87.         }
    1 u& a7 D9 K# N' Y# d- M
  88. }
    ) m3 A3 l$ F/ ?" k

  89. 6 n  G) @/ b! g4 \" ^0 e7 T
  90. static void INT1_Isr() interrupt 2{
    9 i1 |& |& v0 {  N8 k
  91.         // 矩形波次数累计归零+ E" Z+ K$ k1 |' |4 s* T9 C2 w: y# _9 A
  92.         count = 0;; l2 O& R" b% e% C2 a
  93.         // 重开定时器0中断
    ( X5 h* w4 M& Y. U+ q0 D  F/ x$ V
  94.         ET0 = 1;
    / k. b& D2 V. E3 K6 G# ~
  95. }  Z  N; n0 }# \4 j) v( @  i& W

  96. : {1 ]- D# R, Q! }( y

  97. 0 ]- v. Y3 V0 S; c+ V2 N. z
  98. void main(){
    5 `$ }7 Q# z3 |3 v$ I# o, W. `
  99.         // 初始化P3和P5口
    5 }9 b( g2 @5 h7 y5 z8 J
  100.         GPIO_Init();
    ' }: z% Y' f& S$ M/ R
  101.         // 初始化定时器0
    ) x3 y) d* B7 n) F% P
  102.         Timer0_Init();$ O6 I: j. k3 i8 X! w; H% S! u
  103.         // 初始化中断
    - z) O' Z  Q- B( D8 ?
  104.         Interrupt_Init();/ `5 w) D0 [' R4 Q
  105.        
    6 P! E4 z. f; Z) ]7 s+ n0 F/ u, S
  106.         while(1){4 c' M% Z- V# J: _% G9 q' o
  107.                 // 检测电量6 k2 ~  p. \) J3 k( M$ U# Z1 I4 M
  108.                 if(PCON & (1 << 5)){2 B. _- W2 c5 h7 E& G
  109.                         // 如果电量低,低压指示灯亮2 q0 n  Y7 w6 A, @& d" |
  110.                         LED = 0;3 p( L) T: h8 }- e9 M2 t
  111.                         // 清电量检测硬件标志位+ @/ K6 ^0 I, Y8 F; j$ G
  112.                         PCON &= ~(1 << 5);. }- m, `# F6 _9 A0 p2 P
  113.                 }else{
    / ]% P# s+ w- ^- p9 v6 p3 @
  114.                         // 电量正常,低压指示灯灭/ P  t/ q4 e. x! ~  v& {* [1 d
  115.                         LED = 1;
    . k5 s1 B. c, Y; ~8 q
  116.                 }! i; V% {: p% |8 l6 x

  117. . D2 \# s, b9 j3 v
  118.                 // 检测到停机标志- Q% R3 o9 R6 [2 {5 G
  119.                 if(isReadyToHalt == 1){* B/ k) z* o* {6 y
  120.                         // 暂时关闭定时器0中断
    ! p7 P2 I5 e1 l3 w. {0 R
  121.                         ET0 = 0;0 A# S8 ]# O! g  [' @# k7 e# H2 ]
  122.                         // 停机之前先把矩形波输出脚置低电平,以方便INT0和INT1唤醒CPU7 D6 e% Y4 S4 v% T
  123.                         OUT = 0;
    " N" N1 v$ b7 F2 ]7 B9 i6 w
  124.                         // 停机之前先把低压指示灯灭掉,以省电0 T' h2 D; N2 M3 u4 w9 K
  125.                         LED = 1;% I* A' \# z6 V: b! i3 R
  126.                         // 进入停机模式' X) ?/ ]. `  v
  127.                         PCON |= 0x02;
    # Y- t' w. o/ e0 B8 J2 l7 u& x
  128.                         _nop_();5 V5 W0 k- j# L! s) n% v
  129.                         _nop_();
    * d3 t! B  g3 |8 r: h# q5 y4 k3 V
  130.                         _nop_();9 e7 h2 `" O2 H! v4 P
  131.                         _nop_();2 u0 f% p0 I; A8 ~4 v' Q& G% o
  132.                         // 唤醒,清标志位
    ; q2 ]5 H+ z% Z
  133.                         isReadyToHalt = 0;
    , C7 V) T( l+ y/ V' q( g
  134.                         // 重开定时器0中断
    " m$ ^  S0 @, a, m: p9 W- |& Y
  135.                         ET0 = 1;! k( b, z3 u6 Y9 B( r: M
  136.                 }& {# P$ y4 H" U) q3 K9 D0 i8 c( d
  137.         }
    * u: ?4 B1 b0 _$ Y, r
  138. }' g9 o2 A5 N& t2 N/ n- n
复制代码

0 J4 B9 j, X1 o& ^硬件参数配置:" }2 d8 @6 m$ c% Q$ h

* x  x% v( g3 t" P! `( n  I* Z
- y( q* P5 J/ V1 c  B: k# @接收端:
" u0 m; X6 M# @" g3 Q$ s% W: Z- E9 J
  1. #include <INTRINS.H>
    ; u' }. a3 I0 o& ?: H
  2. #include "STC15W.h"
      C3 H  Z* h8 x- n
  3. ; t: _# D, h% V# e6 [
  4. + M& E3 P5 h2 @
  5. /*
    9 S6 _( ]9 w6 O2 U

  6. & j/ c, [  |6 R9 M0 r& m
  7. *---------------------------*. m+ J" N7 i/ k6 s8 W
  8. |1 (GPIO2)         \__/  (GPIO1)16|
    0 I; j, y/ u2 K& ?
  9. |                                                        |
    ! `4 U, g/ }* u& t* o- g
  10. |2 (GPIO3)                   (GPIO0)15|/ H# f7 y7 Z# B% S+ h* o6 ]
  11. |                                                        |
    : b- E( W5 l$ Q1 j
  12. |3 (GPIO4)                                  14|
    % R% {) O" B: P+ ^) q
  13. |                                                        |
    ' k$ p4 b$ }1 L& h1 r
  14. |4 (GPIO5)                        (DATA)13|
    / M( c3 G+ X) `# f3 r
  15. |                  STC15W204S                |
    , l) c2 a" N. p% f! {2 R
  16. |5 (GPIO6)                   (LATCH)12|, l' S- Q2 H* S/ z% x
  17. |                                                        |5 l3 V" D' P+ X0 J! o% r
  18. |6 (VCC)                         (CLK)11|
    . @2 O$ Z! O  @6 E' v, r
  19. |                                                          |3 s% ]% o0 k, N$ k7 {! m+ N! w
  20. |7 (GPIO7)                         (TXD)10|
    0 `: m) ]1 \& R/ w0 f
  21. |                                                        |
    , Z5 W+ r2 g& Q
  22. |8 (GND)                         (RXD) 9|7 s+ _9 }3 U! x
  23. *---------------------------*; f6 }5 Q* g: g  u. E
  24. Fosc = 12MHz( g5 K1 _* Y0 u  K4 y
  25. $ D! G9 R1 S& F$ Y, H  j  U# i
  26. P1.0 -> 上: ~. H) V4 L# t3 ^/ t
  27. P1.1 -> 左) A" y0 f* R. I6 x% _' e9 s
  28. P1.2 -> 下
    1 g" T* ?6 ]% z: N  w4 a/ n7 U9 _
  29. P1.3 -> 右7 J! {+ u: b' Y+ e3 Q8 }% S
  30. P1.4 -> SEL
    ) \' Q, {% F+ ?7 j' o2 I
  31. P1.5 -> STA
    2 y/ T8 y4 }: F( w3 B/ ?
  32. P5.4 -> B
    / G5 l% D: J# K1 Y! n
  33. P5.5 -> A
    7 q8 z8 m, p; [6 l5 o
  34. # p* [  n- Z" L! K6 ~
  35. */8 _# I' B& Q3 l" o* N8 y/ R
  36. 5 y' Q7 {9 M6 s2 {7 @" y
  37. " x5 c+ o) D, r9 V& z* K
  38. sbit CLK        = P3^2;9 S0 }) o, }' z
  39. sbit LATCH        = P3^3;
    $ `* _9 E$ ]# C, X% x
  40. sbit DATA        = P3^6;3 S2 B4 q) Y4 h8 D! w
  41. 7 Q* {! x8 ?) S0 m, S
  42. bit isReady = 0;
    9 R! t) d# X9 K$ m- F
  43. static unsigned char key = 0;
    2 z3 F6 ?5 y' x$ M9 k, v
  44. static unsigned char buf = 0;        // 双缓冲。这个缓冲区保存从P1和P5组合而来的键值
    - [5 y, M- z8 Z; ]  Q5 k9 m
  45. static unsigned char bufReady = 0;        // 双缓冲。这个缓冲区保存上面那个缓冲区的备份
    , I$ b+ P' ^$ a" K' p
  46. static const unsigned char data mask[] = {0x80, 0x40, 0x10, 0x20, 0x01, 0x04, 0x02, 0x08};        // A B SELECT START UP DOWN LEFT RIGHT。为提升速度,这个表放到RAM中
    5 h4 C  V8 `& G* f
  47. static unsigned char idx = 0;% f" A5 o" q. ?3 E

  48. ! m; n/ L$ G. I$ \5 }

  49. 8 W$ U; S# x& I5 ]8 x/ \0 c2 k
  50. static void GPIO_Init(){* e' `% s: a7 ~( \! J
  51.         // P1口和P5口用于接收并行信号,全部初始化为准双向,依靠内部弱上拉输出高电平: }2 o7 G( I$ [# v/ `
  52.         P1M0 = 0;& v+ C2 M1 X) R1 w" c4 S
  53.         P1M1 = 0;
    . S' ^. j! l" Y
  54.         P1= 0xFF;+ [$ g: \9 h4 f
  55.         P5M0 = 0;9 F  \% F' w( S+ d: L, j7 }
  56.         P5M1 = 0;' U+ E( P! c2 M1 z1 R( S4 m
  57.         P5= 0xFF;
    3 A* H) x1 j! V* X% @; Z: J/ @7 G2 m
  58.         // P3口初始化为准双向" j+ ]0 c1 m# o! M3 t6 m
  59.         P3M0 = 0;1 j( [% b) F  C/ g9 ~
  60.         P3M1 = 0;2 l7 [4 ^$ w7 x, r7 d: ]( f% t
  61.         P3 = 0xFF;* P+ H: i4 h+ G" b: L' o9 S( a3 j
  62. }8 V9 m2 d0 j, M* C# L. H) G- @$ n
  63. / W, e' d0 I5 V' P
  64. static void Interrupt_Init(){, R" `! n4 h* X
  65.         // INT0中断(CLK)触发类型为上升沿+下降沿0 l) Z. o% e( f. ^
  66.         IT0 = 0;
    6 P7 ?6 V( u, ~0 P# {
  67.         // 允许INT0中断1 X& \3 i4 q( F$ Q/ A
  68.         EX0 = 1;& F- ^# [) m" \4 F% S
  69.         // INT1中断(LATCH)触发类型为上升沿+下降沿
    9 x* x, B% V) F2 J( C# l! \
  70.         IT1 = 0;
    % D" [; O3 O2 t2 @6 A6 x( q
  71.         // 允许INT1中断$ O8 J5 U4 B* ^$ {# @  w2 e: q5 u
  72.         EX1 = 1;# t, e0 j% {& k! E, W
  73.         // 开启全局中断' m9 M' k$ {6 A* j
  74.         EA = 1;; U( D' l/ G2 d' |+ l; }% ], u/ ~7 S% G
  75. }
    ! u8 _8 C0 ~  I7 Z( ?7 n
  76. & M' ^. r$ X8 W1 O# \
  77. static void INT0_Isr() interrupt 0{) N" I5 v& Q. C% j
  78.         // 只有已经成功锁存才允许CLK移位
      A" N* [3 A7 r& e
  79.         if(isReady == 0), }+ s: j5 E2 A) u0 T! D6 z
  80.                 return;- V% t" C; p; q# t% @! ]
  81.         // 读当前引脚电平,如果是低电平则说明是下降沿,此时直接忽略该中断
    + U4 l- D9 g# i2 k3 B3 K& _2 z
  82.         if(CLK == 0)$ H- R- K* p4 f
  83.                 return;' g# ^* i& [. W5 t! M- s+ _* ^
  84.         // CLK上升沿到来的时候,取锁存值的下一位输出
    3 w* r2 @: N" b
  85.         idx++;9 b1 W3 |1 `& R' T
  86.         DATA = key & mask[idx];
    1 g% b+ r& k) q
  87.         // 如果已经完成7次移位,则一轮读取完成
    8 R% o# {( @2 U  E
  88.         if(idx >= 7)8 S# `) R) o0 n
  89.                 isReady = 0;
    6 b7 ^: I# G, ~7 i3 H
  90. }
    : F8 E$ H( R; r2 A0 u7 F* m

  91. ! C9 k. o! n- {. Q# e, V
  92. static void INT1_Isr() interrupt 2{# R; ^" S# o6 v7 F- D7 _
  93.         // 读当前引脚电平,如果是低电平则说明是下降沿,此时直接忽略该中断) m0 _# Q2 i3 O9 _/ Q
  94.         if(LATCH == 0)
    - ?1 u5 E6 t+ I# q* {
  95.                 return;
    8 v$ t' b- Q! q2 z: V
  96.         // 当LATCH上升沿到来的时候,锁存所有按键状态,同时把键值A输出到DATA8 G, B9 T& N- R7 U
  97.         key = bufReady;- d. L" ~/ [" X0 b4 L8 b6 f
  98.         DATA = key & 0x80;//mask[0];        // 为了加速运算,直接取表中的值而不是读表
    . W- t7 l2 f) f- U, t' C; g
  99.         idx = 0;6 {- o/ {* ^! X( l
  100.         // 允许CLK进行移位7 q$ F( j% w4 [# F" k& U4 A
  101.         isReady = 1;
    , z* b. D, \) n5 O3 c6 l. L
  102. }7 j% |5 Y; G# ?
  103. % M! U/ m4 Z; k
  104. void main(){
    / |! ]& W. s$ a% B) u* x8 T
  105.         GPIO_Init();1 k  c, `% t, j
  106.         Interrupt_Init();
      G+ d6 L8 R% t/ M" b. M: N
  107.        
    / B! `. E9 c/ `( v' u$ b9 P) b
  108.         while(1){
    + U4 g8 ^4 \6 @6 K% y
  109.                 //PCON |= 0x01;        // 进入省电模式
    " ^0 z1 C' U( H# G' `
  110.                 //_nop_();2 e6 W% Q, i' L1 \
  111.                 //_nop_();4 K" o( J( d7 \
  112.                 //_nop_();- E+ I6 ?2 N" @& Z- _9 d6 b1 Q
  113.                 //_nop_();9 l# z5 G- \5 i5 G$ A) q2 H& ^4 |  O* z- K
  114.                 buf = ~((P1 & 0x3F) | ((P5 << 2) & 0xC0));3 [" f) Y+ |/ _, l
  115.                 bufReady = buf;
    / i5 y& V/ t/ q7 Z
  116.         }& ~" J, I! [8 Z+ b# @6 @  l$ u
  117. }. g( `* c& v4 j
复制代码

" i. e) B! x. h0 D: P. Z硬件参数配置无特殊要求,晶振频率选择12M即可。# A9 a) l9 b/ x; M- [3 t

  z" m/ Y4 m; P- z这是编译好的固件。

本帖子中包含更多资源

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

×

评分

参与人数 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. z  @/ X+ |9 I' m9 r
不错的设计,想问一下楼主,FC的15针公头怎么解决?普通的公头太短了,插不进去FC的扩展接口。 ...
2 S0 Z3 m8 C6 E) ]1 [& K
坛友的改造方案
回复

使用道具 举报

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

使用道具 举报

发表于 2019-5-25 12:07:18 | 显示全部楼层
精彩,楼主动手强,也写得很详细。
0 Z8 S2 a7 i  s2.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
4 j+ j6 o, D3 t5 B3 ^& b- g精彩,楼主动手强,也写得很详细。
) J" R. {$ S. D. W2.4G方案是目前无线的最低延迟吗?

2 D& e- x. R' D, g8 T4 w8 [我没用过其他无线手柄,所以实在不知道我自己做的这个手柄到底是不是最低延迟。
( R/ q  y) o3 Z; m, V不过根据网上的说法,延迟高低主要是由通信协议的复杂程度,以及数据传输速率决定的。这个模块虽然是2.4G无线模块,但由于协议很简单,所以延迟比较低。
& h* m& D. ~* K" b4 @) a9 [& I8 F我用这个手柄玩一些ACT游戏,比如超级马里奥、忍者龙剑传、热血系列,完全感觉不到延迟,和游戏机自带的手柄没有任何区别。唯一的区别就是这个手柄是用火花山寨手柄改造的,外壳是垃圾回收塑料,粗糙+脆弱,导电橡胶弹性不佳,手感不是一般的差。9 C. c. ~, F; A" s
我手里还有十几张板子,等我有空了我再做一套,到时候买一个好一点的手柄改造。
回复

使用道具 举报

 楼主| 发表于 2019-5-29 16:56:14 | 显示全部楼层
ppad 发表于 2019-5-28 17:27
' r; F' e' q8 z: B0 }# k" M给技术帝赞一个,有半成品发布吗,自己焊接改造就可以,编程实在不会啊 ...
1 ?2 I# g/ q4 x- g, t0 L: L, S- v6 ~
很可惜,我手里没有多余的单片机了,LDO也找不到了,锂电池以及充电模块更是没有了。反正就是该用到的元件基本都没了,所以没法发布半成品。4 s3 p3 U4 G' f' D, S
两个板子倒是有十几张剩余。# G  A! p# O+ }& T& O' `4 i
你要是有USB转TTL串口板,完全可以自己买这两种单片机,然后我给你编译好的固件,你自己用串口板下载到单片机里面就行了。两个2.4G无线模块也得通过串口板用AT命令设置参数,不过好在我在设计电路的时候就已经预留好了串口,可以直接在线下载和在线设置参数。总的来说并不麻烦。
回复

使用道具 举报

 楼主| 发表于 2019-5-29 17:00:34 | 显示全部楼层
孙大师 发表于 2019-5-28 18:55
! K3 X8 K; K- T# ~8 R: c) y非常好,楼主是技术帝,到目前我都还没开发fc的无线套件,等空了,开发一套套件,等玩家自己组装。 ...

) D4 y, e7 L/ K) ^" q9 @! u; F& `能得到孙大师的赞誉,不胜荣幸!5 a0 J1 N* t+ c3 U+ j
不如开发一个多功能手柄,比如用SFC手柄改造,L/R键配合其他组合键可以用来切换2P~4P、调节连发速度、软重启等各种功能。接收端插到15PIN扩展口。
回复

使用道具 举报

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

本版积分规则

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

GMT+8, 2026-7-22 14:52 , Processed in 0.103412 second(s), 15 queries .

Powered by Discuz! X3.5

© 2001-2025 Discuz! Team.

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