找回密码
 注册

QQ登录

只需一步,快速开始

查看: 24231|回复: 29

自制FC无线手柄

  [复制链接]
发表于 2019-5-22 14:16:45 | 显示全部楼层 |阅读模式
本帖最后由 雷精灵2046 于 2019-6-14 09:28 编辑 6 _) ?+ m' v; |8 X

8 N! _7 z$ R1 _6 k3 G没有用复杂的分立元件搭建发射接收电路,直接用的现成的2.4G无线模块jdy-40。1 c* F/ Q" c" H6 f+ X; A" K

: X% Q0 _9 C( ]: y+ m, [+ O6 I$ Y) ]0 {7 {
发射端靠3.7V锂电池供电,用了一片SOP8封装的STC单片机,负责产生连发脉冲,同时负责检测电池电量,电压低于3V左右的时候触发低压中断,低压指示LED就会亮起来告知该充电了。平时发射模块和单片机均处于睡眠状态,有按键按下才会唤醒,从而实现省电。实测睡眠状态下整机电流约1~2uA。板子洗了一下稍微干净了一点。因为对于微功耗设备来说,焊接残余的助焊剂可能会增加漏电流。
* E6 ]: D( ~4 x5 H- p1 c) B% a
% j, @& M' R- _( i$ ?5 V3 W买了一个火花的FC山寨手柄,去掉里面的牛屎板子,并修正一下塑料挡板,把锂电池和充电模块装进去。, ]# c8 z/ N+ A$ e$ ^6 ^3 C
为了减少体积,充电模块裁剪得十分小,并且更换了充电电阻使之适应这个小小的锂电池。这么小容量的电池,也不需要多么大的充电电流是吧?
, e. o% B* ^( U6 J然后统统用热熔胶粘上。充电电流比较小,所以发热很少,不会熔化热熔胶。9 m0 I0 n0 [5 |6 X- A1 i; e" m0 p

" J. P" E, h0 I0 G- P) D" M; ~! x9 m) _9 O7 ^
" b6 f" U$ {+ t
最后把按键、导电橡胶和电路板装上去。
* M6 i8 K5 C4 [) r精心裁剪了电路板,正好扣上,不会阻碍其他元件,也不会影响后盖和拧螺丝。9 c4 U4 g/ {. e" f$ b. A6 I# Y
, z: S$ ^& ^; d& P
% r9 R3 g# ]9 H( V- _
完工!
; y. r# M. A  w. a: |# k6 v6 S0 M
; O, l* w, A/ B0 i% S& o, |
这是充电的MicroUSB插座。旁边的小孔用于透出低压报警LED的光线。
' F& ?# q) R, ~! c0 N
+ y( x/ o$ e* i& _
, W% V- r6 o, M* V/ D- K接收端用一片DIP16封装的STC单片机模拟CD4021。为啥要用单片机模拟而不是直接用CD4021?因为jdy-40模块接收端在有按键按下的时候输出高电平,无按键按下输出低电平,和普通手柄正好相反。当然我也可以用两片74HC00或者74HC04之类的逻辑门进行反相,但那就增加了芯片的数量。对于FC手柄这种工作频率并不高的设备来说,STC单片机完全可以胜任模拟工作。' m0 s9 T/ G1 L5 K; n

4 q  `- ]7 Q5 y6 i: h5 g' I/ |' `0 v$ e7 f& K) @2 i

% L5 S: K. r$ L0 H% K电路设计有点小小的错误,所以有几根飞线。原本设计使用低压差LDO是XC6206,结果在做这个接收模块的时候,买的LDO居然找不到了!无奈只好用了AMS1117。幸好对于接收模块来说是5V降到3.3V,1117可以胜任。要是发射端手柄的话,3.7V降到3.3V,那就非得用6206不可了。
* T! O- _' p# R6 R" [: {" _! I/ j  n" D+ h1 ~- Y! q$ t2 b
实测十分灵敏,延迟极小几乎感觉不出来。可惜这山寨手柄的手感并不佳,尤其是方向键,软塌塌的。看来我得买个剪线手柄改装。0 ^" w2 }) N) N
+ s6 I/ g/ o! J; J  A, |9 \* ~5 ]2 p' j
这是电路图,有兴趣的朋友可以参考。( }) s8 U4 b/ Y1 a' E& A

  }- a5 `/ s7 ?: _  }- o7 X( v8 e3 g5 n) j: D' u; ?
我信奉开源主义,十分痛恨把技术藏着掖着。好东西大家分享嘛!所以两个单片机的源代码大公开!
' V  M; y+ l! S3 ]$ c0 u编译器:Keil 51。
' u6 x# o0 ]6 S7 S6 x
; E0 N2 `  x: H7 t$ a1 ^# T发射端:
. t; r: S4 _  B0 R7 M0 C
  1. #include <INTRINS.H>7 o  Z- F7 g0 X+ J. d, c4 W
  2. #include "STC15W.h"1 d* a& r8 G  X" |$ p( z& N# S

  3. # ?# ?4 H( S1 i5 _3 |) \
  4. 3 D  H& \2 c& F& `1 Y% Q/ S
  5. /*1 f: c( p0 N+ L! t5 \
  6. --------------------------
    3 j3 \9 @4 z+ r
  7. |1 (OUT)        \__/   (INT1) 8|
    & R: Q: k& j; m/ t- l) {  w& g
  8. |                                                   |
    + ^6 S1 {, t1 F# A2 U* u
  9. |2 (VCC)                   (INT0) 7|
    ! H6 g- S" {3 H+ `+ P
  10. |                 STC15W204S                   |# n  @+ c, ]5 J& k$ A  y/ ^
  11. |3 (LED)                         (TXD) 6|: C8 r' K) @- A+ J9 f! h7 \
  12. |                                                   |
    2 Q# ^' {( G( H
  13. |4 (GND)                         (RXD) 5|
    - J  {' ~0 \# q3 |+ y4 \& a7 g' h
  14. --------------------------/ O# Z4 ]4 S3 h. X* [( ^5 Y

  15. ! R+ e! b# Z) M
  16. LED ---|<|---[===]--- VCC# W6 k6 [9 d5 B+ B& d5 L
  17.            Red          330
    3 G, R1 E% W" S8 E* c
  18. ' n; s' ]3 B3 p7 M9 \4 b9 \5 x
  19. Fosc = 6MHz
    . o+ U+ b8 V6 O. b* t+ ~" M
  20. */
    5 `  r9 P- q4 G/ q( r! F
  21. 5 E) E4 w! C- ~. V- u4 A) Y$ ?
  22. 6 v* s  h4 k; c& v7 w
  23. // 矩形波输出脚
    & v/ d$ u0 l* E! K: ^- Q- [2 k% B
  24. sbit OUT = P5^4;4 P5 G* L! w2 Y. o2 D  m1 ^
  25. // 低压指示灯引脚
    6 y+ j6 _/ m" K8 u+ Z6 K
  26. sbit LED = P5^5;
    9 `4 x9 b6 s, q5 t* L* u" X9 L
  27. % S; z1 y( W! j% T: R. i
  28. // 停机标志位) J" b7 j$ \1 |; p! j
  29. bit isReadyToHalt = 0;# V: N* W, Q" e7 [; @0 G
  30. . N3 O; k# n  D1 \' j
  31. // 矩形波次数累计
    " y1 |: u2 u. c- e
  32. static volatile unsigned char count = 0;
    + V/ c; B9 |$ t' q) a" @
  33. 4 H; L; B1 J9 [3 B6 U1 f/ r8 o% I; @
  34. - j! u5 J; N5 m7 q' [
  35. static void GPIO_Init(){
    6 n0 T- V7 K% D2 Y
  36.         // P3口设置为准双向,默认靠内部弱上拉输出高电平1 D" i  @: w: L; z- h" Q+ B* f" F
  37.         P3M0 = 0;) D4 q7 L% ?; i4 O8 z! s) c2 t
  38.         P3M1 = 0;
    ! O2 x: H% g0 L, g: b4 k
  39.         P3 = 0xFF;' H6 u/ `* d+ p0 e
  40.         // P5口设置为准双向,默认靠内部弱上拉输出高电平* d2 e1 Y: Y; f5 X) F5 A
  41.         P5M0 = 0;
    0 C+ P% d0 r7 j4 @1 P7 y
  42.         P5M1 = 0;
    9 D7 t, R1 k$ s1 _8 q, {& Q' b
  43.         P5 = 0xFF;
    & z" Y( _, T8 ^' I, y# k
  44. }
    + y6 S% o% u8 l

  45. , A8 @' U. @/ \* `& I- u9 y0 }
  46. static void Timer0_Init(){( q% g# m6 E( r7 d5 _. m5 `
  47.         // 16毫秒@6.000MHz
    ! {/ Y+ N+ u& ?- f! W6 Y
  48.         AUXR &= 0x7F;        // 定时器时钟12T模式
    ( M2 V: l4 @5 j! j! a# U) T0 |& r
  49.         TMOD &= 0xF0;        // 设置定时器模式
    % N2 l+ C: ]2 N2 e4 N
  50.         TL0 = 0xC0;                // 设置定时初值
    4 X/ g( G# L" g( y. |$ J, W5 b1 z  p
  51.         TH0 = 0xE0;                // 设置定时初值7 i+ L) p  S! ]1 v: d0 B  x/ z) ]* }$ C
  52.         TF0 = 0;                // 清除TF0标志) p( k. J$ D- M4 X' n- A
  53.         TR0 = 1;                // 定时器0开始计时
    " y4 L% a0 L* G5 w  O) E
  54. }
    & S5 d) ?* b. V* U9 d2 C8 h& ~$ ]2 g

  55. " [  V, v3 `- f# f, m: F
  56. static void Interrupt_Init(){/ m" l' O9 `; w9 K. L
  57.         // INT0中断触发类型为下降沿触发  a" O" c3 X6 q+ b
  58.         IT0 = 1;# n5 S/ e! ?2 L, G8 ]: p7 ~
  59.         // 允许INT0中断$ j* B. b4 ]1 m& B
  60.         EX0 = 1;0 t: _( {" K% S) T0 f' n! j+ l
  61.         // INT1中断触发类型为下降沿触发
    - @, I# @: [4 Q* s) O
  62.         IT1 = 1;7 _' Z1 @  l( C9 o8 w
  63.         // 允许INT1中断8 d8 s+ Y: J6 D( ]. r; J
  64.         EX1 = 1;' W! ~$ D" j; U; \
  65.         // 允许定时器0中断
    : S* g  W! y1 ^/ p. j: w
  66.         ET0 = 1;* h; {- Z5 i8 O2 u
  67.         // 允许全局中断
    9 f( N9 `+ a% f
  68.         EA = 1;
    6 K2 n0 r: d! K, o3 q
  69. }
    0 j4 Y) V- L% c2 e: G4 H2 g
  70. 5 V4 ?( }# U8 l2 {
  71. static void INT0_Isr() interrupt 0{
    ' I% L8 O% q6 s
  72.         // 矩形波次数累计归零1 Z  Y. k9 B8 h' u# B4 w6 G
  73.         count = 0;
    9 P" |7 [/ ^4 N4 g5 v
  74.         // 重开定时器0中断
    2 N& b- G7 J- d! ~$ r" u$ o
  75.         ET0 = 1;4 z/ ~; v% V% g7 ?" a- }
  76. }* l& }8 ^4 A3 I" u" |# N- A
  77. . E) m& G/ ^/ M: h; h% ?
  78. static void Timer0_Isr() interrupt 1{
    # @& U6 |& f2 X
  79.         // 输出矩形波
    & M9 @! A! Q* S' y  h; k5 N/ T
  80.         OUT = ~OUT;6 T5 r( C) r$ q7 i  V
  81.         // 累计矩形波次数/ A. Y' K! k' u, {  P6 n1 i
  82.         count++;
    4 s% c; \/ R- g8 {" k! F8 ?
  83.         // 超过250个矩形波,准备停机1 ]7 N. {9 F" _/ W# ^
  84.         if(count > 250){
    $ Q6 a; U. L5 I! d
  85.                 count = 0;# Z. b5 c. g& P! ^. D
  86.                 isReadyToHalt = 1;
    6 \) x; b' _% a. U" e0 A
  87.         }
    7 P* i6 w% J$ ?4 x: ?/ H
  88. }
    * r6 J/ G; @3 ]+ q: A* s
  89. $ o7 i+ C! z, S/ e1 j' O4 o
  90. static void INT1_Isr() interrupt 2{9 I" B8 S  }& ~4 k
  91.         // 矩形波次数累计归零
    ' p( p3 F" T# {$ _, S9 M# Z. x
  92.         count = 0;
    ) |7 `4 m% a; e1 A) z
  93.         // 重开定时器0中断3 O: F, S' E* M2 ~; {
  94.         ET0 = 1;
    $ H# A$ y8 d( z! y; e7 l0 x) J
  95. }& X- [/ Z2 y0 i

  96. # h1 Q! m% e6 T& `
  97. 1 B' V, J+ l3 T% M8 n7 n! w1 Q
  98. void main(){4 v- [7 I7 S$ D9 T  G4 m3 o% M
  99.         // 初始化P3和P5口
    & o8 J" r! u5 X* z) y0 e$ Y9 s, [7 O
  100.         GPIO_Init();
    + Y! {" @$ |! ?8 P
  101.         // 初始化定时器0
    * a( w. O/ y( C% G% W& `" u' |
  102.         Timer0_Init();
      ^1 F3 u6 U/ y- \. W+ K
  103.         // 初始化中断
    0 k8 Q7 O& S" a7 f
  104.         Interrupt_Init();
      ~* ~. N2 I& o) J2 i  D
  105.         / ^4 r9 k' F: w6 V& v" J! @, j
  106.         while(1){
    6 h9 i5 D2 f% N
  107.                 // 检测电量, A3 }% F7 [5 ~+ c) L0 N7 H
  108.                 if(PCON & (1 << 5)){
    9 X& x# Z) P  X- L* _3 `- _3 l
  109.                         // 如果电量低,低压指示灯亮# S7 k( z" S: p( u& L4 ?4 b
  110.                         LED = 0;
    ) g( `4 m' n4 T4 r& n( `
  111.                         // 清电量检测硬件标志位
    0 U0 O6 G1 ]" |) ^0 I$ v8 j
  112.                         PCON &= ~(1 << 5);
    + G4 g# U" L7 T0 i
  113.                 }else{
    , W+ Z7 \1 I7 Z1 D1 [0 d$ q
  114.                         // 电量正常,低压指示灯灭& T( V& }* t/ o$ H
  115.                         LED = 1;
    & _) e* B& S; R. L+ j- R5 F$ W
  116.                 }7 ~) l( d7 p" Y9 j, f; E
  117. 2 Z3 i- \2 C* U: U9 M3 {
  118.                 // 检测到停机标志3 E9 s9 n, O' Z/ f( J; J/ Y
  119.                 if(isReadyToHalt == 1){4 \! B8 |* [) I) K' Y
  120.                         // 暂时关闭定时器0中断
    " L6 L* s; q, J
  121.                         ET0 = 0;$ V( q5 H4 _' |1 I0 B4 d
  122.                         // 停机之前先把矩形波输出脚置低电平,以方便INT0和INT1唤醒CPU9 Z* ?  W3 ^7 q# I2 w- b0 \
  123.                         OUT = 0;
    8 _) {8 b7 S: k5 i
  124.                         // 停机之前先把低压指示灯灭掉,以省电
    ) W$ |6 t0 i( {
  125.                         LED = 1;3 u2 p# J+ K1 O5 u# K) z$ a
  126.                         // 进入停机模式
    & J. U. q3 d! x3 H( l8 H0 o
  127.                         PCON |= 0x02;% S5 V/ j# L  n! w
  128.                         _nop_();
    + B; a( e" d+ s8 V
  129.                         _nop_();. ^7 D* `' `, r: [4 h/ Q" j, [+ W
  130.                         _nop_();$ j6 {' m" }( q  [$ z* \
  131.                         _nop_();
    1 {) E: R- a0 S% C7 \% k/ T) @
  132.                         // 唤醒,清标志位
    ! q9 Z  m: G: C( z" e+ B
  133.                         isReadyToHalt = 0;
    # L" R7 g7 @. \+ w9 K; H6 `
  134.                         // 重开定时器0中断
    8 }/ b) k3 H: |4 \
  135.                         ET0 = 1;
    & Z3 P3 f, `/ @" e
  136.                 }' z: Q" k1 W  o* N" f$ }
  137.         }
    ' Q' F( t' n7 i, J1 N* l  Z$ T
  138. }4 @9 C3 S* R: O0 v$ p
复制代码
" I" ?' N  g1 |4 `' a- S$ d/ _
硬件参数配置:' M# M8 l9 p; ^  Y- d) w) W

6 r/ _2 [5 U! o5 O4 m; @- n7 k0 Q
4 @2 q0 Z: x, E$ H, A2 D/ t0 z接收端:# b3 d- L) P5 l
  1. #include <INTRINS.H>
    * ]% U5 v& l  k. Q; {) F9 Y# M. g
  2. #include "STC15W.h"4 W7 L/ Q1 [% @+ z( i2 E! |

  3. # m+ T$ F) {3 E9 B
  4. 9 |, a$ T5 @6 Z. L& `: `
  5. /*
      ^" e' M# Y: a' U

  6. 6 t) A# Y1 A9 L* K+ k
  7. *---------------------------*
    - {# V5 g0 h$ i: E8 t
  8. |1 (GPIO2)         \__/  (GPIO1)16|- {0 u2 _; L  W/ l: r
  9. |                                                        |! ?9 m5 l1 P- m8 ^7 x  T
  10. |2 (GPIO3)                   (GPIO0)15|. y: s' W0 R3 G* K* r. L
  11. |                                                        |
    ( [9 ~$ a1 ^' \- p# c! U
  12. |3 (GPIO4)                                  14|
    - z* V6 S- u$ P
  13. |                                                        |
      y( N: P4 ~( L, ^
  14. |4 (GPIO5)                        (DATA)13|' s9 H0 D# O! f9 a
  15. |                  STC15W204S                |- u" Y0 \! G+ D, b
  16. |5 (GPIO6)                   (LATCH)12|
    $ B( X/ j% @4 ^; N
  17. |                                                        |
    : @; U8 f# |: U
  18. |6 (VCC)                         (CLK)11|* l1 A( H* Z( q' h( M, m
  19. |                                                          |, @9 X. x2 g$ |) E/ D+ V" p
  20. |7 (GPIO7)                         (TXD)10|
    ( K% {1 P. r6 t$ l# a! @
  21. |                                                        |
    ) h& O% b$ J' w$ K/ @& K: J
  22. |8 (GND)                         (RXD) 9|5 F. f$ {: U) h) G$ ]( Z* u
  23. *---------------------------*
    # s' o; X' {0 [1 n
  24. Fosc = 12MHz
    4 ]* v- \% o& g3 B. Z1 a9 `8 y

  25. ) X$ y9 x6 W' c5 E
  26. P1.0 -> 上2 E7 }% m/ U6 A6 G1 c
  27. P1.1 -> 左6 Z& }/ F* {8 t- {2 k! q/ f
  28. P1.2 -> 下
    : u6 U0 h" Q: R( `! r5 R1 T* r- Z* J
  29. P1.3 -> 右
    4 H! Z( E% x) O( j2 r& K) z+ \
  30. P1.4 -> SEL
    ! g6 m0 T( i+ I9 T* g) L$ i
  31. P1.5 -> STA
    / N. M' N% `% c) C. X, z
  32. P5.4 -> B/ D. r3 ~! A) [. O  P
  33. P5.5 -> A! b9 n1 |" W8 a# H( P* ?
  34. % `  f& a2 t: h1 \  z
  35. */" c+ z  t! j" |( C# j: U
  36. % Q; b; w" A# S: Q# G' G& |. j( [

  37. + `( ^" c2 i7 q& t
  38. sbit CLK        = P3^2;6 L! G% w0 P  c6 @: }8 ~
  39. sbit LATCH        = P3^3;
    ) O! i. l# m4 Z9 ], F
  40. sbit DATA        = P3^6;
    ! t0 ~( K& H& D
  41. ) {9 K# G  t8 v0 H5 }9 [( {/ S: ^
  42. bit isReady = 0;/ Q/ {+ d) X; ~: D" ~$ n, v
  43. static unsigned char key = 0;8 E& g3 n. l1 c, Z$ M: W7 _
  44. static unsigned char buf = 0;        // 双缓冲。这个缓冲区保存从P1和P5组合而来的键值8 P3 f! }# a) E0 y# J
  45. static unsigned char bufReady = 0;        // 双缓冲。这个缓冲区保存上面那个缓冲区的备份* t! A# f) s1 ^$ R
  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 a' S' M8 [% t% I% V
  47. static unsigned char idx = 0;3 L( ]! q# x" k0 \
  48. 3 K' ~) Q* A7 t: q

  49. ! ~1 c" c! ^8 B+ h' C( p
  50. static void GPIO_Init(){: E' F( q1 o: E
  51.         // P1口和P5口用于接收并行信号,全部初始化为准双向,依靠内部弱上拉输出高电平. V5 `+ R9 k; @9 ?/ w% P6 y1 v& b0 j
  52.         P1M0 = 0;: t6 }: C1 j0 {0 O' ?( g3 j- @* I
  53.         P1M1 = 0;5 n6 H8 A+ x+ M/ K
  54.         P1= 0xFF;
    " R. E% I, v$ E+ w
  55.         P5M0 = 0;
      |4 i. G! @9 I0 N/ a) U. X
  56.         P5M1 = 0;
    ( k( O+ ]4 Z  w/ h
  57.         P5= 0xFF;
    6 u! k: ^3 m/ r
  58.         // P3口初始化为准双向% N+ N1 V* a& o- |
  59.         P3M0 = 0;% T0 o! t* _" K* C. t- h9 I
  60.         P3M1 = 0;
    5 @7 H1 T' L. L1 m8 T( Y. `
  61.         P3 = 0xFF;# E5 c+ K( p2 y* @% t0 d- |
  62. }7 y$ L( {/ ?2 B3 T

  63. ' l% ]! _6 }' B  U: _' T9 \5 s
  64. static void Interrupt_Init(){
    6 J% w0 g, x; D( a8 ?- O5 I
  65.         // INT0中断(CLK)触发类型为上升沿+下降沿
    / ^+ n( G" k; a: N
  66.         IT0 = 0;7 P4 I5 X8 U; m
  67.         // 允许INT0中断
    6 i7 y7 S" f& E: L6 h
  68.         EX0 = 1;
    8 G8 u; {9 O, U4 J* p$ f: O  ?
  69.         // INT1中断(LATCH)触发类型为上升沿+下降沿
    - \" g3 z/ ]: T& }# T$ ^
  70.         IT1 = 0;: s5 F& j2 b8 D& R) i
  71.         // 允许INT1中断
    $ U. g. E0 a$ _5 {0 D
  72.         EX1 = 1;
    & p9 b, B; z3 l8 s; U  r1 N" K
  73.         // 开启全局中断3 f. B4 P. W; R& S6 x; W  S1 Y6 ~
  74.         EA = 1;
    ' w! _+ d( l. S
  75. }
    2 p# j% N/ ~5 Q5 p
  76. 4 I; ?. J) G3 f; X  F! k
  77. static void INT0_Isr() interrupt 0{
    2 a0 Y9 ~* C% w5 `
  78.         // 只有已经成功锁存才允许CLK移位+ ]. r. ~* d/ v  S" J
  79.         if(isReady == 0)
    8 L" n: K! t/ [* y) E$ ], O. H* r
  80.                 return;2 w7 ^% |7 ~! g2 w6 d( R, U
  81.         // 读当前引脚电平,如果是低电平则说明是下降沿,此时直接忽略该中断4 `4 o" E6 _- Z2 z! V
  82.         if(CLK == 0)0 r# q1 }$ i; o8 H. h- R
  83.                 return;
    + E* Y, B+ i. t6 z7 n
  84.         // CLK上升沿到来的时候,取锁存值的下一位输出) F, u% q6 Y0 l8 `/ p2 T& M
  85.         idx++;9 C3 t3 r4 P+ F% p
  86.         DATA = key & mask[idx];
      E; K0 G; r7 v: h' R5 S
  87.         // 如果已经完成7次移位,则一轮读取完成- Q- L# _9 M* r+ F6 I
  88.         if(idx >= 7)
    4 a' b9 \3 r# h1 h5 `# g8 @
  89.                 isReady = 0;1 _1 h  B) m% Q% a* I9 ?& ~
  90. }7 N) x# t/ j+ o6 d/ `
  91. ( x' l; Y2 k$ A9 v' s
  92. static void INT1_Isr() interrupt 2{' `7 P3 {0 h# p2 I7 i3 X
  93.         // 读当前引脚电平,如果是低电平则说明是下降沿,此时直接忽略该中断
    2 o) J. r' t5 E
  94.         if(LATCH == 0)
    & |7 Z' V9 `+ g
  95.                 return;' [9 J9 S" X# w
  96.         // 当LATCH上升沿到来的时候,锁存所有按键状态,同时把键值A输出到DATA' k/ z' N4 b  l% @0 x1 v
  97.         key = bufReady;
    4 ?& A+ G+ F0 X1 G' `0 x: F
  98.         DATA = key & 0x80;//mask[0];        // 为了加速运算,直接取表中的值而不是读表( w* m0 p$ D  @# ]6 \: d! Y& Y: k
  99.         idx = 0;
    ' a* ^  Z6 p; z' G0 s
  100.         // 允许CLK进行移位
    3 s! n, s1 r1 J2 ^) Q( j
  101.         isReady = 1;
    3 [7 y2 k8 K* h. N: E
  102. }) h6 f, T/ }0 ]. [9 p8 h: B
  103. 4 [5 n" l3 ]9 s* Y; F( v# {7 |- V; _
  104. void main(){  |& x2 C) g( ?4 k7 z
  105.         GPIO_Init();
    1 B, w) t. [7 T
  106.         Interrupt_Init();
      B1 i5 C# J) i' w
  107.           [8 S7 Q; x+ S! {
  108.         while(1){
    2 J1 h# L8 C6 |! d8 ]! \4 F( G: V% _7 U
  109.                 //PCON |= 0x01;        // 进入省电模式
    # H" [! m7 a, F  }7 w
  110.                 //_nop_();
    - b" ^- d6 X0 E9 X" l
  111.                 //_nop_();: ~, c1 M- G" L& P4 o; W+ h; j
  112.                 //_nop_();2 G( g9 z1 a! `& c) I* K+ _
  113.                 //_nop_();
    4 `' S7 \. O( I1 F
  114.                 buf = ~((P1 & 0x3F) | ((P5 << 2) & 0xC0));
    - K3 s' j6 Z7 y, u  f
  115.                 bufReady = buf;
    % y+ u3 p* O* O5 |% U
  116.         }- c! Z; e6 _, l6 Z0 i3 J# y* o
  117. }& Z) h: A% O, r) {/ H
复制代码

5 s' e/ L5 {) B/ s: V硬件参数配置无特殊要求,晶振频率选择12M即可。: g- T- E3 y8 N

. A* \% J8 N1 L( }这是编译好的固件。

本帖子中包含更多资源

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

×

评分

参与人数 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
/ G. s: e- z8 M2 H# i不错的设计,想问一下楼主,FC的15针公头怎么解决?普通的公头太短了,插不进去FC的扩展接口。 ...

  V. u3 V) U& x" G4 R# v1 @& f1 |坛友的改造方案
回复

使用道具 举报

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

使用道具 举报

发表于 2019-5-25 12:07:18 | 显示全部楼层
精彩,楼主动手强,也写得很详细。
/ n( i* O+ y  u. m+ p2.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
: S, a/ |. H6 W4 n9 q4 p精彩,楼主动手强,也写得很详细。
- M" ?) h) P# ?# u2.4G方案是目前无线的最低延迟吗?

/ n8 Q- N' z8 A4 {我没用过其他无线手柄,所以实在不知道我自己做的这个手柄到底是不是最低延迟。
7 g2 w) r% ~# g! G. k不过根据网上的说法,延迟高低主要是由通信协议的复杂程度,以及数据传输速率决定的。这个模块虽然是2.4G无线模块,但由于协议很简单,所以延迟比较低。
! {" ^" N  H* A# V  M# `5 L, U我用这个手柄玩一些ACT游戏,比如超级马里奥、忍者龙剑传、热血系列,完全感觉不到延迟,和游戏机自带的手柄没有任何区别。唯一的区别就是这个手柄是用火花山寨手柄改造的,外壳是垃圾回收塑料,粗糙+脆弱,导电橡胶弹性不佳,手感不是一般的差。  @" [# R7 x! P* b  N1 F
我手里还有十几张板子,等我有空了我再做一套,到时候买一个好一点的手柄改造。
回复

使用道具 举报

 楼主| 发表于 2019-5-29 16:56:14 | 显示全部楼层
ppad 发表于 2019-5-28 17:270 M2 J! }9 d! I* \4 y# n+ d
给技术帝赞一个,有半成品发布吗,自己焊接改造就可以,编程实在不会啊 ...

& Z- z) O: x9 @0 \' K很可惜,我手里没有多余的单片机了,LDO也找不到了,锂电池以及充电模块更是没有了。反正就是该用到的元件基本都没了,所以没法发布半成品。) x9 U1 g3 c' H3 e2 J+ M3 b$ K
两个板子倒是有十几张剩余。
3 Y) s) [+ W5 P9 {4 g你要是有USB转TTL串口板,完全可以自己买这两种单片机,然后我给你编译好的固件,你自己用串口板下载到单片机里面就行了。两个2.4G无线模块也得通过串口板用AT命令设置参数,不过好在我在设计电路的时候就已经预留好了串口,可以直接在线下载和在线设置参数。总的来说并不麻烦。
回复

使用道具 举报

 楼主| 发表于 2019-5-29 17:00:34 | 显示全部楼层
孙大师 发表于 2019-5-28 18:55
1 i  V$ r* i1 Y& C  q, L非常好,楼主是技术帝,到目前我都还没开发fc的无线套件,等空了,开发一套套件,等玩家自己组装。 ...
6 X( E# j; c/ W( S% J2 |$ H0 X+ P
能得到孙大师的赞誉,不胜荣幸!
' t* w0 J" e" l8 L( q0 O8 z2 Q7 N不如开发一个多功能手柄,比如用SFC手柄改造,L/R键配合其他组合键可以用来切换2P~4P、调节连发速度、软重启等各种功能。接收端插到15PIN扩展口。
回复

使用道具 举报

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

本版积分规则

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

GMT+8, 2026-3-22 15:59 , Processed in 0.109185 second(s), 15 queries .

Powered by Discuz! X3.5

© 2001-2025 Discuz! Team.

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