电玩DIY [ VG DIY ] - Video Game Do It Yourself

 找回密码
 注册

QQ登录

只需一步,快速开始

查看: 14764|回复: 27

自制FC无线手柄

  [复制链接]
发表于 2019-5-22 14:16:45 | 显示全部楼层 |阅读模式
本帖最后由 雷精灵2046 于 2019-6-14 09:28 编辑 ! I6 L$ P, W; m  `: n/ @% g

" @2 f# Q* o- q& h* E6 F没有用复杂的分立元件搭建发射接收电路,直接用的现成的2.4G无线模块jdy-40。& J0 [% \! N) m( j

, n# {  P$ _! {7 ]3 y! x) v3 S7 Z5 f) E1 e( c* u$ |
发射端靠3.7V锂电池供电,用了一片SOP8封装的STC单片机,负责产生连发脉冲,同时负责检测电池电量,电压低于3V左右的时候触发低压中断,低压指示LED就会亮起来告知该充电了。平时发射模块和单片机均处于睡眠状态,有按键按下才会唤醒,从而实现省电。实测睡眠状态下整机电流约1~2uA。板子洗了一下稍微干净了一点。因为对于微功耗设备来说,焊接残余的助焊剂可能会增加漏电流。
+ J* |" Y- g  a8 A+ c1 O6 a( J/ b, j$ A
买了一个火花的FC山寨手柄,去掉里面的牛屎板子,并修正一下塑料挡板,把锂电池和充电模块装进去。
+ L9 X) g7 l0 w, u为了减少体积,充电模块裁剪得十分小,并且更换了充电电阻使之适应这个小小的锂电池。这么小容量的电池,也不需要多么大的充电电流是吧?
* J5 G) m' b9 D" a然后统统用热熔胶粘上。充电电流比较小,所以发热很少,不会熔化热熔胶。0 |$ X% s: |1 G0 E# @
/ k' a4 e- K# y- r& V3 l
+ T& ]- G0 s% A  m
+ C, G0 i0 j( A: y. G  f
最后把按键、导电橡胶和电路板装上去。/ f% q5 b  B/ h5 p
精心裁剪了电路板,正好扣上,不会阻碍其他元件,也不会影响后盖和拧螺丝。% \5 q2 G5 i4 d/ [  i- A0 C; u( f- f

( @# E7 z$ s" e4 M6 s; y( R
; _" C5 w( D; \* r完工!* a* g# W! C2 |
# f' j9 a: Q3 j0 {3 R  p

" a7 v9 p& R: e" i4 h7 C- e8 u这是充电的MicroUSB插座。旁边的小孔用于透出低压报警LED的光线。
7 w- w. a$ {' I$ \) ?6 G4 H- H  K! _" U& C- J9 [
$ a. ~; E4 Y$ V1 F
接收端用一片DIP16封装的STC单片机模拟CD4021。为啥要用单片机模拟而不是直接用CD4021?因为jdy-40模块接收端在有按键按下的时候输出高电平,无按键按下输出低电平,和普通手柄正好相反。当然我也可以用两片74HC00或者74HC04之类的逻辑门进行反相,但那就增加了芯片的数量。对于FC手柄这种工作频率并不高的设备来说,STC单片机完全可以胜任模拟工作。
) [& d0 h3 t: M' C9 m- w5 n- G: T  M* Y

5 z3 q/ S# n! v* P) H5 w
* l( o$ C" c/ @, m$ }; z  }电路设计有点小小的错误,所以有几根飞线。原本设计使用低压差LDO是XC6206,结果在做这个接收模块的时候,买的LDO居然找不到了!无奈只好用了AMS1117。幸好对于接收模块来说是5V降到3.3V,1117可以胜任。要是发射端手柄的话,3.7V降到3.3V,那就非得用6206不可了。/ {; s; o% J2 W# Q1 u# s; A  M3 S/ U2 P

6 ~- w8 p5 L7 |: v' t实测十分灵敏,延迟极小几乎感觉不出来。可惜这山寨手柄的手感并不佳,尤其是方向键,软塌塌的。看来我得买个剪线手柄改装。/ X0 N& a9 R7 C6 |8 s9 i( p9 S  R

$ G* e/ j3 p" ^8 }" X6 l这是电路图,有兴趣的朋友可以参考。" ^2 W4 u3 h5 L6 Q9 l. d
; w) o8 |& `5 m: F4 j8 ^

$ P3 o1 @4 R6 S0 @  e( u我信奉开源主义,十分痛恨把技术藏着掖着。好东西大家分享嘛!所以两个单片机的源代码大公开!' G! U; w( m6 ?  V3 W* ~: c" x# ]
编译器:Keil 51。
* M) j% b5 Q# {# \
! c  C. `0 S, v发射端:! P! Q1 ?8 V  W" U' m. N
  1. #include <INTRINS.H>
    8 ]+ n9 }. \! ]+ y: f- S: k) W; s: i
  2. #include "STC15W.h"6 T; ?( T+ S5 Y( [; y

  3. . F& p  B' Z7 n
  4. 4 g2 T0 `2 S, W/ b
  5. /*3 H) l# H& l" D9 O
  6. --------------------------  e1 x# @: _# @
  7. |1 (OUT)        \__/   (INT1) 8|& x) }7 Z& Q8 v' D1 i4 Q
  8. |                                                   |
    ' Y; a' A% L. ?/ |$ c. v  t
  9. |2 (VCC)                   (INT0) 7|$ U  t$ s$ \; O5 k6 A2 ~
  10. |                 STC15W204S                   |5 ~; T6 G2 q( o0 ?1 b+ J' i" S8 L
  11. |3 (LED)                         (TXD) 6|
    - D7 h% `3 X2 I# ]- G5 e$ d
  12. |                                                   |' C  r4 |6 i* w3 u( F
  13. |4 (GND)                         (RXD) 5|  w- D2 M5 m! [  U! W9 `4 T
  14. --------------------------
    ! p+ M' z2 U! C: _% z. h' Y

  15. $ {  j$ X  ]' K% r3 T+ p# l/ w
  16. LED ---|<|---[===]--- VCC
    / ^7 b* J8 f/ S6 T! N0 |! `
  17.            Red          3306 X. A7 ^/ m" q7 A, H+ R; j1 H
  18. 7 N, p" k. h  p$ x' j% b
  19. Fosc = 6MHz
    ' G3 W6 v1 |6 g4 X# I7 B" I
  20. */- c+ `5 @: g& s3 Y# d, ?4 d$ ^2 ~9 y

  21. ( {, L1 [1 k( E; O) T: U8 _

  22. # E0 y; N" h1 s) d8 W
  23. // 矩形波输出脚! E5 d. x+ F* J
  24. sbit OUT = P5^4;2 E8 t% R- W8 d  f0 [9 g6 _
  25. // 低压指示灯引脚; |# m  |! E9 D& Z1 C: Y& A
  26. sbit LED = P5^5;/ l$ T3 D6 X5 z- s4 }+ m
  27. ) E, |7 T+ ^9 z+ S
  28. // 停机标志位6 U* p/ T) R+ r
  29. bit isReadyToHalt = 0;
    5 D, a" z$ g4 n" D+ S! K

  30. : D. H  J4 A' N' G, M
  31. // 矩形波次数累计
    * U2 }' z4 V5 N) ?
  32. static volatile unsigned char count = 0;
    ) q' u* [. k! N
  33. - o5 S/ A' n2 L* B# v! ?" V

  34. 3 x8 r& H* p& r5 m. ?6 j8 O
  35. static void GPIO_Init(){
    8 X/ c" U. x# q( e/ _3 |
  36.         // P3口设置为准双向,默认靠内部弱上拉输出高电平7 ?$ K. n( c  i% {8 ^$ O& c# t! v
  37.         P3M0 = 0;
      ~* ^4 c8 n+ I! }
  38.         P3M1 = 0;# S, K# `& p. \1 w
  39.         P3 = 0xFF;
    / J; N6 \* R5 o  l4 W8 d/ k
  40.         // P5口设置为准双向,默认靠内部弱上拉输出高电平7 b3 M4 H! b( e% {  u: w4 [- A
  41.         P5M0 = 0;
    * m: p! }( y" K
  42.         P5M1 = 0;
    , H* z: }9 d$ B0 Z, b
  43.         P5 = 0xFF;
    : p( [2 U8 _' U7 D2 u
  44. }4 z0 w$ K" {; h  v/ W7 I

  45. + Y/ }* a' X/ B
  46. static void Timer0_Init(){" k9 z% a5 v- _7 J$ c
  47.         // 16毫秒@6.000MHz" P$ ~9 f( M# |# T* O' P/ l( B
  48.         AUXR &= 0x7F;        // 定时器时钟12T模式
    # i! g9 s  w8 o+ I; T
  49.         TMOD &= 0xF0;        // 设置定时器模式
    8 v  C: N1 j0 \8 D$ M! ]2 J( _! l7 z
  50.         TL0 = 0xC0;                // 设置定时初值
    , N7 E6 J3 l6 _4 A4 @9 D* |
  51.         TH0 = 0xE0;                // 设置定时初值
    5 S0 }+ ^9 D. R
  52.         TF0 = 0;                // 清除TF0标志/ g/ G1 \1 @5 w5 A% i& S
  53.         TR0 = 1;                // 定时器0开始计时
    + V8 ]+ o' v+ c4 e, N0 C, t0 h5 ]* A
  54. }
    ( V' w4 c8 X3 x! d3 S, y; u
  55. ! V+ W/ ~0 X" r- J8 z, h5 `
  56. static void Interrupt_Init(){
    " Y# I9 X  b6 A/ X! J7 D
  57.         // INT0中断触发类型为下降沿触发, m! z- f4 y" G8 _# w% L
  58.         IT0 = 1;( w0 P9 }& K' X1 L9 C% w5 C
  59.         // 允许INT0中断
    3 @3 Y" G% p3 Q: j
  60.         EX0 = 1;
    2 S  S' `4 }7 A# Q/ c( F
  61.         // INT1中断触发类型为下降沿触发
    5 d# F) c- p7 T4 O
  62.         IT1 = 1;& b$ X1 |- v. n' \* O' Y
  63.         // 允许INT1中断$ |- F. ~8 _4 L" c0 T! J4 o6 p
  64.         EX1 = 1;: h. `! q) l4 U' [7 d4 B+ [2 L
  65.         // 允许定时器0中断2 l7 N3 s! a) k' e3 d
  66.         ET0 = 1;, d' g3 ~8 L% Q* G; L+ {# y* c
  67.         // 允许全局中断& c" w6 O; ]; {6 Y& D* j5 g
  68.         EA = 1;; x; h  V: C( B- L0 [2 e9 w5 m
  69. }6 m: d# q, `% K' C9 v5 V

  70. 1 X7 p9 s; C* m
  71. static void INT0_Isr() interrupt 0{2 l5 Q. ?' t! J# Q, u) ^8 R
  72.         // 矩形波次数累计归零
    & f, d- m) T# H6 H- h' X
  73.         count = 0;: G9 m6 }7 {6 l; \5 j1 S) M
  74.         // 重开定时器0中断
    2 B, H& {: _5 ^2 R5 E* a
  75.         ET0 = 1;
    / N/ ]5 n4 r0 L5 C) g$ L6 s
  76. }
    % Q5 M7 E0 u) P6 Y
  77. , Z# Q8 d. \' Q8 b: w% t
  78. static void Timer0_Isr() interrupt 1{
    6 Q1 A5 o# [- {4 f/ G* C
  79.         // 输出矩形波
      O( i- r0 s4 T# R; b
  80.         OUT = ~OUT;5 A; G% P2 r. y/ O0 Z. x7 m
  81.         // 累计矩形波次数
    7 W/ W8 B+ ]* ~, h; B/ m* c5 g
  82.         count++;, H$ g3 ?1 ?- |1 s+ a9 M" d, s/ l
  83.         // 超过250个矩形波,准备停机; J5 S) V  L7 u& }
  84.         if(count > 250){
    - g- j; k% W6 N/ U- N, o+ L
  85.                 count = 0;
    ) F4 t- E) e& S/ ~  _
  86.                 isReadyToHalt = 1;! m' x  _$ Y- K# u
  87.         }8 s- i/ J# B  m% Q1 P
  88. }& p) x& f) k) Q5 ~& Y

  89. ( J1 u" V1 u' h* j0 P$ ?
  90. static void INT1_Isr() interrupt 2{7 d, E7 ~. k6 b. N0 K
  91.         // 矩形波次数累计归零
    $ V$ _* {" x. h0 _2 l/ {8 U
  92.         count = 0;( a, }: E" C! J8 m& W1 `
  93.         // 重开定时器0中断
    ) b+ m6 ^7 ^# b. i
  94.         ET0 = 1;  g; V5 T. c6 b$ a
  95. }2 |+ \+ P) I/ h" n" E5 L
  96. 8 R# X, S6 V" R' U
  97. : ~9 ]* N! t4 V, D
  98. void main(){
    5 J9 b' `3 v! @) v+ ~3 q
  99.         // 初始化P3和P5口
    5 [$ b& L) ^+ W, l
  100.         GPIO_Init();  u# O6 F$ N- }- W5 @
  101.         // 初始化定时器0
    " i7 G! o8 \; Y1 {
  102.         Timer0_Init();
    + Y8 K# J% d7 x! g: X
  103.         // 初始化中断
    8 y, M$ }5 {' @
  104.         Interrupt_Init();2 W3 I/ V. j! |* U
  105.        
    ; ]; Y# e; O; N& A
  106.         while(1){7 r9 P: J  D! `: {
  107.                 // 检测电量5 n& E  b5 K) e4 t# ~3 i
  108.                 if(PCON & (1 << 5)){+ a& n2 R0 O2 D. l! y2 c0 W7 |
  109.                         // 如果电量低,低压指示灯亮: X, S+ R; f+ n. v: i# m. p; q
  110.                         LED = 0;( i+ [' b: E  g
  111.                         // 清电量检测硬件标志位
    & b, a( Y& \# R$ m3 j- @
  112.                         PCON &= ~(1 << 5);+ T, L/ I) j0 k! ~
  113.                 }else{
    ' |! X% B- Q$ u( A0 }! J
  114.                         // 电量正常,低压指示灯灭; j8 ^' x4 ^8 R7 y! O6 T& Z) @
  115.                         LED = 1;  k0 H0 ^3 Z8 t- T; E* _
  116.                 }* K- U* f1 ?$ I' [6 R: |
  117. # ]" M+ d2 `7 L3 ?
  118.                 // 检测到停机标志
    . Q0 x/ K( v  }  P' I$ s
  119.                 if(isReadyToHalt == 1){
    1 Y0 T4 j, r! D" z2 I2 K5 [4 y
  120.                         // 暂时关闭定时器0中断  M2 q6 X' }9 Y9 d: s" `
  121.                         ET0 = 0;+ [& _! ]) j9 d' K, k1 D
  122.                         // 停机之前先把矩形波输出脚置低电平,以方便INT0和INT1唤醒CPU2 A; D1 k( G4 w/ {
  123.                         OUT = 0;
    2 k+ \, I8 x2 n* X" C! N7 ^
  124.                         // 停机之前先把低压指示灯灭掉,以省电
    $ i4 q) \5 V, Q+ ?1 c( N& s8 s
  125.                         LED = 1;
    6 R5 e# P" Y. y! M" \
  126.                         // 进入停机模式
    5 R! \+ E+ B! }. E0 y* g% W. K& r
  127.                         PCON |= 0x02;. N/ v+ L& F7 i
  128.                         _nop_();& l5 ^* Z* F/ \7 J% C! H
  129.                         _nop_();
    & V8 e/ V, {2 h7 ^! t  g: s, E" l
  130.                         _nop_();1 K4 r! z- Z7 f$ ~! R: U
  131.                         _nop_();
    ; O9 Y% q/ Q) [1 }3 j
  132.                         // 唤醒,清标志位% v- J* V& l  o1 f0 T$ X8 z- k
  133.                         isReadyToHalt = 0;
    / V8 i$ b( w: t  }: i4 Z$ q
  134.                         // 重开定时器0中断
    ' x6 {& p* C/ s; `, k
  135.                         ET0 = 1;
    2 ?* p* y$ p9 j1 @2 n2 S
  136.                 }
    . \5 {( c9 g8 b0 C& \2 k( O
  137.         }( p+ S! W1 F8 B) g
  138. }
    ) x) p; j* Y( B$ ]
复制代码
9 \/ ~( L6 t( a, L3 _2 ~
硬件参数配置:2 e$ M4 s. U0 m3 L# L
% j( ]* K5 D4 ^  p

5 X' d6 e6 J0 P9 Y6 V( n( m接收端:2 s8 {0 D$ f; [+ z$ j4 M
  1. #include <INTRINS.H>: |! W/ G0 U* \
  2. #include "STC15W.h"
    # ~$ C+ T) Q9 n  A

  3. ; m) ^# D$ v7 ~! h  x) F% s
  4.   C; }2 v9 X' t5 O" j, R1 S
  5. /*% ^5 Y( `; U& G7 r0 G

  6. , ]% t. p4 v( P) B2 V0 P
  7. *---------------------------*# ?* n7 M9 e! @5 A0 L7 D; \
  8. |1 (GPIO2)         \__/  (GPIO1)16|
    ( X% n5 m3 I( c
  9. |                                                        |  j7 L% C5 d  f9 g( `
  10. |2 (GPIO3)                   (GPIO0)15|$ D5 L8 F7 \- t* `( l, K; I' b  a
  11. |                                                        |
    . z# H" V# F0 k' v
  12. |3 (GPIO4)                                  14|
    4 x/ M6 f' A( t9 b
  13. |                                                        |& L) x, H, B8 X( J% t
  14. |4 (GPIO5)                        (DATA)13|" e% e/ D) X% |8 c# k1 s
  15. |                  STC15W204S                |, z) u# d) `: H3 }% r+ B
  16. |5 (GPIO6)                   (LATCH)12|
    7 C. V+ [' H$ j% o0 Y; a
  17. |                                                        |
    1 A8 ~0 p, q; q9 C, o4 J
  18. |6 (VCC)                         (CLK)11|
    4 s. D% T+ f9 Y3 F) N
  19. |                                                          |
    5 y  r; ?0 Y) g/ o+ c/ v
  20. |7 (GPIO7)                         (TXD)10|
    $ z' Y5 k) k: h) {) y) Q( s% ]4 ?
  21. |                                                        |
    ' r9 m& H) s+ w7 D$ X
  22. |8 (GND)                         (RXD) 9|
    ) J' j( u4 w) [3 `4 @8 W
  23. *---------------------------*: _; s7 z$ D2 ?' n7 w' Q
  24. Fosc = 12MHz4 W$ E8 Q1 T( Z  z0 V
  25. & J* X( R; ?" n4 @& R! O$ b
  26. P1.0 -> 上" r- S5 }8 C4 a- v$ j3 s% t
  27. P1.1 -> 左4 B0 V& s0 q# q8 ~6 w* {$ X
  28. P1.2 -> 下
    : `8 t* i2 G+ p( g: f
  29. P1.3 -> 右
    * S7 m6 w% l9 b- Z
  30. P1.4 -> SEL
    7 r8 G1 |2 o/ K* O; V6 x
  31. P1.5 -> STA
    * \4 ~5 T) }2 _6 V
  32. P5.4 -> B% v2 s8 l' I6 i
  33. P5.5 -> A
    + M2 ]) m* t: z. M- J
  34.   Q2 D4 @) W& L4 k$ i  s# V
  35. */
    7 G% H2 S: v; v

  36. , F+ B3 h% h7 i+ [
  37. ' j" X$ _, D" U) H& S$ H" i. I4 Y
  38. sbit CLK        = P3^2;
    + d3 C* d' t& v# z  o, Y
  39. sbit LATCH        = P3^3;
    ( w, W  b/ v: q. E8 d
  40. sbit DATA        = P3^6;$ N3 E( f, x3 h9 K
  41. . I1 A4 N# s( c- z# c0 ]
  42. bit isReady = 0;
    ! T0 K; b$ V/ A" ^. P
  43. static unsigned char key = 0;
    - I( }% G% g3 Q) d6 R: I
  44. static unsigned char buf = 0;        // 双缓冲。这个缓冲区保存从P1和P5组合而来的键值
    : X% l4 T9 o: u2 m% g0 a
  45. static unsigned char bufReady = 0;        // 双缓冲。这个缓冲区保存上面那个缓冲区的备份
    ; [$ \- z! V9 p  h
  46. static const unsigned char data mask[] = {0x80, 0x40, 0x10, 0x20, 0x01, 0x04, 0x02, 0x08};        // A B SELECT START UP DOWN LEFT RIGHT。为提升速度,这个表放到RAM中
    " N# Z7 R% W' }
  47. static unsigned char idx = 0;
    6 e' K6 Z7 s: i

  48.   |- T( W& I3 {4 @6 a4 V

  49. 5 q  p7 A1 [9 Y2 f- _) O% i* m
  50. static void GPIO_Init(){, J* V( M. ]- k4 H$ }: o/ y
  51.         // P1口和P5口用于接收并行信号,全部初始化为准双向,依靠内部弱上拉输出高电平
    * @1 N/ f0 ]; C0 Q1 G- [
  52.         P1M0 = 0;/ h% w: @6 l5 K3 M
  53.         P1M1 = 0;8 ^) L9 X! z5 t
  54.         P1= 0xFF;
    , t5 v: p0 V0 S8 L' _1 B" A
  55.         P5M0 = 0;- f& N. b0 Z# V1 F) F9 Q
  56.         P5M1 = 0;1 p5 s% c+ d& L7 a6 C4 j
  57.         P5= 0xFF;
    9 i9 y; Y) M/ D/ M8 @# ]
  58.         // P3口初始化为准双向  m  f/ w: h0 I. \
  59.         P3M0 = 0;
      u1 S, Y. S' B/ z8 I
  60.         P3M1 = 0;! e6 K3 Q- O& P. u
  61.         P3 = 0xFF;: M5 C+ @7 m/ L. k0 P! \$ E3 Y
  62. }
    + \) q+ A% Z* K0 C, ^/ C9 g

  63. , r# }) O+ T* P" x' J9 |
  64. static void Interrupt_Init(){
    ' N/ D2 q3 Y! n8 }
  65.         // INT0中断(CLK)触发类型为上升沿+下降沿
    ! E0 |. M- u5 ]' m8 A
  66.         IT0 = 0;
    # L7 E) @  r; |8 n
  67.         // 允许INT0中断! M/ S, L" i: s/ C$ d
  68.         EX0 = 1;
    7 R8 ?, [9 z2 ~. R, ~
  69.         // INT1中断(LATCH)触发类型为上升沿+下降沿& b) l( J" [+ `% v8 Q- p' z
  70.         IT1 = 0;
    % {. l$ O6 V7 o) A8 }  x) k
  71.         // 允许INT1中断% v1 S& W% D- D9 P3 U
  72.         EX1 = 1;
    6 x% o4 x* {. b2 ]2 g6 l; k5 P
  73.         // 开启全局中断4 R$ m2 i" o+ X( X& |
  74.         EA = 1;% z- X' \9 ^  c2 K% R: o1 `
  75. }
    9 S' I+ ?1 I! m; z# ~; s# H$ T0 L
  76. ) v7 N/ R  L' ?3 ~4 V4 H
  77. static void INT0_Isr() interrupt 0{  ~* F6 `; B: k2 N7 B, V( v( J
  78.         // 只有已经成功锁存才允许CLK移位
    : w: B. {8 u( x+ \( U3 s
  79.         if(isReady == 0)
    9 D5 S$ _( {8 T' \4 h# |' d- O
  80.                 return;
    2 T; R( r- p2 V7 G& _$ E. k6 W3 J
  81.         // 读当前引脚电平,如果是低电平则说明是下降沿,此时直接忽略该中断
    9 c6 u5 G5 d; K, C
  82.         if(CLK == 0)% \. c5 |! P3 L9 n8 {4 A2 H
  83.                 return;( u' l5 @4 ^% b7 U
  84.         // CLK上升沿到来的时候,取锁存值的下一位输出* w; [5 E% z" E+ `. D1 m
  85.         idx++;3 O; B. B3 ^6 L/ W+ o9 I: N
  86.         DATA = key & mask[idx];- Y8 T6 A% e# x8 u. N- e' l
  87.         // 如果已经完成7次移位,则一轮读取完成! H1 o; e, I, F% V: K- {5 P) f) B, l
  88.         if(idx >= 7)
    3 N7 Z6 Y" Y( ~/ H+ @2 Q
  89.                 isReady = 0;
    * f1 n+ W/ h" r/ H' N; i6 v
  90. }' G% Y3 {8 ~% ], H1 C) x& C
  91. % ]! L: b( `6 R
  92. static void INT1_Isr() interrupt 2{
    4 j$ X! F- S* o4 _* Z* U! l
  93.         // 读当前引脚电平,如果是低电平则说明是下降沿,此时直接忽略该中断8 A! z' A) U) u( Q+ N) K) m! @
  94.         if(LATCH == 0)8 e8 B, q7 m& M3 N* H- U- d
  95.                 return;+ i: |( c: S& b; W5 w) t3 {& K
  96.         // 当LATCH上升沿到来的时候,锁存所有按键状态,同时把键值A输出到DATA& J9 Z( O! O) _  D) Z; s
  97.         key = bufReady;
    / S/ Q; w& E0 E' X+ y# D4 }
  98.         DATA = key & 0x80;//mask[0];        // 为了加速运算,直接取表中的值而不是读表
    $ C5 z0 |6 ]/ R4 x
  99.         idx = 0;
    ) f" _2 P$ r& C' V; {1 n& {' ]4 c
  100.         // 允许CLK进行移位
      V5 \4 T6 i/ p! m; p( E
  101.         isReady = 1;
    8 ^/ A: _, _( e
  102. }. R$ u+ Q7 @: j% o+ D

  103. 5 E- |  @8 k* F" C
  104. void main(){2 M) Y+ R% z0 N1 B; W: j0 k( D
  105.         GPIO_Init();: Z5 @+ }  A  p. }: ~" q; k! B
  106.         Interrupt_Init();" L- s+ Z( I! _% n' L8 `6 B1 V
  107.         6 E$ w" c/ }; T- D
  108.         while(1){/ ]( b5 z: `$ z; o
  109.                 //PCON |= 0x01;        // 进入省电模式
    * r% G! L: ~. B, v4 }
  110.                 //_nop_();
    2 ~( {, |/ t1 x0 y1 j8 R5 i
  111.                 //_nop_();+ V! b) @0 G. }* n2 }
  112.                 //_nop_();
    + O6 l9 N3 Y4 U& h+ J8 y- [0 c
  113.                 //_nop_();
    ( [3 x* ~) O2 {0 u  S) ^
  114.                 buf = ~((P1 & 0x3F) | ((P5 << 2) & 0xC0));
    ( H! H- n6 Q4 Y  f8 x* w, J& A; O
  115.                 bufReady = buf;; @5 T5 i4 N) I) z7 d
  116.         }
    6 l0 g6 P; a! l6 t; p0 V! c
  117. }1 Y9 g/ W7 ^- F' l3 R0 [
复制代码
9 f) O8 T  @0 t* U! V* @% q$ x- L4 a- f
硬件参数配置无特殊要求,晶振频率选择12M即可。
# |& _5 [2 O; c* @/ r+ A0 m! R6 o$ B2 l
这是编译好的固件。

本帖子中包含更多资源

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

x

评分

参与人数 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
( V) U' N! n; P0 c( S5 Y3 f# E不错的设计,想问一下楼主,FC的15针公头怎么解决?普通的公头太短了,插不进去FC的扩展接口。 ...

+ s, ]; {! n- `! x坛友的改造方案
回复

使用道具 举报

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

使用道具 举报

发表于 2019-5-25 12:07:18 | 显示全部楼层
精彩,楼主动手强,也写得很详细。
3 ~. I: r' o( V8 @( b5 }: Q2.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
* X+ x( }. g* }* ]精彩,楼主动手强,也写得很详细。
' ]6 i) F0 _5 O: G2.4G方案是目前无线的最低延迟吗?
) G7 @; p, I" Q
我没用过其他无线手柄,所以实在不知道我自己做的这个手柄到底是不是最低延迟。. O. ^7 h2 H, [2 L6 m( c/ w
不过根据网上的说法,延迟高低主要是由通信协议的复杂程度,以及数据传输速率决定的。这个模块虽然是2.4G无线模块,但由于协议很简单,所以延迟比较低。
7 \, p! k  v- i4 X我用这个手柄玩一些ACT游戏,比如超级马里奥、忍者龙剑传、热血系列,完全感觉不到延迟,和游戏机自带的手柄没有任何区别。唯一的区别就是这个手柄是用火花山寨手柄改造的,外壳是垃圾回收塑料,粗糙+脆弱,导电橡胶弹性不佳,手感不是一般的差。
; r* d1 n9 l1 b) j! T; T" x9 w; `我手里还有十几张板子,等我有空了我再做一套,到时候买一个好一点的手柄改造。
回复

使用道具 举报

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

使用道具 举报

 楼主| 发表于 2019-5-29 17:00:34 | 显示全部楼层
孙大师 发表于 2019-5-28 18:55
8 i; ^- V1 G. k% i1 u% l非常好,楼主是技术帝,到目前我都还没开发fc的无线套件,等空了,开发一套套件,等玩家自己组装。 ...

) p9 `8 u6 X9 ~2 l( }; b2 c. I能得到孙大师的赞誉,不胜荣幸!
" s) `8 y. Z9 D3 Y' t不如开发一个多功能手柄,比如用SFC手柄改造,L/R键配合其他组合键可以用来切换2P~4P、调节连发速度、软重启等各种功能。接收端插到15PIN扩展口。
回复

使用道具 举报

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

本版积分规则

小黑屋|手机版|Archiver|Video Game Do It Yourself ( 闽ICP备14000865号 )

GMT+8, 2024-4-28 08:07 , Processed in 0.071758 second(s), 17 queries .

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

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