找回密码
 注册

QQ登录

只需一步,快速开始

查看: 24897|回复: 32

自制FC无线手柄

  [复制链接]
发表于 2019-5-22 14:16:45 | 显示全部楼层 |阅读模式
本帖最后由 雷精灵2046 于 2019-6-14 09:28 编辑 * b6 T/ _0 {1 ~6 }0 O: @

3 A+ P& ^: A6 N! f' V( N) H没有用复杂的分立元件搭建发射接收电路,直接用的现成的2.4G无线模块jdy-40。- f6 @0 N# V: X2 |( o' d
2 u  Q7 r0 `0 Z" @, ^. f
) ?6 Q% d8 m' N9 ~5 K* B$ H* r
发射端靠3.7V锂电池供电,用了一片SOP8封装的STC单片机,负责产生连发脉冲,同时负责检测电池电量,电压低于3V左右的时候触发低压中断,低压指示LED就会亮起来告知该充电了。平时发射模块和单片机均处于睡眠状态,有按键按下才会唤醒,从而实现省电。实测睡眠状态下整机电流约1~2uA。板子洗了一下稍微干净了一点。因为对于微功耗设备来说,焊接残余的助焊剂可能会增加漏电流。7 A5 l1 c: `" p% J9 m

, }9 C  @3 M9 g1 [" C7 S0 a买了一个火花的FC山寨手柄,去掉里面的牛屎板子,并修正一下塑料挡板,把锂电池和充电模块装进去。
  n7 O4 ]! m" n: E为了减少体积,充电模块裁剪得十分小,并且更换了充电电阻使之适应这个小小的锂电池。这么小容量的电池,也不需要多么大的充电电流是吧?
/ O- [! n* W9 @9 _然后统统用热熔胶粘上。充电电流比较小,所以发热很少,不会熔化热熔胶。% `) Q( |; w, O+ O

8 n7 E  b' P" \, Q
" x- W4 @1 y6 j3 X. D6 s: R# l7 w( F
最后把按键、导电橡胶和电路板装上去。
8 ]3 o$ B1 [: \- M' W& q精心裁剪了电路板,正好扣上,不会阻碍其他元件,也不会影响后盖和拧螺丝。7 o, m. }  B" w5 i2 |: f
% n3 y7 x7 b1 `* S2 I4 u; D

- j4 J0 g7 N$ ]0 m  k% g完工!4 s+ g5 s9 Z3 O# y0 a9 A

- d/ l! i7 S6 n  e. R
/ [) P& Z0 L, n0 S# I这是充电的MicroUSB插座。旁边的小孔用于透出低压报警LED的光线。. P7 O* p" ~8 p* k5 R" W* B5 x

( \8 g" U: n+ o9 J" y/ n0 W
4 d: e/ N4 l4 R$ J$ [接收端用一片DIP16封装的STC单片机模拟CD4021。为啥要用单片机模拟而不是直接用CD4021?因为jdy-40模块接收端在有按键按下的时候输出高电平,无按键按下输出低电平,和普通手柄正好相反。当然我也可以用两片74HC00或者74HC04之类的逻辑门进行反相,但那就增加了芯片的数量。对于FC手柄这种工作频率并不高的设备来说,STC单片机完全可以胜任模拟工作。4 n* H4 \/ W) v( [% [+ W
. h( W4 d8 \" g
- I# x7 a; l- H% x5 {# k
, f' z5 ^- z$ v
电路设计有点小小的错误,所以有几根飞线。原本设计使用低压差LDO是XC6206,结果在做这个接收模块的时候,买的LDO居然找不到了!无奈只好用了AMS1117。幸好对于接收模块来说是5V降到3.3V,1117可以胜任。要是发射端手柄的话,3.7V降到3.3V,那就非得用6206不可了。
3 w" ]7 y. w* |0 I, k7 V$ ^4 R4 B+ z. V/ M
实测十分灵敏,延迟极小几乎感觉不出来。可惜这山寨手柄的手感并不佳,尤其是方向键,软塌塌的。看来我得买个剪线手柄改装。
/ `6 S( u7 c- E, I, U( G- h9 T2 o; ~0 v3 W
这是电路图,有兴趣的朋友可以参考。
7 d4 a9 A  q- b% p/ _9 Z6 I; ]/ f2 B3 y6 w$ h- X

3 c" R* t; A1 v5 O/ n$ v' j我信奉开源主义,十分痛恨把技术藏着掖着。好东西大家分享嘛!所以两个单片机的源代码大公开!
; I! e- g4 J) X" Y3 E# ~$ c编译器:Keil 51。
0 K0 d/ i; w8 d) ]2 Y) \
/ |  u+ D- }7 _* {9 z& S3 {+ e发射端:: Z! a  ~4 E3 k6 H; _
  1. #include <INTRINS.H>
    ; E* k0 a' V9 |6 g2 P
  2. #include "STC15W.h"9 G" B6 b& P+ r
  3. 9 c6 @; O) y2 J- M) ~' l1 X

  4. ! U2 X$ w( i1 l' O, L
  5. /*
    9 x/ A5 \0 ]: x% N1 O# F5 c
  6. --------------------------
    " i% W' I) x! g6 ?% `4 g- [
  7. |1 (OUT)        \__/   (INT1) 8|* W* R4 z1 E4 B& n& V6 L6 [* p: Y
  8. |                                                   |
    + T0 ~" P. `- a" j
  9. |2 (VCC)                   (INT0) 7|
    6 }, R* W3 T3 h8 B
  10. |                 STC15W204S                   |
    6 q& {) p7 C8 E' ]% `; q
  11. |3 (LED)                         (TXD) 6|
    $ m  N* f' t% q5 V
  12. |                                                   |
    ' d+ m6 N5 b+ b# X4 k6 v
  13. |4 (GND)                         (RXD) 5|
    , M/ n  G9 O) W  y
  14. --------------------------
    & {; ^. W: P+ ^3 B  v

  15. ; f$ G0 f2 V# W9 C+ {  ~3 k
  16. LED ---|<|---[===]--- VCC/ G! ~( R. d; `8 N7 V% T6 ^! }
  17.            Red          330  s( z  M* R/ [# B/ P" p5 I
  18. ' S1 D5 ]6 ?" ~4 |
  19. Fosc = 6MHz) ?) A, k6 @# c9 T6 ~
  20. */
    ' f( e' |. o) P* X
  21. ; P& ]7 ^( o, m6 g0 f- F4 v6 j
  22. ! o& Z/ x# `* [/ h# z
  23. // 矩形波输出脚
    3 M" _; t8 t$ C4 B  Z4 J- w8 ^
  24. sbit OUT = P5^4;; R/ t5 A, c4 b
  25. // 低压指示灯引脚# M+ X( l3 P! ~, T5 [
  26. sbit LED = P5^5;
    % j. ^7 a. j  H, h% s9 s
  27. " h. o  G( l, E( ?$ j$ I: q& R
  28. // 停机标志位
    5 [  ?) `/ |( P2 r
  29. bit isReadyToHalt = 0;1 }. H% q/ |, _

  30. ; r: L# q+ B; M* m
  31. // 矩形波次数累计
    4 L# Z3 a1 Q2 b
  32. static volatile unsigned char count = 0;
    # i: B" p9 [' F
  33. 0 Z/ g7 M  G; _4 B# k1 N7 U4 Y! B: E

  34. 5 r( M  w  s$ r# j/ U7 H  A' S0 v
  35. static void GPIO_Init(){" o  Y/ ^0 S; Y: G4 X
  36.         // P3口设置为准双向,默认靠内部弱上拉输出高电平
    9 Q; v9 V1 j( I3 f; I
  37.         P3M0 = 0;/ N: ]0 X1 H0 a( _6 H
  38.         P3M1 = 0;
    3 X( _, g, Q- o$ L& b2 q4 {
  39.         P3 = 0xFF;
    ; d7 X, ?# B$ A
  40.         // P5口设置为准双向,默认靠内部弱上拉输出高电平
    / Y9 w1 E4 x) q. p1 k' W$ v" Q
  41.         P5M0 = 0;
    2 t& h9 N: A. W
  42.         P5M1 = 0;
    * V6 \& C, F9 J: D
  43.         P5 = 0xFF;' F. B4 i/ G% R5 z( w' |
  44. }* ~; `. G8 ]7 y* P+ l: T

  45. . c3 W% x- q! k( s8 K2 E. c( _
  46. static void Timer0_Init(){
    3 W/ F+ x4 ]) ?4 Z" V
  47.         // 16毫秒@6.000MHz2 _7 t" x' m5 z+ D
  48.         AUXR &= 0x7F;        // 定时器时钟12T模式
    ) @4 |5 K% n$ \; U
  49.         TMOD &= 0xF0;        // 设置定时器模式
    3 B& q# e6 v# [$ f6 E$ J9 X
  50.         TL0 = 0xC0;                // 设置定时初值
    : f, r+ j7 ?# O( q. R7 X1 C7 Z
  51.         TH0 = 0xE0;                // 设置定时初值) A  Y( i, T  f* a( q
  52.         TF0 = 0;                // 清除TF0标志0 z8 H1 L+ V- _' l- H: B& ^7 _
  53.         TR0 = 1;                // 定时器0开始计时# m( S( a# @* [( _. b+ ]- q. @
  54. }! L2 D6 N/ }7 J$ N/ T
  55. . Q& v1 e9 l  t7 C! z
  56. static void Interrupt_Init(){4 [' R9 Q- ^, ]9 l( R
  57.         // INT0中断触发类型为下降沿触发* U3 n" S4 u. D: I& w5 J% ~  X# [
  58.         IT0 = 1;( r& [9 H2 T1 {5 n6 Q4 W8 q2 p
  59.         // 允许INT0中断
    " J  D3 ]1 v2 S3 Q& G  d
  60.         EX0 = 1;3 K7 ]2 T/ e# e0 F; U% S; Q
  61.         // INT1中断触发类型为下降沿触发
    / F- }$ O  E/ y% K& f
  62.         IT1 = 1;, z9 T9 S( C( E# w. r: K$ k
  63.         // 允许INT1中断
    # J3 d- _1 b3 p4 N( G0 P( x, X4 p
  64.         EX1 = 1;% i9 h- k' j9 o4 ], \& [0 Q7 V
  65.         // 允许定时器0中断
    / }/ f6 c, k2 H# {5 p& U' y
  66.         ET0 = 1;& t4 l& {+ H! p
  67.         // 允许全局中断- A7 O; Q0 T* R( v+ N( Z
  68.         EA = 1;
    / n4 z! i1 `1 Y5 S# y3 S4 b
  69. }5 U+ b! k8 Y8 ^
  70. 6 l" G) |0 ^/ ^! T
  71. static void INT0_Isr() interrupt 0{9 M6 d3 w/ _8 Q6 P4 p7 h
  72.         // 矩形波次数累计归零6 c! M7 L- E( X% {$ C! |; n
  73.         count = 0;
    * w. V8 b) k0 P/ L: H5 `7 f
  74.         // 重开定时器0中断8 |  y6 [  e/ }) x4 d
  75.         ET0 = 1;
    * q, j# _) E; T# H
  76. }3 O( A5 i1 v' d7 b+ d( N, q# d* J

  77. . Z- e( r- f; f4 n  ]: m
  78. static void Timer0_Isr() interrupt 1{. P: }( D+ o& r& I2 R8 t/ [9 C) s
  79.         // 输出矩形波
    + r, v: H- t5 P8 E* J! |
  80.         OUT = ~OUT;. S) f, f: h; d% e3 o, k9 _% ]7 p
  81.         // 累计矩形波次数
    8 W2 ^% G& w3 W7 O8 y" L5 m0 g
  82.         count++;. F, z8 m8 ^- [6 s$ w) E
  83.         // 超过250个矩形波,准备停机
    : f4 s! X5 c8 K$ U* Q
  84.         if(count > 250){& g2 j0 r; Y( o/ i3 C0 h
  85.                 count = 0;& z/ n3 v! g8 S$ |/ F- y) b
  86.                 isReadyToHalt = 1;
    + A6 N' [% h9 }: S# U# @
  87.         }, f/ |6 H7 E$ c/ l2 k+ |
  88. }5 R7 Q+ v8 x) [9 V# H" s0 ]

  89. " H8 F0 d+ X# z, d
  90. static void INT1_Isr() interrupt 2{  j: e9 C7 Z, H
  91.         // 矩形波次数累计归零
    5 P( t" }$ P0 l8 `2 ]
  92.         count = 0;
    1 E7 d0 p) M, F# H: d) L, V0 x' g
  93.         // 重开定时器0中断1 q: X" Z# t5 ^+ N
  94.         ET0 = 1;# n. E* I( ]* D9 B  p' Z
  95. }; B6 F9 X0 y7 y2 C1 }- s3 T! G
  96. , H7 e; l; g! B- Y, t8 ?
  97. $ Z/ @8 _' [$ \6 v1 ]$ S. l
  98. void main(){
    2 `% A! q! P1 Z- a: a4 N3 r3 n- c
  99.         // 初始化P3和P5口
    8 v1 c& t/ @0 h0 E  b
  100.         GPIO_Init();, @$ u) C" @6 Z9 f9 x
  101.         // 初始化定时器0" h$ Y, n3 f( S+ {3 b
  102.         Timer0_Init();
    2 z! t: k, U! L; }) e
  103.         // 初始化中断$ t4 B" s( I+ H5 O4 {
  104.         Interrupt_Init();' i1 \- u' f3 i
  105.         ; u  C7 e1 O- r' ~8 T6 J$ M- F3 [
  106.         while(1){6 S+ R& N( W1 E5 M6 c" t) [! J
  107.                 // 检测电量. x, a5 i$ b% k& d
  108.                 if(PCON & (1 << 5)){8 q% D( @% D/ D- y; n& x
  109.                         // 如果电量低,低压指示灯亮
    : e0 i, k$ a8 M# d7 o/ T
  110.                         LED = 0;
    ! i. j8 W. ?: U1 }" K
  111.                         // 清电量检测硬件标志位! s: c7 s! F3 N" v
  112.                         PCON &= ~(1 << 5);
    , M$ o7 [& u% C$ f$ j% q- r# G
  113.                 }else{
    % g& O. Z8 K4 T* r% ?
  114.                         // 电量正常,低压指示灯灭
      `4 l5 b# M3 z: l# g$ w7 D
  115.                         LED = 1;# t# u- T0 F, P1 H  `4 q" r
  116.                 }
    9 ]( y. l, ]/ [1 [6 s0 ~) T

  117. 6 w( n; X2 |) O5 x8 X
  118.                 // 检测到停机标志: ~; L% d, U# s' P' |, m
  119.                 if(isReadyToHalt == 1){
    1 a' t, j* q8 F. D; Z$ [2 u
  120.                         // 暂时关闭定时器0中断
    ! e/ @1 ~+ w* g) C' q
  121.                         ET0 = 0;
    2 m( m2 y; b+ S
  122.                         // 停机之前先把矩形波输出脚置低电平,以方便INT0和INT1唤醒CPU' q* A: Q7 H$ C2 k, |0 g
  123.                         OUT = 0;
    5 R, Q( e0 n( e$ W" a+ l" s9 a
  124.                         // 停机之前先把低压指示灯灭掉,以省电$ d8 R) y0 Q8 q% r+ _& Y
  125.                         LED = 1;
    0 u) p; S3 x5 l: A+ ]" m/ k+ H
  126.                         // 进入停机模式# v  Z- d4 n  ^" [# g5 Q
  127.                         PCON |= 0x02;
    $ h' x/ B5 V- I4 ]1 a( f- S
  128.                         _nop_();
    ( o# n; c0 K. F  F5 b
  129.                         _nop_();, n9 c7 S4 C7 E# s# ^8 ]3 Q
  130.                         _nop_();
    , R: |3 c- T3 M  ]* v  B/ U9 ]
  131.                         _nop_();7 A. T: x+ E, H
  132.                         // 唤醒,清标志位
    ! l3 F; d# l3 J0 P+ D; ^+ z
  133.                         isReadyToHalt = 0;$ Q! a; v9 J! j) Y" a9 L( t
  134.                         // 重开定时器0中断
    8 z' f7 l4 n, F8 Y9 v$ N5 I2 B
  135.                         ET0 = 1;
    6 H. y9 X' q" X/ [& A% Z
  136.                 }) v( {- x2 O# p
  137.         }! U/ ^& o+ E* A, W" B3 n/ n
  138. }- `- h8 g0 x" ?. x& U
复制代码
' I9 b5 i0 @/ ?  ^0 h4 ~/ P& {
硬件参数配置:
* R1 E" q- ?2 X: W# C( _; H2 }1 e* B7 w. J

9 k4 |% E4 C8 Y接收端:
* e) D$ C+ h1 p$ x4 `. N
  1. #include <INTRINS.H>& I6 N3 B4 U; `9 e. n
  2. #include "STC15W.h": N2 U8 r7 P4 M( N

  3. 4 g1 \! H6 G3 p+ d! ^

  4. ) L+ e. c. @+ ?* }* \; z7 D+ U
  5. /*. a- R; Z+ N8 L9 b: p2 I2 I

  6. 9 U3 e9 x2 O" y7 [3 H: B
  7. *---------------------------*6 u, F0 b) j+ ]# b) Y: r9 z! t
  8. |1 (GPIO2)         \__/  (GPIO1)16|
    - }- H+ W7 N& `9 Q
  9. |                                                        |
    8 Q# ^5 E: {8 j* Z
  10. |2 (GPIO3)                   (GPIO0)15|
      m2 o+ \6 F6 s' J
  11. |                                                        |
    / a$ F5 Y! f7 h: D6 Q7 H
  12. |3 (GPIO4)                                  14|. E$ [2 f  G( [& S  o+ J
  13. |                                                        |% U' i7 j0 ?4 J
  14. |4 (GPIO5)                        (DATA)13|6 z+ P" O* c" M0 O
  15. |                  STC15W204S                |, k0 ^. _) A" U2 ]* W# H8 F0 i+ J
  16. |5 (GPIO6)                   (LATCH)12|
    + k) Z" d# a! ?( A
  17. |                                                        |
    & [* \% {) O: ^% o* `5 d
  18. |6 (VCC)                         (CLK)11|" A/ O/ p& Y" {' Y; {- {6 R
  19. |                                                          |3 J! w! F6 r4 w- D1 g# P  b
  20. |7 (GPIO7)                         (TXD)10|
    ) T4 o. p) i" ^" f" p8 n0 N
  21. |                                                        |
    * O/ a- T) |, t6 B  F. t* R6 N
  22. |8 (GND)                         (RXD) 9|
    " Z4 ?& ?5 j/ X
  23. *---------------------------*; L- C7 ^7 ~( c+ }
  24. Fosc = 12MHz
      ^4 F* I9 U: ^; I
  25. 4 s" v' l/ j9 r, t' z' T2 r
  26. P1.0 -> 上% ^- D% d7 C9 d! a) m3 ?
  27. P1.1 -> 左% _1 A; r( i4 H! H' C) ^
  28. P1.2 -> 下
    ' D6 B. I+ f7 z: }, Z8 g- v) A
  29. P1.3 -> 右
    , P8 ~& q9 w% W1 h8 @
  30. P1.4 -> SEL5 N9 t$ y2 {5 E
  31. P1.5 -> STA7 R2 n1 d! m6 |/ h+ H. |) |
  32. P5.4 -> B
    5 I) M& w+ p/ ~* ?
  33. P5.5 -> A: t4 [$ C5 ^0 e3 N- ^
  34. . e2 @4 ~! h; ^- |
  35. */
    9 O/ N+ S/ V4 O2 i
  36. 5 b6 w3 r9 ~6 X) I
  37.   F1 \* X7 n8 w4 b
  38. sbit CLK        = P3^2;
    ' U6 q7 l: q3 F# f! m
  39. sbit LATCH        = P3^3;, y: k/ K% {* b4 G# y# ?
  40. sbit DATA        = P3^6;: U1 C! P! Y. _9 U
  41. / P0 x3 f. N0 j- W" k% L6 j
  42. bit isReady = 0;
    , ^8 y* U2 H. W! R( |
  43. static unsigned char key = 0;" g, \  W4 N$ E& K  R
  44. static unsigned char buf = 0;        // 双缓冲。这个缓冲区保存从P1和P5组合而来的键值- Y3 z" ~4 N* |5 R3 B
  45. static unsigned char bufReady = 0;        // 双缓冲。这个缓冲区保存上面那个缓冲区的备份9 Z: v1 ~) ]/ B( @: y% q% 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中
    $ `! e$ `! v3 I5 e: T/ x5 c0 M# r
  47. static unsigned char idx = 0;9 J7 r$ a6 \# w' c: }

  48. 7 J9 N" Y& H- I' X& O7 G

  49. 3 D- h- @8 k6 L  \. V+ q
  50. static void GPIO_Init(){4 `% M3 N( o$ w( H# K- `
  51.         // P1口和P5口用于接收并行信号,全部初始化为准双向,依靠内部弱上拉输出高电平
    6 y2 t7 [  ]) o. f" B! K* Y. z
  52.         P1M0 = 0;
    % ]/ }) ~8 [8 Z6 ]
  53.         P1M1 = 0;2 M* e& u& h2 B: y4 S  h- T
  54.         P1= 0xFF;% L6 k, J5 h+ d/ ~0 X" Q9 J5 M
  55.         P5M0 = 0;
    : K  M& l* k% G
  56.         P5M1 = 0;1 o$ W$ L/ m: E4 A" F4 |7 b. m
  57.         P5= 0xFF;8 E2 c- m1 V3 P# Z+ R9 P! a
  58.         // P3口初始化为准双向7 V  B( Y+ Y  R4 V1 c: i
  59.         P3M0 = 0;
    $ t& \0 ~4 r0 S, W4 b  ]
  60.         P3M1 = 0;" r3 P" M$ s/ D' X3 }# V2 l
  61.         P3 = 0xFF;$ t  E+ _, r0 R: T4 z9 z
  62. }
    " I( {8 A* k3 V

  63. ' T$ C1 F) N6 T' r9 x% a7 w
  64. static void Interrupt_Init(){) K9 Q9 a1 s. C2 m% C6 [0 Z4 n
  65.         // INT0中断(CLK)触发类型为上升沿+下降沿- k6 w- }# b. y: e$ V& m) Y
  66.         IT0 = 0;$ M7 T8 J9 P2 ^% u7 S6 b
  67.         // 允许INT0中断9 ?/ i3 C2 W& @5 X
  68.         EX0 = 1;
    ( H$ V( l& Z( T4 Q# g! T3 B
  69.         // INT1中断(LATCH)触发类型为上升沿+下降沿2 e' x9 U& p$ q& P6 l/ P
  70.         IT1 = 0;
    # v: D9 Z7 @* t# D. l0 r3 k0 j: F
  71.         // 允许INT1中断
    2 K) X/ j% X' E5 {& D
  72.         EX1 = 1;( c! e8 {3 T. B# J
  73.         // 开启全局中断3 A: `$ x, ~0 L$ P
  74.         EA = 1;
    5 w- e  X- x% A9 d2 N0 p+ Q1 b
  75. }
    + _6 o; V) F$ C' r; V6 I5 a

  76. % ~  R( s/ M; t0 R, o9 m4 S
  77. static void INT0_Isr() interrupt 0{0 R9 r8 I- o( q/ s$ _2 {4 q
  78.         // 只有已经成功锁存才允许CLK移位' h- Y' q6 M7 o% e) h
  79.         if(isReady == 0), \2 k! r. [9 M) C; s
  80.                 return;
    , P% m5 R4 C1 q2 i9 A* Y- b& m/ k
  81.         // 读当前引脚电平,如果是低电平则说明是下降沿,此时直接忽略该中断
    ) I% O0 `; _; y. ?+ {; a
  82.         if(CLK == 0)
    " C2 y, R; m6 [" b$ S
  83.                 return;
    8 O4 W5 a6 X& M; H4 b7 d& F  l# J2 X3 X
  84.         // CLK上升沿到来的时候,取锁存值的下一位输出( w7 X+ f# E* P) h$ y6 @' `9 |
  85.         idx++;
    7 c" E" e; e% x& c
  86.         DATA = key & mask[idx];
    ( `2 u: X3 i" {/ i- Y
  87.         // 如果已经完成7次移位,则一轮读取完成
    * e3 F0 [7 \: {1 j. G+ i9 b0 R- }
  88.         if(idx >= 7)) E9 Q. b, `; O$ U
  89.                 isReady = 0;' F& T$ u8 X' Y5 T- n
  90. }5 K( ]2 G$ D# r* d+ X
  91. 7 m& D- w3 H: ~" ^3 J$ [
  92. static void INT1_Isr() interrupt 2{
    5 ]4 V. k( X+ N8 B* W
  93.         // 读当前引脚电平,如果是低电平则说明是下降沿,此时直接忽略该中断
    6 e& @4 I, x6 J* v
  94.         if(LATCH == 0)% B2 L7 D0 b$ y( ~- k  U9 ~! V: ?! I' e
  95.                 return;; e0 U: M5 R7 R; s$ `; j! }7 L
  96.         // 当LATCH上升沿到来的时候,锁存所有按键状态,同时把键值A输出到DATA
    . a$ N0 i& J/ T4 ~8 t8 \
  97.         key = bufReady;
    9 \+ D3 j7 u$ v2 w5 i# U
  98.         DATA = key & 0x80;//mask[0];        // 为了加速运算,直接取表中的值而不是读表
    " o  ?/ A7 B) _& q+ i" @
  99.         idx = 0;
    - O( I' {0 W5 y
  100.         // 允许CLK进行移位/ k* o1 z& t- Y- n( ]
  101.         isReady = 1;
    . \! y! B! S5 g8 O6 [
  102. }* n/ T4 y. k0 n' Y; ?3 L7 s
  103. + ]0 Q7 M/ J. }
  104. void main(){; g" m" y5 q4 R
  105.         GPIO_Init();) _5 N- c5 b" i* q
  106.         Interrupt_Init();0 G+ [, K3 m: d) Z
  107.         + c* r2 S6 D$ p
  108.         while(1){
    & J$ T; Y* D$ W, B, C
  109.                 //PCON |= 0x01;        // 进入省电模式, ]! F6 `. f, n
  110.                 //_nop_();+ x/ f. k: y  f+ ]4 l" U
  111.                 //_nop_();4 g' p9 V* ~3 ^! [+ e: ^
  112.                 //_nop_();
    . H8 P! d. W0 B2 _0 c8 m# o
  113.                 //_nop_();
    # o, ~8 l2 e" p1 ~6 ~* E
  114.                 buf = ~((P1 & 0x3F) | ((P5 << 2) & 0xC0));+ G7 R4 Z" A! {3 F4 [, x% ]
  115.                 bufReady = buf;
    ! P8 f+ w* u0 h. z4 t- p
  116.         }6 N) C5 _3 I; v+ _' F6 E, H3 f- w- d
  117. }
    5 ~) y* g! h+ H+ X. E2 {' \) W: V
复制代码

6 j. D) ?- q7 Q7 x+ {, t硬件参数配置无特殊要求,晶振频率选择12M即可。
( r- ^8 v& D6 {7 i2 k
  z0 V/ P; ~0 L7 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
3 Y% a  L& N0 A; u不错的设计,想问一下楼主,FC的15针公头怎么解决?普通的公头太短了,插不进去FC的扩展接口。 ...
" e/ M9 a) j% @" y+ X" U6 k: j
坛友的改造方案
回复

使用道具 举报

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

使用道具 举报

发表于 2019-5-25 12:07:18 | 显示全部楼层
精彩,楼主动手强,也写得很详细。/ Q+ {/ _5 y8 f& \
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
! F# f& U( A5 s) O+ S精彩,楼主动手强,也写得很详细。! J$ S: \% z8 u4 N: @0 k% x; `: Q
2.4G方案是目前无线的最低延迟吗?

5 C# C( Z/ i0 G; T我没用过其他无线手柄,所以实在不知道我自己做的这个手柄到底是不是最低延迟。$ h4 c) s) x5 T: p
不过根据网上的说法,延迟高低主要是由通信协议的复杂程度,以及数据传输速率决定的。这个模块虽然是2.4G无线模块,但由于协议很简单,所以延迟比较低。$ E6 e. }$ s+ _" u% F
我用这个手柄玩一些ACT游戏,比如超级马里奥、忍者龙剑传、热血系列,完全感觉不到延迟,和游戏机自带的手柄没有任何区别。唯一的区别就是这个手柄是用火花山寨手柄改造的,外壳是垃圾回收塑料,粗糙+脆弱,导电橡胶弹性不佳,手感不是一般的差。
4 ]2 F0 L$ i" z9 Q  s: y- \% X我手里还有十几张板子,等我有空了我再做一套,到时候买一个好一点的手柄改造。
回复

使用道具 举报

 楼主| 发表于 2019-5-29 16:56:14 | 显示全部楼层
ppad 发表于 2019-5-28 17:276 N9 ~. |% e9 {; c. {( u8 W
给技术帝赞一个,有半成品发布吗,自己焊接改造就可以,编程实在不会啊 ...
4 n! a) w8 c( G. C; H
很可惜,我手里没有多余的单片机了,LDO也找不到了,锂电池以及充电模块更是没有了。反正就是该用到的元件基本都没了,所以没法发布半成品。
& C/ U0 }% G# u两个板子倒是有十几张剩余。
7 Y. |. O6 a9 M3 O/ ~你要是有USB转TTL串口板,完全可以自己买这两种单片机,然后我给你编译好的固件,你自己用串口板下载到单片机里面就行了。两个2.4G无线模块也得通过串口板用AT命令设置参数,不过好在我在设计电路的时候就已经预留好了串口,可以直接在线下载和在线设置参数。总的来说并不麻烦。
回复

使用道具 举报

 楼主| 发表于 2019-5-29 17:00:34 | 显示全部楼层
孙大师 发表于 2019-5-28 18:557 ?) q" F8 q  i0 i
非常好,楼主是技术帝,到目前我都还没开发fc的无线套件,等空了,开发一套套件,等玩家自己组装。 ...
) f5 i9 W1 N9 R+ m+ i; ?  p: \
能得到孙大师的赞誉,不胜荣幸!( e+ p& v! m# D: ~( m: P- U3 y; }$ Z
不如开发一个多功能手柄,比如用SFC手柄改造,L/R键配合其他组合键可以用来切换2P~4P、调节连发速度、软重启等各种功能。接收端插到15PIN扩展口。
回复

使用道具 举报

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

本版积分规则

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

GMT+8, 2026-5-15 20:08 , Processed in 0.099697 second(s), 14 queries .

Powered by Discuz! X3.5

© 2001-2025 Discuz! Team.

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