找回密码
 注册

QQ登录

只需一步,快速开始

查看: 26165|回复: 32

自制FC无线手柄

  [复制链接]
发表于 2019-5-22 14:16:45 | 显示全部楼层 |阅读模式
本帖最后由 雷精灵2046 于 2019-6-14 09:28 编辑
/ t4 `% L  J" M) x+ ^
! A  |% \# B9 d1 m没有用复杂的分立元件搭建发射接收电路,直接用的现成的2.4G无线模块jdy-40。2 R# `/ |. ~4 [( t' @. r. k5 f8 {

$ a( g1 a- A2 l: Z# C4 A/ F9 Y
' _8 N6 }, O6 A4 H  F/ m' G$ O发射端靠3.7V锂电池供电,用了一片SOP8封装的STC单片机,负责产生连发脉冲,同时负责检测电池电量,电压低于3V左右的时候触发低压中断,低压指示LED就会亮起来告知该充电了。平时发射模块和单片机均处于睡眠状态,有按键按下才会唤醒,从而实现省电。实测睡眠状态下整机电流约1~2uA。板子洗了一下稍微干净了一点。因为对于微功耗设备来说,焊接残余的助焊剂可能会增加漏电流。
' q  m6 k% j% v
% J1 N7 O% Q. o9 C买了一个火花的FC山寨手柄,去掉里面的牛屎板子,并修正一下塑料挡板,把锂电池和充电模块装进去。
4 `. L8 ~7 S. j! \为了减少体积,充电模块裁剪得十分小,并且更换了充电电阻使之适应这个小小的锂电池。这么小容量的电池,也不需要多么大的充电电流是吧?* V8 A$ k+ ?* |
然后统统用热熔胶粘上。充电电流比较小,所以发热很少,不会熔化热熔胶。; |4 V6 C& O4 N  w/ |) R/ R9 J

  M7 e9 h& Z5 X2 i; @, B; p3 W2 _: N8 [5 Y
: M9 ^+ H3 y- I2 H# g7 H7 Q/ P% v0 j9 @
最后把按键、导电橡胶和电路板装上去。
, V% c# Y$ s5 U8 j3 V精心裁剪了电路板,正好扣上,不会阻碍其他元件,也不会影响后盖和拧螺丝。
7 s3 D' A1 }2 w- G& G' s! G' Y# z( k1 p3 x: x6 O; Z

& A' ]$ o' \$ x% u: @5 O, s8 F  v完工!
6 S9 A9 t* ]2 S) m( E+ r. X: {3 p) _) |: D
) W& v! n7 x/ n% w- c5 o
这是充电的MicroUSB插座。旁边的小孔用于透出低压报警LED的光线。
! ^8 T& h9 T# d6 t
2 d' M- b/ Q2 V5 ]2 B: X1 R* l  g3 L  p& z% M) r; Y
接收端用一片DIP16封装的STC单片机模拟CD4021。为啥要用单片机模拟而不是直接用CD4021?因为jdy-40模块接收端在有按键按下的时候输出高电平,无按键按下输出低电平,和普通手柄正好相反。当然我也可以用两片74HC00或者74HC04之类的逻辑门进行反相,但那就增加了芯片的数量。对于FC手柄这种工作频率并不高的设备来说,STC单片机完全可以胜任模拟工作。
. E4 y2 k5 Q, S0 K% Q4 q" V; ?- @6 J& B* M% L
1 I4 f  w* G& q
$ ^# m( c1 ^4 C3 L/ ~
电路设计有点小小的错误,所以有几根飞线。原本设计使用低压差LDO是XC6206,结果在做这个接收模块的时候,买的LDO居然找不到了!无奈只好用了AMS1117。幸好对于接收模块来说是5V降到3.3V,1117可以胜任。要是发射端手柄的话,3.7V降到3.3V,那就非得用6206不可了。
: `1 h1 \5 A1 D: ]! q+ j* F
2 g# L& k; m, e实测十分灵敏,延迟极小几乎感觉不出来。可惜这山寨手柄的手感并不佳,尤其是方向键,软塌塌的。看来我得买个剪线手柄改装。# E0 N$ s; T7 y( ^6 @* `0 Z! m) o
( m! \6 w9 w( e0 f
这是电路图,有兴趣的朋友可以参考。; b5 s7 c9 T( I* j1 N
1 \" C7 i0 e- b8 K9 f; O! o
5 J- j% Q: p8 b
我信奉开源主义,十分痛恨把技术藏着掖着。好东西大家分享嘛!所以两个单片机的源代码大公开!5 z7 w" l, N  d
编译器:Keil 51。$ U% j" W2 h- H( M& u

$ U1 p3 ~( t' ~: n( t! s发射端:8 ]  z' W: ?8 `+ C# x4 S
  1. #include <INTRINS.H>
    2 F$ t5 f4 V. c; _1 H4 g! I( h: Y
  2. #include "STC15W.h"
    4 `8 a- Y( {& r) \  C; V1 ?" G

  3. # a$ Z+ n' D( }1 Y
  4. 4 M" f5 T8 m; F: R) z9 ~  l2 c& m
  5. /*! c! e% J$ W* F- ?  O# @, h
  6. --------------------------
    # ]8 ]- X* U/ Y- q& {
  7. |1 (OUT)        \__/   (INT1) 8|
    & F+ D, {- j4 T7 r9 P% o2 Z
  8. |                                                   |
    9 V5 ?4 M: A: R) G# B) R8 T
  9. |2 (VCC)                   (INT0) 7|: g% g4 l- n& L2 ]. w# R* X
  10. |                 STC15W204S                   |) Q/ G6 K6 S. C! ~6 g( G6 G2 g. a
  11. |3 (LED)                         (TXD) 6|2 A6 v) i  n, \8 M. }
  12. |                                                   |- P1 ?. F8 `: _
  13. |4 (GND)                         (RXD) 5|2 g7 v  X% D" o  J1 S# U. ]; n9 l' u
  14. --------------------------  g7 h4 L! O: H# G1 u  E

  15. 4 Z% l. l) l! X  M8 L
  16. LED ---|<|---[===]--- VCC1 R) U  r* @+ w; l7 V
  17.            Red          330
    - I2 Z4 r$ x' X  p/ t5 W
  18. 0 s( o& i5 F% n$ l0 O9 @
  19. Fosc = 6MHz7 p/ K8 m) w1 S- E  W7 @0 g
  20. */
    - a' v. W8 i: X! o

  21. 2 @5 ~) v0 B# n
  22. 0 i4 `# J& l( W" ~4 q- u
  23. // 矩形波输出脚3 T# D. I. t8 R) S9 ~" E' n
  24. sbit OUT = P5^4;
    * s" _5 ?/ U" ~$ i" i- p
  25. // 低压指示灯引脚3 O- E( S8 X; b6 z$ ]6 J/ g" F- Q
  26. sbit LED = P5^5;( C& M. Q7 j! S7 c6 ]5 G) J6 s

  27. 8 x) ]/ W% D7 V2 C  Y. _
  28. // 停机标志位
      L) v0 D1 L& u% H
  29. bit isReadyToHalt = 0;$ L  \; b+ @1 W& Z: L7 j

  30. " J$ s8 n! @$ V( U( t# v) D
  31. // 矩形波次数累计
    - T. d& i/ i9 h$ l( W. s
  32. static volatile unsigned char count = 0;" N* i; K- r" M: _$ [
  33. - o: D- k7 E2 g. T! e3 i8 p* f
  34.   D0 r+ M; B- b  X
  35. static void GPIO_Init(){7 ^6 h0 D+ M/ A9 ?
  36.         // P3口设置为准双向,默认靠内部弱上拉输出高电平
    % ]4 b. |. j# i+ o
  37.         P3M0 = 0;
    % f) S2 ?/ a3 R6 Z( d" [
  38.         P3M1 = 0;: T0 w4 W2 i2 i5 P: z. F! \( f
  39.         P3 = 0xFF;5 m7 C% c; D2 |5 l" N2 u
  40.         // P5口设置为准双向,默认靠内部弱上拉输出高电平
    7 Y* ?# T9 i" ~7 k
  41.         P5M0 = 0;
    ' G, S4 M3 z: T" C1 \' Q) J2 s
  42.         P5M1 = 0;
    6 X/ y6 `* v" k$ T5 `) Z6 t( ^) z
  43.         P5 = 0xFF;
    ) G7 C9 l  f& D1 Q5 [6 P
  44. }1 |2 m" X6 J& v+ `8 `+ ^

  45. + g$ \1 N$ G2 J1 \" P, ^. r
  46. static void Timer0_Init(){- _# L  R2 o  H3 T# Y* G8 A
  47.         // 16毫秒@6.000MHz9 g* U2 U6 ]" S- f( X1 n7 w
  48.         AUXR &= 0x7F;        // 定时器时钟12T模式- {2 h% u6 Q) t( H
  49.         TMOD &= 0xF0;        // 设置定时器模式5 r7 i, y  }# T6 h% a$ |
  50.         TL0 = 0xC0;                // 设置定时初值1 G5 Q; N  Z" Y- G; o. q: o
  51.         TH0 = 0xE0;                // 设置定时初值% C( e: R) e+ J( C
  52.         TF0 = 0;                // 清除TF0标志
    5 a5 G8 C8 U, Y9 D  U3 {5 ^' F
  53.         TR0 = 1;                // 定时器0开始计时; u/ ~1 ?  }' x! P( V
  54. }
    : o# e. c( g1 U* I, y) P3 @
  55. ' T; \' \" _3 z" U2 U& g2 C
  56. static void Interrupt_Init(){
    . A$ i" j. g5 z' H. Q# N
  57.         // INT0中断触发类型为下降沿触发
    5 a6 [  `8 _* h$ E+ k/ I
  58.         IT0 = 1;  U* p3 v2 A: d( W
  59.         // 允许INT0中断
    9 E4 a5 I9 e$ s9 X& Z/ g
  60.         EX0 = 1;
    9 X7 R: g; A8 n. R3 _
  61.         // INT1中断触发类型为下降沿触发
    4 ]( {6 u7 Z! v0 M
  62.         IT1 = 1;. r1 Z( }* g8 d0 w
  63.         // 允许INT1中断# Z! i8 s6 x+ y0 {* @% h
  64.         EX1 = 1;9 U3 F9 ?+ w/ w4 ^* ?
  65.         // 允许定时器0中断3 V& N5 k9 [0 i$ W
  66.         ET0 = 1;
    7 e" i$ }5 U( `% r& Y2 a+ J" a
  67.         // 允许全局中断
    ; P, O/ S1 {% Q0 O. ]' W2 y+ j
  68.         EA = 1;
    , O" S$ u8 V: B
  69. }
    9 f2 I5 X$ R1 ]% D) X
  70. 8 _$ e9 A/ w  y+ g3 S% T. z/ k  @
  71. static void INT0_Isr() interrupt 0{& ?3 D  W$ g5 o$ k2 p
  72.         // 矩形波次数累计归零
    , c- b' ?# {- {4 r
  73.         count = 0;
    % X: X! j0 K+ ]! R
  74.         // 重开定时器0中断2 q1 E) N$ U+ H% D0 ]7 @  d2 i
  75.         ET0 = 1;! b! \0 |0 ?; N4 [, Z3 k
  76. }
    % }, M2 }  y* d7 J
  77. 9 }1 T1 c5 I+ n7 }
  78. static void Timer0_Isr() interrupt 1{
    1 x7 }0 a( N( L1 P9 b+ g
  79.         // 输出矩形波) G5 t& d; F" m) h0 R9 ~/ Y  {6 R
  80.         OUT = ~OUT;' N  E/ y3 Z1 q' a
  81.         // 累计矩形波次数. H7 X' J4 E( }- W" `6 p7 j) _
  82.         count++;! Y% ^( i7 n2 w/ ^: Z0 j
  83.         // 超过250个矩形波,准备停机; [  p' `0 n+ T: F0 j: @
  84.         if(count > 250){' o8 z& _8 t# f% ^
  85.                 count = 0;- ]- R/ l/ o2 D) H3 ^. E, ]( V
  86.                 isReadyToHalt = 1;. P# S3 I$ ?& ?; p7 k
  87.         }8 X3 t) D" J) x. \
  88. }& a* l6 p; a+ f& y( i
  89.   h- r- D; N5 K- ?
  90. static void INT1_Isr() interrupt 2{
    0 b0 \. G$ T, W+ k1 E; N1 B
  91.         // 矩形波次数累计归零
    & V. B! P. V0 p% v1 n. w
  92.         count = 0;4 R# @/ W0 R( f$ J. k1 R: _9 l
  93.         // 重开定时器0中断
    2 C5 _: X+ |# c
  94.         ET0 = 1;
    * u4 y' j* c5 {) s! Y. A2 [
  95. }
    : d' E2 i) M5 b% I1 c0 l% g

  96. ; m! ]! g* N* o8 k' N9 D$ D

  97. ; Q1 D9 [9 Z5 U9 i
  98. void main(){
    * U1 t( l$ N; G; B. D% E% n
  99.         // 初始化P3和P5口
    7 K. c4 k1 B" n$ D( o
  100.         GPIO_Init();
    5 ~& b# l$ D3 `1 b# ]
  101.         // 初始化定时器0' e/ v% E; }6 l4 S
  102.         Timer0_Init();
    ! Q7 T, g" y* `5 \0 [# v) y" X
  103.         // 初始化中断% B7 V( {  \) W9 K$ a1 F/ b
  104.         Interrupt_Init();% f- b+ p9 p) C& L" a
  105.        
    + H0 m, c- n: X. p: _3 R# R
  106.         while(1){8 k0 `! r2 b' g3 k2 M6 T
  107.                 // 检测电量5 {* q$ B0 _. E$ V8 c3 ?
  108.                 if(PCON & (1 << 5)){
    4 C1 U' e9 ^; h5 e4 b/ d* |" k
  109.                         // 如果电量低,低压指示灯亮* l; d. o4 P9 j
  110.                         LED = 0;/ l7 W- e2 d' A3 h4 a* \
  111.                         // 清电量检测硬件标志位* g0 y1 A9 a! W: R
  112.                         PCON &= ~(1 << 5);
    9 ]6 T% |8 `5 F# E6 [* A: A
  113.                 }else{7 {% y( D( Q6 n; M& T
  114.                         // 电量正常,低压指示灯灭; g! s* m% I; V, f- g
  115.                         LED = 1;# P  S4 b( q" K7 r5 z  g& Y' m; J. d8 m
  116.                 }+ U# x1 t/ _) j; P  Z
  117. * s. B* f) k9 l) I" x
  118.                 // 检测到停机标志+ a3 l# V: c* N8 B5 |/ z
  119.                 if(isReadyToHalt == 1){
    # I" z* i# u- A: R2 I# ^! t; a
  120.                         // 暂时关闭定时器0中断
    + i. |: t2 O, O8 @
  121.                         ET0 = 0;
      b% p, I9 \2 l3 D- O2 C
  122.                         // 停机之前先把矩形波输出脚置低电平,以方便INT0和INT1唤醒CPU% F  l! y$ s4 v/ p1 T% W
  123.                         OUT = 0;9 _/ b" ~- h6 ]* C" F+ W8 E' m
  124.                         // 停机之前先把低压指示灯灭掉,以省电  R4 S* G+ f$ F- W- F! d+ M
  125.                         LED = 1;
    9 u$ k, j; Q8 I& w
  126.                         // 进入停机模式
    " `) b+ U' ]( E7 n. L' W
  127.                         PCON |= 0x02;8 n" J9 t( M& H" W4 ^: C* U
  128.                         _nop_();
    % n" [# L4 ]; c: R
  129.                         _nop_();' x* Z( P, x3 B
  130.                         _nop_();
    % T( E. m- Y/ Q$ M0 R
  131.                         _nop_();' J/ |$ l  Q/ o4 U! n3 P5 x, }
  132.                         // 唤醒,清标志位, n& G3 X" J7 |; P( O2 K) Q
  133.                         isReadyToHalt = 0;) e. v$ j) H' G4 t8 G! g# |7 g+ L$ n: o
  134.                         // 重开定时器0中断$ H9 B/ C% H* \9 m/ T( J
  135.                         ET0 = 1;
    # V$ d/ u' p! W
  136.                 }
    ) M4 k* T4 ?! t* l6 z
  137.         }
    ( u( N# Y# g  C1 p1 e
  138. }: i) h  t, c& j
复制代码
( a: |' d: c9 C1 v  e+ W
硬件参数配置:$ t% C$ ~9 u, u" d; O
8 A( x$ b1 ~# Y# S% K) @+ K. w4 E8 \

- D0 f! s2 D) p! l# x* B接收端:
, @5 I/ w4 j* _% B* r1 ~( d
  1. #include <INTRINS.H>
    , [& k' Z7 Y  @! J; y* O8 ]( J) Y1 i
  2. #include "STC15W.h". q7 a( s0 o: z. G

  3. 1 `1 H: ]6 H( A% U: q( A

  4. : l5 v, y9 y' Y; V' l
  5. /*: _) r1 `6 f& K2 H7 B2 R. \' Q" Z

  6. 1 p- S( S) h: O7 }' Z/ [1 l/ {
  7. *---------------------------*
    4 L$ `$ ?* L' Q2 K, }. ]7 u" {
  8. |1 (GPIO2)         \__/  (GPIO1)16|) T4 s5 s6 l& J5 m$ l
  9. |                                                        |
    / a# E+ f8 S) Z" r0 W3 {
  10. |2 (GPIO3)                   (GPIO0)15|
      H$ q2 K& v6 D; V( f" q& q; Q' l
  11. |                                                        |
    ' Z' S- G! v* V+ v, I, o
  12. |3 (GPIO4)                                  14|
    ' T0 M) x3 |% \# a: s* ?$ I
  13. |                                                        |
    4 [3 V! ?' c9 h/ [0 m$ ~7 U
  14. |4 (GPIO5)                        (DATA)13|
      y) ^  i7 U# `1 K( }$ {
  15. |                  STC15W204S                |
    5 O7 q: |1 b6 B/ W6 h# E
  16. |5 (GPIO6)                   (LATCH)12|2 K; e2 G/ A" e3 t6 D
  17. |                                                        |
    1 d* ^! y2 _9 U
  18. |6 (VCC)                         (CLK)11|3 `5 `! E, z4 |, I6 T
  19. |                                                          |1 t/ E0 u& f" H  z7 L( P
  20. |7 (GPIO7)                         (TXD)10|
    ( H: k: j6 ^/ y+ y
  21. |                                                        |+ M2 Z0 \' s% c1 t7 a
  22. |8 (GND)                         (RXD) 9|
    " g4 Y" g$ Q: O9 @7 `1 _- v) K
  23. *---------------------------*2 G0 M: C7 N& G6 m. `
  24. Fosc = 12MHz
    2 W0 T  U7 z( ]) [) `

  25. ! V( I) \+ u! |0 K% G: A
  26. P1.0 -> 上
    " U) c  V7 G1 s
  27. P1.1 -> 左
    1 y& L( s: E% \# @/ p
  28. P1.2 -> 下* S8 P9 \) a* [' p9 D
  29. P1.3 -> 右0 P9 i& a4 Q: l2 S* f" Y0 [
  30. P1.4 -> SEL
    : Y& j0 @2 C7 O2 i2 D* N: n* t
  31. P1.5 -> STA, O+ I0 g: n; p+ v% F: [- G/ N
  32. P5.4 -> B; |4 e1 s, j' J7 D6 d, X6 Y
  33. P5.5 -> A
    5 e! {: \! L6 W& I% O5 K" u

  34. 9 Q/ }  _0 b) @$ b0 X6 y- Q- b
  35. */
    $ S7 S0 Z  f- l0 b5 X5 ?9 V

  36.   q; }2 ]% o& j* c6 C4 O2 a( l
  37. ' a, i9 U( u) Q& w/ }  _7 b3 z- p
  38. sbit CLK        = P3^2;
    . I1 [3 A5 @: C) P* A" w  U
  39. sbit LATCH        = P3^3;1 k, s* j3 X: d2 O
  40. sbit DATA        = P3^6;
    9 o% j! T: `/ C7 U- U7 w2 E" @. O$ ~
  41. 9 C' K5 k6 k' k8 `" j
  42. bit isReady = 0;
    1 M, s. _& b6 C, I! O7 i+ E
  43. static unsigned char key = 0;1 O! ?" Q3 H" y( [  Z9 n
  44. static unsigned char buf = 0;        // 双缓冲。这个缓冲区保存从P1和P5组合而来的键值
    . ~) x7 ]; U0 O. J
  45. static unsigned char bufReady = 0;        // 双缓冲。这个缓冲区保存上面那个缓冲区的备份5 @4 X3 T( V2 N  i& G
  46. static const unsigned char data mask[] = {0x80, 0x40, 0x10, 0x20, 0x01, 0x04, 0x02, 0x08};        // A B SELECT START UP DOWN LEFT RIGHT。为提升速度,这个表放到RAM中
    ) K* r+ Y& X2 V. q" T& Y/ e0 |
  47. static unsigned char idx = 0;
      ~. ?) O0 G9 F0 c6 @

  48. ; S" L! B1 C, T* M

  49. & g; f. |. ^0 U% f) L1 W* `
  50. static void GPIO_Init(){+ }8 L! [+ I6 F9 S
  51.         // P1口和P5口用于接收并行信号,全部初始化为准双向,依靠内部弱上拉输出高电平
    ( Z7 \! {1 o: r3 i( |8 G* Z
  52.         P1M0 = 0;
    # W3 z: `( G) {% a
  53.         P1M1 = 0;4 g& Q3 E' `' m( N
  54.         P1= 0xFF;9 [& H: Q+ y3 ]( m/ y9 ?3 K
  55.         P5M0 = 0;) [  D! H. h: [3 {( a, z( f
  56.         P5M1 = 0;9 L6 R/ D& w% c( |0 R
  57.         P5= 0xFF;
    * X5 C" m+ U  E  D) T* ], P/ ^
  58.         // P3口初始化为准双向: K7 f+ Y2 m. E4 ]( P$ M. q+ Q
  59.         P3M0 = 0;
    % J0 `& X4 v. V/ ?! I" ?; J
  60.         P3M1 = 0;7 ~- b2 k% {$ N7 ?
  61.         P3 = 0xFF;
    - ^, f2 H% f5 I( T& h  S& u
  62. }8 w; |2 p0 ^: @' M% c; J
  63. ( P/ m9 E+ \) b
  64. static void Interrupt_Init(){: w* f7 m$ `/ i- o: D& l% _
  65.         // INT0中断(CLK)触发类型为上升沿+下降沿5 ~3 N: c' U" V3 @/ ]8 a5 ~
  66.         IT0 = 0;
    . P- u- _7 w/ o9 L
  67.         // 允许INT0中断
    4 U& O- t4 K9 o: q3 j
  68.         EX0 = 1;
    - p1 R2 f) k1 x" }% p
  69.         // INT1中断(LATCH)触发类型为上升沿+下降沿
    ; I3 ~0 {0 m3 }5 x; E3 D( m% B
  70.         IT1 = 0;8 o2 L* u7 ?( L& T% }0 H
  71.         // 允许INT1中断
    ( b" o' F; {' |' T! ^
  72.         EX1 = 1;* u2 l; n6 ^9 l0 @* a
  73.         // 开启全局中断
    9 q# \* ^" u/ d2 A8 ~# b) O; Z% P' q
  74.         EA = 1;& d! A2 ^* i7 O/ ]' u% h
  75. }! [6 p- L; f# A9 ?# c5 e
  76. ' O+ Q/ O2 w- H* e5 j: F4 c
  77. static void INT0_Isr() interrupt 0{9 D6 d* R! x/ S6 e% e! C5 E' f
  78.         // 只有已经成功锁存才允许CLK移位9 N3 \7 q. h& d. M' ?* Q; T
  79.         if(isReady == 0)
    , l8 u. u, t/ }8 M* h
  80.                 return;  W/ S% [6 r  Q' e
  81.         // 读当前引脚电平,如果是低电平则说明是下降沿,此时直接忽略该中断
    0 L4 N( X1 J' G
  82.         if(CLK == 0)6 r% y; r2 G$ m$ H
  83.                 return;6 L2 s3 d  A! S
  84.         // CLK上升沿到来的时候,取锁存值的下一位输出
    ! r$ Q$ _: m" C' d' D* T
  85.         idx++;$ U: x. O) O; v! @
  86.         DATA = key & mask[idx];7 [, N" f! o' b# o  C1 x
  87.         // 如果已经完成7次移位,则一轮读取完成7 |5 `: Y1 `, V4 C6 T; |
  88.         if(idx >= 7)
    ; A2 [) X. Q( P& E; t
  89.                 isReady = 0;
    * ]% y, t0 _3 c- H2 C
  90. }
    ) r% t) r3 X8 g1 N. P

  91. 9 a( g; p+ b+ {# W/ i
  92. static void INT1_Isr() interrupt 2{
    ) K2 W" B- u8 a) Y6 B- i- a* d
  93.         // 读当前引脚电平,如果是低电平则说明是下降沿,此时直接忽略该中断6 Q4 Z' d! i" I  A4 U7 W+ n
  94.         if(LATCH == 0)
    6 e+ }# U& }9 R& E9 z7 a$ f
  95.                 return;8 J* z; g5 `; k* t5 K9 r
  96.         // 当LATCH上升沿到来的时候,锁存所有按键状态,同时把键值A输出到DATA4 t2 g, L% k! ~
  97.         key = bufReady;& v2 n1 d4 o5 B) Z) ~
  98.         DATA = key & 0x80;//mask[0];        // 为了加速运算,直接取表中的值而不是读表
    $ c8 u- u  j( q2 W- ~
  99.         idx = 0;
    3 Y( ]1 l" D* b4 }
  100.         // 允许CLK进行移位) c: X* D+ V5 L% t3 P" V" {! u, B& e
  101.         isReady = 1;
    $ L$ K. T9 G( N' t9 K
  102. }- O1 v1 H' G* Y+ }3 u

  103. : [( c( c. ?7 i
  104. void main(){
    9 j( y0 R5 F: o
  105.         GPIO_Init();2 V* }' l) p4 A! T: n" b
  106.         Interrupt_Init();
    0 O4 |- C+ ^% p0 w' |
  107.        
    * h( j4 |+ m8 l
  108.         while(1){3 E" |2 x  {1 B3 |# T  ]9 C
  109.                 //PCON |= 0x01;        // 进入省电模式
    1 O2 h7 x! Z/ C: H, c2 O/ A' p. A
  110.                 //_nop_();
    + P5 G; v; }- E7 w2 ]. K5 e
  111.                 //_nop_();
    ) J* k7 {$ {+ Z4 R7 c4 u8 m" ^6 }: V  b
  112.                 //_nop_();
    # r, C$ `8 v3 M$ I2 b
  113.                 //_nop_();! c! Q; ^0 Q. n
  114.                 buf = ~((P1 & 0x3F) | ((P5 << 2) & 0xC0));1 J7 v0 J" Z- d$ Y% K/ V# E
  115.                 bufReady = buf;
    * @0 o: D5 j* A, M/ _
  116.         }
    * j8 _1 |% ?& w: b  k
  117. }
    4 ^" J# W% I' x& F" _' p4 V
复制代码

4 F8 Z; W) ?; z硬件参数配置无特殊要求,晶振频率选择12M即可。
+ n! J  U( g. n  k
$ V2 u/ `8 B3 R  r; _$ L; ]+ f这是编译好的固件。

本帖子中包含更多资源

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

×

评分

参与人数 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
! C- S& h; U; s: V& e: d不错的设计,想问一下楼主,FC的15针公头怎么解决?普通的公头太短了,插不进去FC的扩展接口。 ...

8 ?6 z4 p9 `% K, C% x坛友的改造方案
回复

使用道具 举报

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

使用道具 举报

发表于 2019-5-25 12:07:18 | 显示全部楼层
精彩,楼主动手强,也写得很详细。- D+ ?3 ^. b. l9 _
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" f2 @' |: e8 z) @* W/ K" A
精彩,楼主动手强,也写得很详细。' x, |% y$ z- ]. {9 `
2.4G方案是目前无线的最低延迟吗?
$ S, b2 u4 K9 ^6 o
我没用过其他无线手柄,所以实在不知道我自己做的这个手柄到底是不是最低延迟。
! M2 [' x* x) ]& Q不过根据网上的说法,延迟高低主要是由通信协议的复杂程度,以及数据传输速率决定的。这个模块虽然是2.4G无线模块,但由于协议很简单,所以延迟比较低。
5 K+ r# x  d) o我用这个手柄玩一些ACT游戏,比如超级马里奥、忍者龙剑传、热血系列,完全感觉不到延迟,和游戏机自带的手柄没有任何区别。唯一的区别就是这个手柄是用火花山寨手柄改造的,外壳是垃圾回收塑料,粗糙+脆弱,导电橡胶弹性不佳,手感不是一般的差。
2 V' G8 x5 F" s3 ]6 \我手里还有十几张板子,等我有空了我再做一套,到时候买一个好一点的手柄改造。
回复

使用道具 举报

 楼主| 发表于 2019-5-29 16:56:14 | 显示全部楼层
ppad 发表于 2019-5-28 17:27+ p# z7 K3 b6 X* \! Z" L
给技术帝赞一个,有半成品发布吗,自己焊接改造就可以,编程实在不会啊 ...
+ w+ c, j& {! P
很可惜,我手里没有多余的单片机了,LDO也找不到了,锂电池以及充电模块更是没有了。反正就是该用到的元件基本都没了,所以没法发布半成品。
8 H+ u) X% k, J: t8 [两个板子倒是有十几张剩余。; A' h' v* z6 W1 |4 u1 n2 {
你要是有USB转TTL串口板,完全可以自己买这两种单片机,然后我给你编译好的固件,你自己用串口板下载到单片机里面就行了。两个2.4G无线模块也得通过串口板用AT命令设置参数,不过好在我在设计电路的时候就已经预留好了串口,可以直接在线下载和在线设置参数。总的来说并不麻烦。
回复

使用道具 举报

 楼主| 发表于 2019-5-29 17:00:34 | 显示全部楼层
孙大师 发表于 2019-5-28 18:556 @9 A: X( Q4 z- u, x* a$ \. }
非常好,楼主是技术帝,到目前我都还没开发fc的无线套件,等空了,开发一套套件,等玩家自己组装。 ...

: J% |: G1 ?7 Q能得到孙大师的赞誉,不胜荣幸!
% v, \" L& \3 y$ y不如开发一个多功能手柄,比如用SFC手柄改造,L/R键配合其他组合键可以用来切换2P~4P、调节连发速度、软重启等各种功能。接收端插到15PIN扩展口。
回复

使用道具 举报

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

本版积分规则

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

GMT+8, 2026-8-5 16:20 , Processed in 0.117627 second(s), 15 queries .

Powered by Discuz! X3.5

© 2001-2025 Discuz! Team.

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