找回密码
 注册

QQ登录

只需一步,快速开始

查看: 24856|回复: 32

自制FC无线手柄

  [复制链接]
发表于 2019-5-22 14:16:45 | 显示全部楼层 |阅读模式
本帖最后由 雷精灵2046 于 2019-6-14 09:28 编辑
2 x  i, a" t# I7 b
: s6 F( Y! y1 ~! N没有用复杂的分立元件搭建发射接收电路,直接用的现成的2.4G无线模块jdy-40。2 g. C( l2 L0 B% b/ q
$ s6 Z+ `; l  y3 X6 c
( D* b4 o: f4 z7 ?( w
发射端靠3.7V锂电池供电,用了一片SOP8封装的STC单片机,负责产生连发脉冲,同时负责检测电池电量,电压低于3V左右的时候触发低压中断,低压指示LED就会亮起来告知该充电了。平时发射模块和单片机均处于睡眠状态,有按键按下才会唤醒,从而实现省电。实测睡眠状态下整机电流约1~2uA。板子洗了一下稍微干净了一点。因为对于微功耗设备来说,焊接残余的助焊剂可能会增加漏电流。; f, B( r$ f# d2 Q
8 \" k' X3 `7 Z- ^$ w
买了一个火花的FC山寨手柄,去掉里面的牛屎板子,并修正一下塑料挡板,把锂电池和充电模块装进去。
( \! C: J( N" V$ b4 T$ X* ~5 P为了减少体积,充电模块裁剪得十分小,并且更换了充电电阻使之适应这个小小的锂电池。这么小容量的电池,也不需要多么大的充电电流是吧?% k: Z8 m5 W% W
然后统统用热熔胶粘上。充电电流比较小,所以发热很少,不会熔化热熔胶。/ l, l6 D4 N. |8 M. E$ ]: n$ N
5 q$ u, R4 a+ L  Q5 T' m

! X4 J! q0 M. C4 p# V8 t- Y
% b$ S" b' b4 V5 R0 j最后把按键、导电橡胶和电路板装上去。
# ^, d3 F4 _2 W, Y2 X2 M4 Y6 ~# \精心裁剪了电路板,正好扣上,不会阻碍其他元件,也不会影响后盖和拧螺丝。
$ ?, x2 v, M5 V. I6 j3 J' c6 q" G$ {  o# U, ^
; b, H! N4 ?4 U( |8 o
完工!
/ q, X& M& O; r9 K
1 h( e8 B- J! ^4 U" a/ L( ~4 k" |+ X( q- p. j* O: S4 V. p1 l
这是充电的MicroUSB插座。旁边的小孔用于透出低压报警LED的光线。
% c1 g5 P4 V  c* m! R1 P' u' [
' [$ B. o9 ^2 p) U
# R0 E+ h; o* T接收端用一片DIP16封装的STC单片机模拟CD4021。为啥要用单片机模拟而不是直接用CD4021?因为jdy-40模块接收端在有按键按下的时候输出高电平,无按键按下输出低电平,和普通手柄正好相反。当然我也可以用两片74HC00或者74HC04之类的逻辑门进行反相,但那就增加了芯片的数量。对于FC手柄这种工作频率并不高的设备来说,STC单片机完全可以胜任模拟工作。/ J, J6 ~' I# x! d$ Y, Z
" g  D7 |: [7 Y" _

+ N0 I9 V4 b: I+ `. I! a$ y, E( [9 W7 f* c4 p
电路设计有点小小的错误,所以有几根飞线。原本设计使用低压差LDO是XC6206,结果在做这个接收模块的时候,买的LDO居然找不到了!无奈只好用了AMS1117。幸好对于接收模块来说是5V降到3.3V,1117可以胜任。要是发射端手柄的话,3.7V降到3.3V,那就非得用6206不可了。
; N$ B8 l* V& _9 s; E# T( c0 ~( |4 k( _- \
实测十分灵敏,延迟极小几乎感觉不出来。可惜这山寨手柄的手感并不佳,尤其是方向键,软塌塌的。看来我得买个剪线手柄改装。
# M3 P+ a7 |6 k# H0 @9 W, B+ v, p1 p7 G# G3 }
这是电路图,有兴趣的朋友可以参考。5 }) i- F# y! m6 U2 G/ u5 M

* O0 U  @* y$ C. C
/ j- l' L' n- G3 S+ P我信奉开源主义,十分痛恨把技术藏着掖着。好东西大家分享嘛!所以两个单片机的源代码大公开!, m7 E, ?5 t' |$ C3 k* e# W
编译器:Keil 51。
% K! V/ Y. m; T' m
: ^; t; ]3 l- F, I# M% J发射端:
% c9 q% O+ I1 j3 K! h
  1. #include <INTRINS.H>* \4 l' q8 w! X  t" s
  2. #include "STC15W.h"
    + Y/ K* ]1 ^; q  c  \
  3. # v1 V, t2 c3 L

  4. ( V& N. T1 Q/ H. M0 w8 L! Y, x
  5. /*  o8 ]% ]/ [" ?  y3 Q
  6. --------------------------1 C; `  M; B+ g8 b+ g" Z$ U
  7. |1 (OUT)        \__/   (INT1) 8|
    5 A/ E1 d6 Z/ Y
  8. |                                                   |
    ( V, O9 s  C# g# i. n
  9. |2 (VCC)                   (INT0) 7|. u8 i) J7 k0 f2 O/ u( g4 i
  10. |                 STC15W204S                   |) O8 ?! H- S: u2 ^$ g: ?9 I
  11. |3 (LED)                         (TXD) 6|3 D, z" y7 q+ D1 ~
  12. |                                                   |/ a; t7 k; m2 ~4 @" Z( `
  13. |4 (GND)                         (RXD) 5|
    " M+ [: m: c3 `1 `5 I! P
  14. --------------------------. S! a* P, a+ k2 |2 [

  15. 8 P; z3 R+ p+ f3 x5 m7 S7 A2 w
  16. LED ---|<|---[===]--- VCC* H6 S8 O) r. n+ m' x1 I: m* Q% h
  17.            Red          330
    ( \( [" F5 N9 a9 B

  18. ( a7 ~* d# {/ {: d6 G* `4 N; A
  19. Fosc = 6MHz6 O  A+ q, y% I" D2 D! I* i
  20. */2 {1 }% e, d: M* U: C- b; T( r8 i

  21. / M1 C/ k7 [& f3 p8 m% f

  22. " z# T; ^0 ]9 e) N& |
  23. // 矩形波输出脚
    + k, T7 Y4 j7 _/ ?9 o
  24. sbit OUT = P5^4;
    # P2 T! M' q- w1 H
  25. // 低压指示灯引脚# a) }, U' R* R
  26. sbit LED = P5^5;
    ( W$ r, [6 X& i: V: D! Y. l3 X# Z  [
  27. 5 r9 Z# J9 h$ ?0 C1 _$ x
  28. // 停机标志位, l8 @: w( B' ?& C8 P0 Q  t% N
  29. bit isReadyToHalt = 0;5 N# x6 }, B& w9 l
  30. ' c7 b8 s, B& K8 [, a* H& |9 L* E8 G
  31. // 矩形波次数累计* F' X: d9 }  G
  32. static volatile unsigned char count = 0;5 f: U1 ?4 ~( [0 q3 o

  33. ( H  A  |( X- K4 Z" U: H9 U

  34. 3 C; R$ w: p) F/ ]2 c4 e
  35. static void GPIO_Init(){
    2 O: q$ I, S$ `: H4 ]* X& L" d
  36.         // P3口设置为准双向,默认靠内部弱上拉输出高电平* ?4 ?8 E+ C  d- _0 \6 C8 b
  37.         P3M0 = 0;
    5 G( \5 j1 [2 a8 [" U
  38.         P3M1 = 0;( S' ?% N( L# b1 U* w% b3 l
  39.         P3 = 0xFF;+ H+ y, [$ Q4 k# G" M+ D
  40.         // P5口设置为准双向,默认靠内部弱上拉输出高电平
    ) r' M/ R7 Q8 K4 t2 i) c
  41.         P5M0 = 0;
      l, e! }, Y9 |4 `' q2 y
  42.         P5M1 = 0;! I" f! g: q# b( X3 c; j9 \
  43.         P5 = 0xFF;
    / {. v, f! U6 O# B/ ]
  44. }: E0 V6 @- f  t
  45. + R' B. C" Y- H# Z3 a
  46. static void Timer0_Init(){
    ( X% k% X9 j- S5 b' ]8 N- d+ \
  47.         // 16毫秒@6.000MHz
    5 W4 h& l; \) f
  48.         AUXR &= 0x7F;        // 定时器时钟12T模式" a2 p9 A  s! }0 V; G4 N
  49.         TMOD &= 0xF0;        // 设置定时器模式  S3 D6 ^$ Y4 D
  50.         TL0 = 0xC0;                // 设置定时初值3 x* s* t' k: I7 a% X  Q+ H
  51.         TH0 = 0xE0;                // 设置定时初值2 }; x& n% g* P, G- D9 f
  52.         TF0 = 0;                // 清除TF0标志: A! n' K, b$ B0 K& ~; F* J
  53.         TR0 = 1;                // 定时器0开始计时
    1 e6 j& k: X6 P
  54. }
    4 T( \6 d) K% [7 B$ s! i

  55. 1 Q7 ~  k9 l5 u5 F: w9 z" ~" b
  56. static void Interrupt_Init(){5 i( \" G1 A, _- K4 N
  57.         // INT0中断触发类型为下降沿触发
    * \0 j5 L1 \- P2 `) M
  58.         IT0 = 1;
    7 U# P% u% B& s* t8 u6 }  ?
  59.         // 允许INT0中断4 \6 R" f% n" F3 c
  60.         EX0 = 1;  m( X3 j: X6 a8 u0 }' ~+ M
  61.         // INT1中断触发类型为下降沿触发0 M# O/ w# F; d8 b5 I
  62.         IT1 = 1;) I' ?7 Q. g3 R9 ?1 K; a( ~; |7 Y
  63.         // 允许INT1中断8 l4 P. _5 A2 h6 q4 J" T9 V
  64.         EX1 = 1;5 y6 {6 P2 ?4 e$ }0 Z( @
  65.         // 允许定时器0中断! p  B6 I: F: v& S% @
  66.         ET0 = 1;' S1 M4 G% _- [) Y: x0 ~0 m$ f
  67.         // 允许全局中断& J* D. \! t$ Y1 o
  68.         EA = 1;
    # E0 j: a) c' q6 |
  69. }
    ) |9 R& t# K8 [

  70. ; e  Y- _5 R6 ~% x% e$ l
  71. static void INT0_Isr() interrupt 0{8 J9 W1 i: s% \. K$ e
  72.         // 矩形波次数累计归零
    ; i/ }6 @  M& D" K/ h# x
  73.         count = 0;
    , Q6 Z6 }; u) E: q/ m
  74.         // 重开定时器0中断+ x( e2 R9 X( u& N. ~
  75.         ET0 = 1;# w0 ]. y/ Z, H7 F
  76. }
    ( Y: `& ]4 }7 T; a% U+ z) B
  77. ' [- O6 C  ?. X- Z/ P1 h8 O
  78. static void Timer0_Isr() interrupt 1{  P# n1 N* V6 k
  79.         // 输出矩形波
    + |$ R- j4 Y0 I& _4 u8 f% _
  80.         OUT = ~OUT;/ P: |  Z" Y' e& c$ ~
  81.         // 累计矩形波次数3 y$ c& n% h$ i+ a. Y5 b: T0 F
  82.         count++;# w% T$ m8 q9 P* U% V! N
  83.         // 超过250个矩形波,准备停机  l# q$ x& s1 y0 K* ~/ D
  84.         if(count > 250){& v0 q" ^) U$ T* @8 r
  85.                 count = 0;
    9 o! V" o+ I8 W2 }8 W
  86.                 isReadyToHalt = 1;2 h: T- `% n; x! E2 S
  87.         }
    + t+ L0 O" d6 E# ?& H1 z: `
  88. }+ W# S# L1 C0 T+ W
  89. " x2 [# A( |6 M" ^1 a! Z" z
  90. static void INT1_Isr() interrupt 2{# s* m( t2 [2 G8 n( N3 l& T6 e% t( h
  91.         // 矩形波次数累计归零
    9 [2 t/ d4 w8 S
  92.         count = 0;. m5 l( |- X. m' D
  93.         // 重开定时器0中断. k. H5 Z% z9 m0 [: K
  94.         ET0 = 1;4 B2 B$ ]# q; o! b6 d
  95. }
    : F8 m% N& _; x1 T

  96. 5 u+ F3 b! M" Y

  97. ) ~1 s- }* s0 t/ w1 L+ l
  98. void main(){% {( i5 n% ^' r% r6 e; V7 }
  99.         // 初始化P3和P5口
    3 U- [7 l6 j; o2 P3 K
  100.         GPIO_Init();
    0 X" x' i* d5 I
  101.         // 初始化定时器0/ V' V! P; d6 z5 B& i
  102.         Timer0_Init();0 _. X8 b( Z* d9 g: w/ i
  103.         // 初始化中断
    ( D: x( W$ O5 [9 n  H1 S
  104.         Interrupt_Init();6 P; [: t- N9 a8 J! L8 x
  105.         6 E5 S- H! J% p2 ^% H1 o
  106.         while(1){
    ; [& y3 \6 a2 z; `7 H8 I
  107.                 // 检测电量
    7 }1 H3 @9 k' H" N5 }3 f8 T
  108.                 if(PCON & (1 << 5)){, z* Z7 S; S) |) w& K
  109.                         // 如果电量低,低压指示灯亮
    # A* v2 i9 l8 \+ e, M
  110.                         LED = 0;6 a4 E1 Z# E3 l' Q3 x
  111.                         // 清电量检测硬件标志位
      B$ S# p' ~" M3 t5 e
  112.                         PCON &= ~(1 << 5);& M; s/ e/ `% I2 \5 Q
  113.                 }else{) D2 Z0 d7 w- y. l$ |& @
  114.                         // 电量正常,低压指示灯灭
    & z9 X: U- m7 l8 e( T# ?
  115.                         LED = 1;
    6 F' M; Y# _" C, Z8 _
  116.                 }$ R1 @( s: O1 v4 \3 `4 ?5 b
  117. : C2 E! C5 P1 o* w! X8 X4 s' O
  118.                 // 检测到停机标志  Z" @. W. A, o. w' E
  119.                 if(isReadyToHalt == 1){
    : t7 E8 `' o  z0 x
  120.                         // 暂时关闭定时器0中断  a! w: e2 v. e4 j' U
  121.                         ET0 = 0;5 P! ~: V, {4 L. t# Q# o, {0 u# E; t; r
  122.                         // 停机之前先把矩形波输出脚置低电平,以方便INT0和INT1唤醒CPU
    : m' A. W2 H$ I% O+ T
  123.                         OUT = 0;/ X5 m/ g: L3 o9 }. z% r9 J
  124.                         // 停机之前先把低压指示灯灭掉,以省电
    0 i" A* E+ N" m9 i
  125.                         LED = 1;
    ) K* b; y* @" S. k; T
  126.                         // 进入停机模式
    3 K/ }! [! k& I
  127.                         PCON |= 0x02;( \, T- [7 P- Z/ u0 q1 N$ Y
  128.                         _nop_();; G% x7 K4 {& ^  l
  129.                         _nop_();6 D: l4 T( p/ D3 K1 X3 p2 T2 a5 G5 ~
  130.                         _nop_();7 E  Z2 k- s% O+ H- n2 P: Q  g
  131.                         _nop_();
    6 w; A5 }5 W) |2 \3 E; Q& N
  132.                         // 唤醒,清标志位
    0 @- K) X) k- f9 p. r" v/ l4 F
  133.                         isReadyToHalt = 0;
    / C4 D  D, p' a/ v/ _6 u. I( Y
  134.                         // 重开定时器0中断
    + M6 U) [" @' K8 Q+ z! z
  135.                         ET0 = 1;
    , B: j4 G: D/ w" K
  136.                 }
    ) i5 j3 i4 e4 H0 r
  137.         }5 k1 e4 W# v- b( O) j$ T! A, c
  138. }& F, m# ?- {7 Y- q, j+ T
复制代码

0 D4 C5 T% ^( h硬件参数配置:1 Z" A) b- B( T4 k3 L& Y' R
: Z  S" b6 o( _9 U! s1 O- G* n5 x8 X

- x" r7 i& K0 A7 f' w. S接收端:1 i# \2 O5 C9 t( R  Q. R
  1. #include <INTRINS.H>! _3 c$ G/ z% P& [+ T( D' y
  2. #include "STC15W.h"
      Z! D; v( d8 J4 _
  3. 5 F0 I" a6 `' U/ @" h+ ?" a

  4. ( x: R5 g/ G9 @9 U8 {
  5. /*3 r% l4 [& A& ]
  6. , [) J4 ?( X% u$ b4 ]0 G
  7. *---------------------------*
    0 _/ q9 Z" H. T+ J* a# s
  8. |1 (GPIO2)         \__/  (GPIO1)16|
    3 a) G9 M, u2 [8 u5 ^3 E6 m
  9. |                                                        |
    / ~; M  I1 P: j2 D2 q' p
  10. |2 (GPIO3)                   (GPIO0)15|
    $ T8 Y' b8 w& f4 j% p! d
  11. |                                                        |
    , v) M- {/ p) g
  12. |3 (GPIO4)                                  14|
    - p% }  d5 P# s
  13. |                                                        |
    : B& a0 u3 X1 o
  14. |4 (GPIO5)                        (DATA)13|
    + S# M1 e7 Y2 `  ~1 g, W
  15. |                  STC15W204S                |! c. r5 ]. N  M
  16. |5 (GPIO6)                   (LATCH)12|
    / X9 A! O4 g: {! J: f, }* b
  17. |                                                        |
    ; R/ S# d' I' @# K" b5 F! E: \
  18. |6 (VCC)                         (CLK)11|, ]8 r. ]7 n4 n: }4 z& \4 t
  19. |                                                          |8 A$ J8 a& P6 `8 d9 w, x& H' I
  20. |7 (GPIO7)                         (TXD)10|
    0 e2 R2 n* W  Z$ g( g! e
  21. |                                                        |) X: e1 g- B; B- n5 t
  22. |8 (GND)                         (RXD) 9|
    , p/ j  i% E; V5 T( w
  23. *---------------------------*7 H+ y, Y7 Z+ O4 ]( J, B- @0 h+ x
  24. Fosc = 12MHz# i! Q% h+ G+ h: h4 R3 b

  25. 6 O5 c. M/ B( l$ A, D9 c& t
  26. P1.0 -> 上  m( q1 ]3 m, _8 }+ j! c
  27. P1.1 -> 左6 O( \! Y- Z+ w2 @. S4 z
  28. P1.2 -> 下
    9 Y6 \' N% ?, L1 a/ b/ [
  29. P1.3 -> 右
    ! a3 L9 o  G4 R  w
  30. P1.4 -> SEL' E7 z5 {. \. O7 u. W: Q
  31. P1.5 -> STA
    & G  x3 ^. p6 r% @- ^
  32. P5.4 -> B
    * l7 p/ @2 y3 v6 u; t! w7 R
  33. P5.5 -> A- l' ]) b0 j0 G$ G$ e3 F' k6 _

  34. 4 k8 a, n+ ]' O
  35. */
    # q: p0 B" {# p- W3 @6 M2 P

  36. 6 Q* O& Q0 t4 z: v! J9 W
  37. ! ?: t6 O* J9 m$ E6 ?% e
  38. sbit CLK        = P3^2;3 c$ M- I5 X1 k  Y
  39. sbit LATCH        = P3^3;/ V% I+ A( \; f, A
  40. sbit DATA        = P3^6;
    " F; y" `1 T: }' q' p

  41. ) e/ m6 M! T! n5 S: D2 Y- ?
  42. bit isReady = 0;0 j" l- p" Y/ j( Q5 X2 L% ?; W
  43. static unsigned char key = 0;$ F6 i: f$ x* g4 i& K6 u# ?
  44. static unsigned char buf = 0;        // 双缓冲。这个缓冲区保存从P1和P5组合而来的键值
      ^9 M  B5 s6 b1 o/ p8 w
  45. static unsigned char bufReady = 0;        // 双缓冲。这个缓冲区保存上面那个缓冲区的备份
    / ^' ?. h- M1 f
  46. static const unsigned char data mask[] = {0x80, 0x40, 0x10, 0x20, 0x01, 0x04, 0x02, 0x08};        // A B SELECT START UP DOWN LEFT RIGHT。为提升速度,这个表放到RAM中
    6 v% y3 V7 T# ?0 l6 l6 B: D0 v0 X
  47. static unsigned char idx = 0;0 g5 G/ ~: n7 V* g, r

  48. . T' Y9 K" m0 o% p( H6 z; T

  49. 0 \  S5 w! E( L' p6 ^2 A+ `5 g
  50. static void GPIO_Init(){
    8 }8 \6 |9 s' G$ y) ^  e
  51.         // P1口和P5口用于接收并行信号,全部初始化为准双向,依靠内部弱上拉输出高电平/ N# Y* \" U, f: e6 z
  52.         P1M0 = 0;
    ; U4 M$ q; _# C# D6 r
  53.         P1M1 = 0;
    4 n3 I% b  b# {2 }+ B( T$ n4 {
  54.         P1= 0xFF;+ _0 p* `3 O$ E0 C4 ~. d
  55.         P5M0 = 0;: d9 i3 w$ Y, g$ L8 z. Q
  56.         P5M1 = 0;' G) X8 N; H0 J% D1 v  {; p7 M: M
  57.         P5= 0xFF;1 b& Q. x2 Q: g- p% _- f
  58.         // P3口初始化为准双向# S* d, }. }& V$ _8 I; c
  59.         P3M0 = 0;
    ; y( u. v4 m5 ]) f3 [# {
  60.         P3M1 = 0;
      ^% D1 p# N" j4 [8 \2 I
  61.         P3 = 0xFF;
    - F' ]1 c% N6 ]7 Q1 z
  62. }. i' _$ s6 y5 c2 g
  63. % c, Z) Y; H& S1 i5 S
  64. static void Interrupt_Init(){' X* c8 d! {4 j; y& T' x) I
  65.         // INT0中断(CLK)触发类型为上升沿+下降沿. Y5 @0 H& n+ R- H% H
  66.         IT0 = 0;' `& G1 ]3 u2 x) c. B
  67.         // 允许INT0中断  S* U6 ^+ s* F9 B: z0 Z
  68.         EX0 = 1;. C3 C& \" G& I9 c
  69.         // INT1中断(LATCH)触发类型为上升沿+下降沿* t8 O7 O. s" |
  70.         IT1 = 0;, n- l, r. [1 O0 P0 e# A. l4 U; F
  71.         // 允许INT1中断
    . V. V( B" \$ t8 m6 n1 @$ x6 D8 I
  72.         EX1 = 1;
    " p  f& M& F- D9 f1 X4 A& Q) Q5 K
  73.         // 开启全局中断1 f- b' [& @, @; Y
  74.         EA = 1;
    1 y4 B5 Z1 D# `8 |1 ^3 N0 C$ E
  75. }7 b: w3 Y$ e' n/ P. l- r: m) F

  76. * B# z1 G: ?7 a$ X
  77. static void INT0_Isr() interrupt 0{
    7 Q7 n$ `3 w" _7 I+ ^/ s/ K
  78.         // 只有已经成功锁存才允许CLK移位/ f% @; \) i; r
  79.         if(isReady == 0)
      F* U  x+ {8 Z5 o/ O8 A: M
  80.                 return;6 A6 w8 u, O% u4 B' @2 d
  81.         // 读当前引脚电平,如果是低电平则说明是下降沿,此时直接忽略该中断3 ^. Z. w5 \2 t3 d
  82.         if(CLK == 0)
    # \# o& d) f# _6 {2 c
  83.                 return;
    " `! k* D3 d4 C4 N7 d, x
  84.         // CLK上升沿到来的时候,取锁存值的下一位输出6 m& V8 i, ~9 Q( F, [3 m% x
  85.         idx++;9 n% _* @" B8 p% X6 ^
  86.         DATA = key & mask[idx];% S) G8 P3 }9 i5 Z; b: h
  87.         // 如果已经完成7次移位,则一轮读取完成
    ( J9 F0 g6 u5 F) z' `$ z
  88.         if(idx >= 7), d( L* T3 R5 n% q! C; k
  89.                 isReady = 0;' v- T, c3 B' g
  90. }
    8 R: T# Q/ M# E
  91. ; e) n7 F7 |) C0 L$ e
  92. static void INT1_Isr() interrupt 2{! N$ n! p7 u; ^
  93.         // 读当前引脚电平,如果是低电平则说明是下降沿,此时直接忽略该中断0 z( t& X  K, G: t4 T
  94.         if(LATCH == 0)
      x, |0 E2 C1 i( _+ K' G
  95.                 return;/ ?3 r5 k! ^* w) u0 e
  96.         // 当LATCH上升沿到来的时候,锁存所有按键状态,同时把键值A输出到DATA
    - B1 A7 ~3 k) z' d' o) Y
  97.         key = bufReady;; u2 n! G" H" u1 m  h
  98.         DATA = key & 0x80;//mask[0];        // 为了加速运算,直接取表中的值而不是读表
    % E, F2 b2 H' L& D" o
  99.         idx = 0;
    7 Y/ ~3 n& ~6 b8 ]: K
  100.         // 允许CLK进行移位) G1 P8 d; {$ S
  101.         isReady = 1;. s. q5 z" h/ c9 J0 o4 v
  102. }
    0 @8 m) u7 f" m: O5 L

  103. 8 p7 R; n8 o) F8 ~
  104. void main(){
    1 ?+ \% [2 M2 x
  105.         GPIO_Init();7 z  k( v- l3 I+ F$ R
  106.         Interrupt_Init();( c$ u+ ~! f6 M
  107.        
    , z. r6 }* d9 {( H& S4 f; }
  108.         while(1){( g2 w* y( ?4 T1 d
  109.                 //PCON |= 0x01;        // 进入省电模式0 z& u6 T! J8 i2 z' R3 L
  110.                 //_nop_();' f+ s: R$ Z! {( x- Q( K  \! M
  111.                 //_nop_();" k: L7 K8 E7 |+ @5 U) @
  112.                 //_nop_();
    & y$ `# }  s! A3 X% H* g
  113.                 //_nop_();
    ; ], C8 s$ A& |5 i: Z. h9 \
  114.                 buf = ~((P1 & 0x3F) | ((P5 << 2) & 0xC0));
    . s7 m( Z" N) C, o- M8 ]% u& b
  115.                 bufReady = buf;
    ( _/ T- r2 b5 a" ?
  116.         }
    / A3 U+ H+ v! S9 s, K* z* f
  117. }  [# i; c9 S. |, J  [
复制代码
( E% d, T6 {" k1 b+ W7 s8 d
硬件参数配置无特殊要求,晶振频率选择12M即可。
9 ~/ S: p  L. T$ l3 H# o
/ S5 p4 G7 V: ^& U5 q. 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. |* r" Q8 u4 n4 a8 X
不错的设计,想问一下楼主,FC的15针公头怎么解决?普通的公头太短了,插不进去FC的扩展接口。 ...
/ I  G% u* U3 i. R
坛友的改造方案
回复

使用道具 举报

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

使用道具 举报

发表于 2019-5-25 12:07:18 | 显示全部楼层
精彩,楼主动手强,也写得很详细。
# O  g- D# R$ a2.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:074 u% Y/ d) {4 E8 I3 n) S
精彩,楼主动手强,也写得很详细。; N+ }5 Y! [$ h
2.4G方案是目前无线的最低延迟吗?
3 a' E" R) g" o
我没用过其他无线手柄,所以实在不知道我自己做的这个手柄到底是不是最低延迟。
; x: l, l2 y: l' M! v* R+ G# o: g不过根据网上的说法,延迟高低主要是由通信协议的复杂程度,以及数据传输速率决定的。这个模块虽然是2.4G无线模块,但由于协议很简单,所以延迟比较低。. a4 y0 u0 T& b; F6 K
我用这个手柄玩一些ACT游戏,比如超级马里奥、忍者龙剑传、热血系列,完全感觉不到延迟,和游戏机自带的手柄没有任何区别。唯一的区别就是这个手柄是用火花山寨手柄改造的,外壳是垃圾回收塑料,粗糙+脆弱,导电橡胶弹性不佳,手感不是一般的差。
% f7 h5 {. |4 ~1 Y0 {8 k" j我手里还有十几张板子,等我有空了我再做一套,到时候买一个好一点的手柄改造。
回复

使用道具 举报

 楼主| 发表于 2019-5-29 16:56:14 | 显示全部楼层
ppad 发表于 2019-5-28 17:27
: k! I  g: g- `/ L  C& L+ m9 O# h给技术帝赞一个,有半成品发布吗,自己焊接改造就可以,编程实在不会啊 ...
2 O: ?2 v* G1 e$ V) e
很可惜,我手里没有多余的单片机了,LDO也找不到了,锂电池以及充电模块更是没有了。反正就是该用到的元件基本都没了,所以没法发布半成品。
. j6 [4 N9 q( T$ f( f  u两个板子倒是有十几张剩余。* r- ~" N9 j  `& ^  n  z$ E; e
你要是有USB转TTL串口板,完全可以自己买这两种单片机,然后我给你编译好的固件,你自己用串口板下载到单片机里面就行了。两个2.4G无线模块也得通过串口板用AT命令设置参数,不过好在我在设计电路的时候就已经预留好了串口,可以直接在线下载和在线设置参数。总的来说并不麻烦。
回复

使用道具 举报

 楼主| 发表于 2019-5-29 17:00:34 | 显示全部楼层
孙大师 发表于 2019-5-28 18:551 p5 t# H/ N1 }+ |5 r
非常好,楼主是技术帝,到目前我都还没开发fc的无线套件,等空了,开发一套套件,等玩家自己组装。 ...

9 D6 }5 R) X+ U8 B+ W能得到孙大师的赞誉,不胜荣幸!
1 b' O  T3 V, H4 b不如开发一个多功能手柄,比如用SFC手柄改造,L/R键配合其他组合键可以用来切换2P~4P、调节连发速度、软重启等各种功能。接收端插到15PIN扩展口。
回复

使用道具 举报

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

本版积分规则

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

GMT+8, 2026-5-8 17:34 , Processed in 0.100225 second(s), 14 queries .

Powered by Discuz! X3.5

© 2001-2025 Discuz! Team.

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