找回密码
 注册

QQ登录

只需一步,快速开始

查看: 26771|回复: 33

自制FC无线手柄

  [复制链接]
发表于 2019-5-22 14:16:45 | 显示全部楼层 |阅读模式
本帖最后由 雷精灵2046 于 2019-6-14 09:28 编辑
- \9 Y2 }5 C& `9 ?2 X1 S0 q3 {: O' J1 T" u
没有用复杂的分立元件搭建发射接收电路,直接用的现成的2.4G无线模块jdy-40。! }) K( a. m) C; G# d! K  Y; `

  V$ I: S' Z7 o0 S: o' b# [
. n$ L: m6 e/ W# w8 `& m发射端靠3.7V锂电池供电,用了一片SOP8封装的STC单片机,负责产生连发脉冲,同时负责检测电池电量,电压低于3V左右的时候触发低压中断,低压指示LED就会亮起来告知该充电了。平时发射模块和单片机均处于睡眠状态,有按键按下才会唤醒,从而实现省电。实测睡眠状态下整机电流约1~2uA。板子洗了一下稍微干净了一点。因为对于微功耗设备来说,焊接残余的助焊剂可能会增加漏电流。
' o% B! G9 r" R" T( H5 I3 E9 p6 U( r* D( b+ l9 T  q1 _* |
买了一个火花的FC山寨手柄,去掉里面的牛屎板子,并修正一下塑料挡板,把锂电池和充电模块装进去。5 M7 d" W+ t$ P. |
为了减少体积,充电模块裁剪得十分小,并且更换了充电电阻使之适应这个小小的锂电池。这么小容量的电池,也不需要多么大的充电电流是吧?
# i' p5 I' W" p, F2 n5 h# U2 A0 @然后统统用热熔胶粘上。充电电流比较小,所以发热很少,不会熔化热熔胶。
/ Z" `/ ]3 @* S7 L, S& U$ V  Q. ?$ q. m; ?* b7 i5 h/ @1 r6 ]; `
8 m/ w3 Q1 I5 m& h3 G; B7 s
. D# Z+ O& ]' E/ c9 f5 `4 E+ P
最后把按键、导电橡胶和电路板装上去。
3 d, g& Y) T3 H. R% e" N精心裁剪了电路板,正好扣上,不会阻碍其他元件,也不会影响后盖和拧螺丝。
9 U) s5 T/ c0 \  d( o
  y4 u+ n/ ]# R# m5 _
3 w; u- h+ B& f7 _7 n3 ~. z  Q2 N# R完工!
9 Y" s, k2 [9 _7 {( s/ P, h
2 W1 s+ N' k, j9 n* ^6 G' Q' C8 V4 ~6 u
这是充电的MicroUSB插座。旁边的小孔用于透出低压报警LED的光线。# ]+ P& w$ C/ d4 O

: Z" u* h# W: l8 `/ I5 z' S
7 I4 u3 L5 u1 b' s接收端用一片DIP16封装的STC单片机模拟CD4021。为啥要用单片机模拟而不是直接用CD4021?因为jdy-40模块接收端在有按键按下的时候输出高电平,无按键按下输出低电平,和普通手柄正好相反。当然我也可以用两片74HC00或者74HC04之类的逻辑门进行反相,但那就增加了芯片的数量。对于FC手柄这种工作频率并不高的设备来说,STC单片机完全可以胜任模拟工作。; ?  R1 F$ i# T7 x
/ i) w: t* ?0 C2 H; V- v! \

# a0 {2 _, ^/ p% J9 A: L8 H' H4 @- A: R& u% P$ g2 g! l# N5 [
电路设计有点小小的错误,所以有几根飞线。原本设计使用低压差LDO是XC6206,结果在做这个接收模块的时候,买的LDO居然找不到了!无奈只好用了AMS1117。幸好对于接收模块来说是5V降到3.3V,1117可以胜任。要是发射端手柄的话,3.7V降到3.3V,那就非得用6206不可了。
* X$ ~- Z& q* y  }% u5 e8 A3 L7 d  O8 }+ F( I" l8 q4 a
实测十分灵敏,延迟极小几乎感觉不出来。可惜这山寨手柄的手感并不佳,尤其是方向键,软塌塌的。看来我得买个剪线手柄改装。
1 J/ K4 Q9 H2 V
7 @3 P  d" b4 Y/ Y! p& P) k2 z) n这是电路图,有兴趣的朋友可以参考。3 a# U5 c, e! Q7 n6 T7 C. Y
9 i4 \# ]% _- R) M4 X

4 t3 s5 D, }; ^& j7 P- @+ S我信奉开源主义,十分痛恨把技术藏着掖着。好东西大家分享嘛!所以两个单片机的源代码大公开!3 N* R# h3 i3 J
编译器:Keil 51。
/ D' L; L- r7 J0 c3 X
- c8 I* U; S# O( t" j2 B) i发射端:3 U! M" T7 {/ z1 D7 D- ]/ F2 N  ?
  1. #include <INTRINS.H>
    5 |0 `5 {7 H: ^$ J
  2. #include "STC15W.h". V5 s# A1 H8 T5 _  U
  3. 5 ~3 j( e8 x( b$ B

  4. . ]0 A0 E% G' d6 L+ I+ M
  5. /*7 ]8 S- [% p" G8 b  E3 V/ X
  6. --------------------------
    , A$ d. l) O# i7 Z4 G. C& N
  7. |1 (OUT)        \__/   (INT1) 8|
    & _0 m# W+ e" T7 E  k( Z
  8. |                                                   |. e6 ^& u; Y* J( E: n
  9. |2 (VCC)                   (INT0) 7|! O) ?% n/ \/ i1 F2 y. J
  10. |                 STC15W204S                   |
    / q) g" i" e% p' K1 j: I1 u
  11. |3 (LED)                         (TXD) 6|/ i# q1 q$ \0 O
  12. |                                                   |
    . m' t4 m1 o' i* K4 P
  13. |4 (GND)                         (RXD) 5|
    % J. z- ]- k2 R5 k$ X& z
  14. --------------------------+ _& C  r. F/ y1 f

  15. : n  \" _5 t5 |2 Y/ f) j
  16. LED ---|<|---[===]--- VCC1 @" k6 ~$ W0 ]9 d7 ^
  17.            Red          330
    0 m1 V/ V4 e3 M: M# f

  18. 0 U3 c( o! c( H$ ~; K+ c* m
  19. Fosc = 6MHz
    % U; `' C  `2 U% H# p0 m& X1 u
  20. */
      E5 h- l1 x3 Y4 L

  21. . J3 A0 h! v. r  [& r3 d
  22. - b. |7 _0 r% r( G
  23. // 矩形波输出脚
    * [9 ~6 \( N  [" h
  24. sbit OUT = P5^4;1 Z5 G$ z5 i2 o$ z% Z
  25. // 低压指示灯引脚
    ) x- ?7 g% `/ `7 O4 @3 T
  26. sbit LED = P5^5;3 {+ a, S9 n& d" @8 B+ i: U
  27. % }3 o- f8 _4 K% ^0 K7 M
  28. // 停机标志位+ y9 ^0 l: G7 k. x4 B! Q: T
  29. bit isReadyToHalt = 0;
    : S' ^" h5 y, q0 D- o* j! h
  30. ) L/ m" b0 N& H/ O4 k. b
  31. // 矩形波次数累计$ L1 M- ]# Y: o
  32. static volatile unsigned char count = 0;
    5 O5 Y3 J( A  K  Z6 R
  33. 6 a- p4 a9 U' N

  34. , V0 C8 d1 B  _) a+ j, ]
  35. static void GPIO_Init(){
    / g" C% V5 a8 G
  36.         // P3口设置为准双向,默认靠内部弱上拉输出高电平
    " |. I" Q$ t5 }( }: e
  37.         P3M0 = 0;' Y. Y' N+ A( r. v, t" x
  38.         P3M1 = 0;
    6 L% l% A  `, [% N: d6 H
  39.         P3 = 0xFF;3 {+ e' R/ @& n, H
  40.         // P5口设置为准双向,默认靠内部弱上拉输出高电平
    1 \8 M* b1 z4 j4 o$ |& _* Q
  41.         P5M0 = 0;
    + _* }# T$ R* J7 @
  42.         P5M1 = 0;1 U: i' G# S, Q1 M! p4 n
  43.         P5 = 0xFF;
    / d' e$ @0 C1 e/ b, k% Y, d
  44. }
    7 `) c# _% b# C2 J$ C5 r" B9 ^, R

  45. 4 p2 t& e  u+ F5 u7 x+ g( f0 B
  46. static void Timer0_Init(){
    , D; a+ F7 U+ B6 |- I7 B
  47.         // 16毫秒@6.000MHz
    & R2 l; ~4 d: q, u# }0 f; C& z
  48.         AUXR &= 0x7F;        // 定时器时钟12T模式5 k. V; z! \9 j6 P2 H( W5 }
  49.         TMOD &= 0xF0;        // 设置定时器模式5 t) i1 D9 s- z
  50.         TL0 = 0xC0;                // 设置定时初值
    3 M; P9 ^  a' G+ R/ h6 q
  51.         TH0 = 0xE0;                // 设置定时初值
    . E# R8 F1 o5 X0 Y0 T% `
  52.         TF0 = 0;                // 清除TF0标志
    & u7 X  ]6 S- x. ?4 e
  53.         TR0 = 1;                // 定时器0开始计时2 K/ Y2 K, `: A% W0 h
  54. }. @; P4 c2 e) b  f& N
  55. * ?8 {4 T8 g5 v! J% E
  56. static void Interrupt_Init(){
    $ F, P" h* g0 q
  57.         // INT0中断触发类型为下降沿触发
    ; C5 z! h, i) p3 i
  58.         IT0 = 1;
    . i' S* }2 |8 I6 z3 C  M* y
  59.         // 允许INT0中断- }5 H' v6 N% s* S, v5 N
  60.         EX0 = 1;
    3 l  R: Z2 Z/ R3 Z+ u. h9 _/ R
  61.         // INT1中断触发类型为下降沿触发
    ' A8 u! R" Y( Y
  62.         IT1 = 1;
    ( K* s0 ?1 I6 M0 N* [. `
  63.         // 允许INT1中断
    * c9 j# d0 O  ]- _
  64.         EX1 = 1;( k" X' K6 ?% I7 v! U7 U% T
  65.         // 允许定时器0中断( ^% _+ Q) K0 n
  66.         ET0 = 1;
    ) B/ p, g/ V- ]! B# M/ Z- F
  67.         // 允许全局中断2 q/ [6 [% e7 k: A) M
  68.         EA = 1;! t: e# l9 o: D6 K( X2 W3 P: s
  69. }0 L1 K8 ?) x4 k  m5 h3 v3 ^
  70. - o) q1 _. w5 J& d
  71. static void INT0_Isr() interrupt 0{1 O  a7 b, U2 `$ e  a# F
  72.         // 矩形波次数累计归零9 _2 c3 E' l: U1 e/ D& L
  73.         count = 0;
    3 ?& Y6 m3 I, A! f' d) y
  74.         // 重开定时器0中断
    - Y  \! N' m3 y' z) z5 `
  75.         ET0 = 1;3 j' v. j7 H# ^% G' R7 I/ p5 k; Y
  76. }: c0 e$ G. Q$ Y* Y4 r) O! |
  77. % C) W) j$ F; ^8 G# X
  78. static void Timer0_Isr() interrupt 1{3 E' \% r( ^( k9 g* x* X; ~5 g0 _6 m
  79.         // 输出矩形波
    ( A% l2 @! z2 |5 C& \3 o4 V$ q
  80.         OUT = ~OUT;
    ' o  O& h/ d7 Y% k6 I1 D5 P
  81.         // 累计矩形波次数
    * e: B* g3 o/ D9 U: H4 ^
  82.         count++;
    " u" h7 |/ V0 K; s3 k! S1 W- ~
  83.         // 超过250个矩形波,准备停机
    $ k7 W& s9 u' f* d+ T
  84.         if(count > 250){
    # y" i: f! p; h- j  l+ d1 U8 L
  85.                 count = 0;% e& U1 E3 _5 C9 k& C3 d
  86.                 isReadyToHalt = 1;
    $ @' m) K7 e+ s  e2 ]# ]2 |0 G* x
  87.         }
    ; D, \4 u! \( M/ ?" A
  88. }
    4 _7 R/ E5 H7 ~0 @5 I- p3 M
  89. 2 f' |1 A  B3 J0 k; L- T
  90. static void INT1_Isr() interrupt 2{5 A% H, o+ o- Y$ r  X/ h3 N: |
  91.         // 矩形波次数累计归零# H* K) k& H8 ?6 y
  92.         count = 0;
    8 `" x/ [- }4 T1 h. K. V
  93.         // 重开定时器0中断
    ' Q0 c' O  Y) W# K
  94.         ET0 = 1;
    - t$ W- z; Q) x6 w. @5 m! G+ _
  95. }
    * G7 J8 M  f2 D; b$ @

  96. ( c4 a8 j3 r; j, J0 |  \0 x; v
  97. : X/ d! F, Z* H* n  P- g8 H8 A0 q
  98. void main(){) L, p" a# A. Q0 o
  99.         // 初始化P3和P5口
    % a# ]8 k, z8 r: q
  100.         GPIO_Init();
    " C; {1 v9 |3 M# f; i7 Y7 K: p
  101.         // 初始化定时器0! @7 h5 y" m1 N" B
  102.         Timer0_Init();; f; x5 A+ q+ q% r* k* ^
  103.         // 初始化中断
      C' B1 |0 G6 G* U: [8 [. {
  104.         Interrupt_Init();; K4 u9 `: n2 _1 ^* K$ [
  105.        
    ( a  n, j3 P* @$ U
  106.         while(1){
    9 @7 N* t$ P* I* ^. d0 O9 [' z
  107.                 // 检测电量
    ' A1 t: H( g8 ?  Q) h
  108.                 if(PCON & (1 << 5)){6 Y: S+ m5 r0 f! m& [
  109.                         // 如果电量低,低压指示灯亮
    ; M* a$ W; u0 Z0 e
  110.                         LED = 0;# Y  \7 y' L& ]" s
  111.                         // 清电量检测硬件标志位, b+ R% c5 Y! ^9 c; U3 i
  112.                         PCON &= ~(1 << 5);
    4 i8 z' f* R: b, O; D
  113.                 }else{+ x/ R) T+ l# c5 v% I
  114.                         // 电量正常,低压指示灯灭, M0 t! i. C% ?2 P5 r. \: w) h
  115.                         LED = 1;1 {$ J( Y+ u, l1 b2 r
  116.                 }8 D3 A7 @7 M9 j
  117. 1 T! @! J: z+ N8 J2 `+ j( E4 O
  118.                 // 检测到停机标志
    6 B* ]. H( h/ F/ G$ M# A/ ?/ l" e
  119.                 if(isReadyToHalt == 1){
    + u% A% L5 F! S3 ^2 K6 f" c1 x( R
  120.                         // 暂时关闭定时器0中断& Z1 x/ W4 D2 w9 J5 K
  121.                         ET0 = 0;
    5 o' A5 E) t& U; `$ C
  122.                         // 停机之前先把矩形波输出脚置低电平,以方便INT0和INT1唤醒CPU% Q, Z: X5 A/ t
  123.                         OUT = 0;3 y& g  E3 Q) Z9 g6 f% w' u
  124.                         // 停机之前先把低压指示灯灭掉,以省电
    8 J) `4 D9 F( r) z; m6 ^
  125.                         LED = 1;
    & @' h: W0 c: r1 v
  126.                         // 进入停机模式
    : y* O4 b* i  ~- ~
  127.                         PCON |= 0x02;. u4 [+ I0 C# {: {1 _
  128.                         _nop_();3 U7 X) L3 {) k3 z5 f. I
  129.                         _nop_();
    $ F0 [3 S9 S4 i  F/ s
  130.                         _nop_();* d& P2 `  D9 y( v
  131.                         _nop_();
    ' x6 X8 c0 G0 _4 G3 ~
  132.                         // 唤醒,清标志位& M: \% G% B2 ?8 G8 M3 X' p
  133.                         isReadyToHalt = 0;
    $ c; m, @+ w% G5 a2 a" x1 h
  134.                         // 重开定时器0中断% g7 N, ^$ Z. m( k5 ^  U
  135.                         ET0 = 1;
    . p' i9 q) ]. ]; C; F2 j9 d9 x
  136.                 }
    : L" V1 p( y6 x& J: P5 R/ U2 {
  137.         }
    / {& {* i9 S8 J( k
  138. }( D/ g+ Y- z/ a1 E1 n# @2 U- D
复制代码

% j: F4 c) u: Z- t9 E. I# n2 t硬件参数配置:
4 Y1 F3 B0 x' |5 X3 o* u, D, ^7 ~$ F4 b4 K5 z) n) X* B: I( s

% ]1 p. o0 F& y( d+ f接收端:
) ~* T# J6 N, t) d5 ?
  1. #include <INTRINS.H>; E& Z. r  x& D; v
  2. #include "STC15W.h", g$ y. i/ P) _5 S7 K8 j

  3. ( w) M# }/ V( F' T! B0 h
  4. 4 n9 n! s5 j: Y  A9 l* l
  5. /*
    9 ^! @8 C+ r1 ~: v* Y2 t0 S
  6. % L7 S" s# q2 ?+ e( Y  f
  7. *---------------------------*
    2 S( C3 ]) b. h0 F
  8. |1 (GPIO2)         \__/  (GPIO1)16|& t" X2 a$ u; ~  K0 o2 w
  9. |                                                        |9 r  m3 b/ D8 x- s, g/ S* `2 G
  10. |2 (GPIO3)                   (GPIO0)15|. z5 d! d! J; M4 S- d" t5 I3 Q# H
  11. |                                                        |; q( ^9 V! _/ g8 W/ z( ?! K
  12. |3 (GPIO4)                                  14|. O6 b6 g! v6 Z# K
  13. |                                                        |2 q/ E# r, K- I  ^: b
  14. |4 (GPIO5)                        (DATA)13|9 y) n' @: K7 v% c: D
  15. |                  STC15W204S                |
    4 P4 m% e$ a6 F: C. l" o) h
  16. |5 (GPIO6)                   (LATCH)12|
    7 S: Q  X+ a% P) e& `
  17. |                                                        |
    ; P+ t1 [# R# _9 \
  18. |6 (VCC)                         (CLK)11|
    5 `6 ]; M5 b" _. D  N6 `8 d3 m
  19. |                                                          |
    / o& w  v2 H7 J- l' b1 _
  20. |7 (GPIO7)                         (TXD)10|
    2 E% x0 I" Q  _. H; O5 A! U" s4 [1 V
  21. |                                                        |/ h5 B; X; u4 B3 b  K
  22. |8 (GND)                         (RXD) 9|1 a* Z; P' B! n9 r% I
  23. *---------------------------*
    - h7 U1 Q0 T# `
  24. Fosc = 12MHz/ l% {) Y/ Z/ R8 C* w
  25. 7 h. H5 {9 C$ t0 ?: p
  26. P1.0 -> 上
    & X8 A" o1 Q. O( g
  27. P1.1 -> 左* K% S7 X% Z8 H5 g& q0 T
  28. P1.2 -> 下# `* v+ W4 s( {5 O; \0 V, {
  29. P1.3 -> 右
    ' o4 h: Z3 r2 H; ^2 |( m! x2 Q4 u
  30. P1.4 -> SEL! u: n7 B& Z3 R3 n7 G$ d" c
  31. P1.5 -> STA
    ' e" I( |: e5 X4 `8 c) V9 \' H+ ]. i! A
  32. P5.4 -> B
    . C2 _6 h2 I, I; ~
  33. P5.5 -> A5 x6 a1 D0 A9 |) @3 c4 |
  34. 0 A! n: f! C6 ^- s# _$ J
  35. */
    ; t; `; L3 r0 t' [# a: [7 n* e

  36. ' y2 q- v8 t3 {; r
  37. 5 N6 e+ q  K) B9 O4 e/ R8 j
  38. sbit CLK        = P3^2;
    ) T* \& m) m. O. `
  39. sbit LATCH        = P3^3;
    ) a" u' O+ {' B6 j0 J5 O3 \6 M& A
  40. sbit DATA        = P3^6;' x9 J% u: L4 g" a+ V
  41. 9 W" [# x8 I  |4 N
  42. bit isReady = 0;( L' g) u: Y. G: `0 L' b- {' j
  43. static unsigned char key = 0;0 l: T7 R4 B' Y2 Z) H  p' p
  44. static unsigned char buf = 0;        // 双缓冲。这个缓冲区保存从P1和P5组合而来的键值
    % t4 F# I- u$ e5 X! I
  45. static unsigned char bufReady = 0;        // 双缓冲。这个缓冲区保存上面那个缓冲区的备份* l9 J- ^1 }" \0 h% g( B6 _
  46. static const unsigned char data mask[] = {0x80, 0x40, 0x10, 0x20, 0x01, 0x04, 0x02, 0x08};        // A B SELECT START UP DOWN LEFT RIGHT。为提升速度,这个表放到RAM中1 e0 y! K5 u' m: {* Z& v! u6 c
  47. static unsigned char idx = 0;) M8 `5 v. f# P# E
  48. ' ?5 y  F; ^. Y
  49. 3 C. m8 f, i6 L2 |
  50. static void GPIO_Init(){
    8 _8 n9 k9 V0 [' j) t, @: X) t6 _
  51.         // P1口和P5口用于接收并行信号,全部初始化为准双向,依靠内部弱上拉输出高电平
    9 L$ I- n  D2 b6 y# K7 [
  52.         P1M0 = 0;" C& w7 N% H: B6 M# \, ~
  53.         P1M1 = 0;+ j) L& u0 Y0 v
  54.         P1= 0xFF;' b" d/ \* ?# m4 I
  55.         P5M0 = 0;
    4 q$ y1 X5 R6 h
  56.         P5M1 = 0;! J% Y7 N1 i6 k# \7 e1 g: {
  57.         P5= 0xFF;( v  C- e% d' g. v
  58.         // P3口初始化为准双向/ i- m% p. f! h" o4 _
  59.         P3M0 = 0;
    : Q6 Y( e' x& k: _% S
  60.         P3M1 = 0;! m, ~4 o( }# U
  61.         P3 = 0xFF;# f% G6 M! k1 X4 m$ R  a! t' G
  62. }
      S4 l( H9 m. E' v

  63. + A7 C% M, Q: S4 q( y6 Q6 y
  64. static void Interrupt_Init(){6 l$ m: s0 l5 n- m. P0 @# s
  65.         // INT0中断(CLK)触发类型为上升沿+下降沿
    9 l2 |) I9 `5 ^% a( |1 r
  66.         IT0 = 0;! g  A5 L% M* i
  67.         // 允许INT0中断/ }% {$ g* W9 {3 `# R: g! \, [
  68.         EX0 = 1;
    , {, |8 t0 m1 L
  69.         // INT1中断(LATCH)触发类型为上升沿+下降沿% x+ o% c1 M( k
  70.         IT1 = 0;1 Z0 G3 V/ i# |+ K
  71.         // 允许INT1中断. H1 _& I, ]7 b7 k, t5 S6 ~
  72.         EX1 = 1;
    ; g' @, L8 W3 s! g4 c
  73.         // 开启全局中断
    9 x# X  Q* R  ]4 G) n' T$ v
  74.         EA = 1;
    ( W; f# G% Z7 q5 I/ @
  75. }5 [8 {6 _' _0 n& N+ d+ R6 g7 D
  76. ' c: ~/ J9 ?$ a
  77. static void INT0_Isr() interrupt 0{
    8 f4 @, x/ q6 L% r  x
  78.         // 只有已经成功锁存才允许CLK移位; `6 ~$ S  A  L
  79.         if(isReady == 0)( j+ E7 h8 d, Q+ V* U5 s$ T
  80.                 return;
    & E7 I) M( b6 `
  81.         // 读当前引脚电平,如果是低电平则说明是下降沿,此时直接忽略该中断
    + k4 d6 ?* K; L9 b8 ?& Q
  82.         if(CLK == 0)0 r. u/ G6 l5 m% P1 E. y
  83.                 return;  I. Y9 m( `1 g* @
  84.         // CLK上升沿到来的时候,取锁存值的下一位输出5 }! P0 }. K6 x/ t6 s
  85.         idx++;
    0 P9 I  d9 N. H0 Z( S
  86.         DATA = key & mask[idx];
    - }$ P3 `! {2 t$ E
  87.         // 如果已经完成7次移位,则一轮读取完成
    - B  n' F$ f$ {
  88.         if(idx >= 7)) {5 ]* K' P2 T- q3 Y% y( C
  89.                 isReady = 0;2 E! W, q: v4 ?! }& r; t
  90. }
    . W5 |9 ?1 G! R+ ~: ^  J8 X, L
  91.   }3 R  d7 u" E/ E
  92. static void INT1_Isr() interrupt 2{
    $ Y2 s5 C/ Z2 a
  93.         // 读当前引脚电平,如果是低电平则说明是下降沿,此时直接忽略该中断
    4 C5 B+ U6 @1 ]! }* y; [$ Z8 J( `7 @. m
  94.         if(LATCH == 0)
    8 o2 v, V+ D; F+ O
  95.                 return;3 F* u; t8 v+ v9 k
  96.         // 当LATCH上升沿到来的时候,锁存所有按键状态,同时把键值A输出到DATA
    % H) m4 W) ?5 l* V7 |/ X
  97.         key = bufReady;' R5 g3 q3 U- A8 i# |( m
  98.         DATA = key & 0x80;//mask[0];        // 为了加速运算,直接取表中的值而不是读表1 r% A# }$ [- G; S0 `5 E6 Z, U
  99.         idx = 0;
    2 {% E1 ?. V) J( ?0 d
  100.         // 允许CLK进行移位
    # i2 u6 I. ~- `7 z! O8 ^+ S# m
  101.         isReady = 1;
    / m6 {2 K: ]$ w
  102. }. Y2 u% Y5 J1 c' E& L* o

  103. & ^- U# R$ N, j' @4 m5 Z
  104. void main(){
      M! |/ f# k0 W& U7 K& l% h
  105.         GPIO_Init();
    1 D* f" A0 k; H
  106.         Interrupt_Init();6 _' y4 b! P1 }' E
  107.        
    " q5 P' U, N1 y  @+ c
  108.         while(1){( _; Z0 ~: Q* F+ _. H% b
  109.                 //PCON |= 0x01;        // 进入省电模式
    2 V, p9 Y9 B; h
  110.                 //_nop_();6 J3 C! r8 E6 E+ @( P/ ^4 Y* p
  111.                 //_nop_();' l; y& o' H+ J, w2 J
  112.                 //_nop_();/ u: h( Q6 r! X! `4 d$ O& Y% ]" ~  B
  113.                 //_nop_();
    2 n% v, D3 I( t7 l, i3 _
  114.                 buf = ~((P1 & 0x3F) | ((P5 << 2) & 0xC0));
    ' S! G1 k/ N9 E1 s
  115.                 bufReady = buf;
    + t) I' [% }, j* I
  116.         }6 Q  }0 n) e. y; i/ H2 j( O
  117. }
    + X/ F3 K4 F4 ^* \- `2 w0 W
复制代码
0 O* j, ]! T  g+ W# k
硬件参数配置无特殊要求,晶振频率选择12M即可。
5 h8 h6 }1 T: R: K( o4 |, u0 F# u& i! ~- b0 |+ F3 ?% b5 j- D
这是编译好的固件。

本帖子中包含更多资源

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

×

评分

参与人数 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
8 a" {; |7 ?  C: ~3 i不错的设计,想问一下楼主,FC的15针公头怎么解决?普通的公头太短了,插不进去FC的扩展接口。 ...

8 P3 ~0 m# z# `% Z8 C8 H坛友的改造方案
回复

使用道具 举报

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

使用道具 举报

发表于 2019-5-25 12:07:18 | 显示全部楼层
精彩,楼主动手强,也写得很详细。6 p" c$ l) h$ a9 b: b- E
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
! ^" W2 t/ w9 q精彩,楼主动手强,也写得很详细。9 j6 N8 d8 s! X8 F# w
2.4G方案是目前无线的最低延迟吗?
8 X/ G+ ]+ j6 c& z
我没用过其他无线手柄,所以实在不知道我自己做的这个手柄到底是不是最低延迟。) p  b! V- N- x
不过根据网上的说法,延迟高低主要是由通信协议的复杂程度,以及数据传输速率决定的。这个模块虽然是2.4G无线模块,但由于协议很简单,所以延迟比较低。
# H  l0 E0 k( Z. d2 M我用这个手柄玩一些ACT游戏,比如超级马里奥、忍者龙剑传、热血系列,完全感觉不到延迟,和游戏机自带的手柄没有任何区别。唯一的区别就是这个手柄是用火花山寨手柄改造的,外壳是垃圾回收塑料,粗糙+脆弱,导电橡胶弹性不佳,手感不是一般的差。1 e) U! o# l, Y1 ?5 \4 [
我手里还有十几张板子,等我有空了我再做一套,到时候买一个好一点的手柄改造。
回复

使用道具 举报

 楼主| 发表于 2019-5-29 16:56:14 | 显示全部楼层
ppad 发表于 2019-5-28 17:27% f" D5 I. C  a0 L! t: d
给技术帝赞一个,有半成品发布吗,自己焊接改造就可以,编程实在不会啊 ...

- A3 q1 ?. o+ x5 M/ A! t4 B% |很可惜,我手里没有多余的单片机了,LDO也找不到了,锂电池以及充电模块更是没有了。反正就是该用到的元件基本都没了,所以没法发布半成品。# F% I5 b0 E' m( m2 X- w
两个板子倒是有十几张剩余。
2 _) V& ~7 ^: i你要是有USB转TTL串口板,完全可以自己买这两种单片机,然后我给你编译好的固件,你自己用串口板下载到单片机里面就行了。两个2.4G无线模块也得通过串口板用AT命令设置参数,不过好在我在设计电路的时候就已经预留好了串口,可以直接在线下载和在线设置参数。总的来说并不麻烦。
回复

使用道具 举报

 楼主| 发表于 2019-5-29 17:00:34 | 显示全部楼层
孙大师 发表于 2019-5-28 18:55
7 {: o4 u0 g9 `! M! U非常好,楼主是技术帝,到目前我都还没开发fc的无线套件,等空了,开发一套套件,等玩家自己组装。 ...

1 ?6 _* ?: @/ E! _/ z4 }) o能得到孙大师的赞誉,不胜荣幸!( g" s' w0 G- w  y# U% N) ]+ W* Q
不如开发一个多功能手柄,比如用SFC手柄改造,L/R键配合其他组合键可以用来切换2P~4P、调节连发速度、软重启等各种功能。接收端插到15PIN扩展口。
回复

使用道具 举报

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

本版积分规则

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

GMT+8, 2026-9-20 23:28 , Processed in 0.100912 second(s), 15 queries .

Powered by Discuz! X3.5

© 2001-2025 Discuz! Team.

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