找回密码
 注册

QQ登录

只需一步,快速开始

查看: 27461|回复: 33

自制FC无线手柄

 荐 [复制链接]
发表于 2019-5-22 14:16:45 | 显示全部楼层 |阅读模式
本帖最后由 雷精灵2046 于 2019-6-14 09:28 编辑
+ Q! |# Y* W. R& }, `  c$ B- p* r7 u  A! D) c( `
没有用复杂的分立元件搭建发射接收电路,直接用的现成的2.4G无线模块jdy-40。
, u5 G6 Y2 w* V+ g
; ~/ l7 W/ y4 U
# E' ~6 {; v, U发射端靠3.7V锂电池供电,用了一片SOP8封装的STC单片机,负责产生连发脉冲,同时负责检测电池电量,电压低于3V左右的时候触发低压中断,低压指示LED就会亮起来告知该充电了。平时发射模块和单片机均处于睡眠状态,有按键按下才会唤醒,从而实现省电。实测睡眠状态下整机电流约1~2uA。板子洗了一下稍微干净了一点。因为对于微功耗设备来说,焊接残余的助焊剂可能会增加漏电流。% L' x8 X' U& j
! k2 Q2 i" L, ?* |% A( Z# {
买了一个火花的FC山寨手柄,去掉里面的牛屎板子,并修正一下塑料挡板,把锂电池和充电模块装进去。2 j5 c# X; o. `
为了减少体积,充电模块裁剪得十分小,并且更换了充电电阻使之适应这个小小的锂电池。这么小容量的电池,也不需要多么大的充电电流是吧?& K0 O" {' b! }/ F2 ~
然后统统用热熔胶粘上。充电电流比较小,所以发热很少,不会熔化热熔胶。! {  t7 ?5 L5 C7 T' b
+ \" ?" `" a4 E4 K+ F, ^
% J: ^) J3 z0 m( L- [) q6 L
" h. ]) c3 g5 K, `4 j
最后把按键、导电橡胶和电路板装上去。# H, \, ^) \2 z* j' w# `3 }* h! Q
精心裁剪了电路板,正好扣上,不会阻碍其他元件,也不会影响后盖和拧螺丝。
9 v4 L7 H0 O2 \& [8 M- p2 a# _5 W+ g6 j% [/ a3 ^( L
& W: |+ f( j0 |, ?; V9 M/ {7 [( s
完工!
/ Q2 x- t4 @, U( F
7 K+ e' a, r) T" g
& e& Z4 k, _6 D. Z  \, C这是充电的MicroUSB插座。旁边的小孔用于透出低压报警LED的光线。  c( |" w4 i* p& F9 ^7 E2 n
' z1 q. J, ~; ]  |
/ d6 J8 O, B, ], k
接收端用一片DIP16封装的STC单片机模拟CD4021。为啥要用单片机模拟而不是直接用CD4021?因为jdy-40模块接收端在有按键按下的时候输出高电平,无按键按下输出低电平,和普通手柄正好相反。当然我也可以用两片74HC00或者74HC04之类的逻辑门进行反相,但那就增加了芯片的数量。对于FC手柄这种工作频率并不高的设备来说,STC单片机完全可以胜任模拟工作。
6 A" s3 T: {2 O3 M4 D4 R; |' q+ s0 @+ A
7 P8 Z1 O  R% H. n/ h5 c
6 ]/ o/ G7 ~( I. f5 i
电路设计有点小小的错误,所以有几根飞线。原本设计使用低压差LDO是XC6206,结果在做这个接收模块的时候,买的LDO居然找不到了!无奈只好用了AMS1117。幸好对于接收模块来说是5V降到3.3V,1117可以胜任。要是发射端手柄的话,3.7V降到3.3V,那就非得用6206不可了。5 K; {; d+ h6 D' A
! d$ H1 g+ ]! s9 O/ H0 q: u/ I/ K
实测十分灵敏,延迟极小几乎感觉不出来。可惜这山寨手柄的手感并不佳,尤其是方向键,软塌塌的。看来我得买个剪线手柄改装。
( c- a( ]4 L' k7 M8 H/ m+ f, c4 f- F8 u3 k- \5 \+ C
这是电路图,有兴趣的朋友可以参考。
* F2 L( G9 s* q  X) w* j' h. J3 k8 l4 L1 ^( T' o- t
5 d0 A$ S" d+ P
我信奉开源主义,十分痛恨把技术藏着掖着。好东西大家分享嘛!所以两个单片机的源代码大公开!
& E- q3 m" j" Q% a! Z编译器:Keil 51。3 y! [; }8 o; v

8 P3 ~# t: [) S: E, u/ D发射端:  }/ X% k6 W" }- e7 j9 F
  1. #include <INTRINS.H>$ e, D. w1 L5 r% k2 o
  2. #include "STC15W.h"
    2 m$ }1 Z7 _2 _
  3. & E# M+ v% o5 w( Z- b/ O
  4.   N& K# b4 f# U; b
  5. /*: _: s! M8 y6 K! {7 c
  6. --------------------------) P! O3 n, \- g- p$ |0 q
  7. |1 (OUT)        \__/   (INT1) 8|( Q/ g# o3 M+ a$ j1 `( U
  8. |                                                   |
    ) |* w! q: u8 U& o# c) K
  9. |2 (VCC)                   (INT0) 7|! R! d- a  ~" O+ N( h  `
  10. |                 STC15W204S                   |7 |. ?9 T. r! y5 u
  11. |3 (LED)                         (TXD) 6|
    ' o* e; y7 x' ]) |! S6 _: ]
  12. |                                                   |; S5 P3 \9 |& }) q
  13. |4 (GND)                         (RXD) 5|
    % t  t, T/ P6 G& h
  14. --------------------------
    / S+ j# z3 j8 B8 z8 ^# p" D
  15. ) i: V: B+ i* @9 N
  16. LED ---|<|---[===]--- VCC
    9 X- C2 A* y( H) z# ~
  17.            Red          3309 f0 ?) p# k3 g2 T" B
  18. * M6 p+ {5 r7 N! _6 b1 ^
  19. Fosc = 6MHz
    % K( u: r9 Z7 `0 r: i- K- P
  20. */
    " F8 ]$ f5 I& k6 P' C( t7 a9 H  D4 [" ?
  21. * L0 q5 J  w$ y' @

  22. : q  L9 C- y) m
  23. // 矩形波输出脚8 A. P4 @& ~  U! o, s
  24. sbit OUT = P5^4;
    1 D3 [  y: d- ]- ]4 c- ~
  25. // 低压指示灯引脚
      P$ C5 u4 G' x" l$ b
  26. sbit LED = P5^5;
    & ]$ `$ G7 D$ E; ^1 Q( j
  27. 5 x7 z( f" G% J1 L9 T0 O4 v0 P
  28. // 停机标志位$ ^6 v+ m$ Y3 i" p1 k8 _% V8 c
  29. bit isReadyToHalt = 0;9 j2 K5 F5 U% u5 F" ^: H  Z

  30. ' {$ `3 H) F3 l  [8 u
  31. // 矩形波次数累计
    ; ?( o- v8 \* x+ }* a1 ?. Z! G
  32. static volatile unsigned char count = 0;
    2 |- k/ ~4 W: a/ S& H8 \8 l4 a
  33. 9 F+ ^/ H. O  e; X; G4 C- L6 I( y

  34. * C6 p: q* P+ |- H
  35. static void GPIO_Init(){$ b8 R/ y$ {/ g$ {  Z, y) [% `
  36.         // P3口设置为准双向,默认靠内部弱上拉输出高电平
    6 t, k: H, @+ E. p9 G. t
  37.         P3M0 = 0;/ L7 Q: R7 \  @* F3 A) i/ ~
  38.         P3M1 = 0;
    # P- t4 o8 d1 H( f0 i
  39.         P3 = 0xFF;% R7 r- k5 k! \, [" X
  40.         // P5口设置为准双向,默认靠内部弱上拉输出高电平
    , t; c* t7 q- k2 i1 s3 ^) j! }5 U
  41.         P5M0 = 0;$ F& C/ P9 \6 n* ]4 \
  42.         P5M1 = 0;
    8 B& L8 ^7 y& k+ c5 D
  43.         P5 = 0xFF;( `" \2 S0 u2 ^) U4 k9 u5 n
  44. }
    8 g  D! n. F+ L8 j

  45. 5 j3 d" j8 J7 z/ x4 e. u
  46. static void Timer0_Init(){
    " P, P* M9 X9 d$ T" R
  47.         // 16毫秒@6.000MHz  a) L, N0 k7 @- X4 E) j+ Q# N
  48.         AUXR &= 0x7F;        // 定时器时钟12T模式
    $ j0 _6 s9 y2 K( a7 Y# o7 i+ M% C8 d3 f
  49.         TMOD &= 0xF0;        // 设置定时器模式
    . o6 c5 _. c9 @) L
  50.         TL0 = 0xC0;                // 设置定时初值
    4 A* Q+ g7 o2 y) e) D0 u
  51.         TH0 = 0xE0;                // 设置定时初值
    $ F9 B4 Y0 T- [
  52.         TF0 = 0;                // 清除TF0标志% ?% ]" X- l5 J. \2 Q' u
  53.         TR0 = 1;                // 定时器0开始计时# ?! p6 F" |5 a
  54. }2 P: {4 x" |  F& s8 g1 I
  55. , X3 W, o/ `& j5 U
  56. static void Interrupt_Init(){5 L+ U1 A2 V% R0 {
  57.         // INT0中断触发类型为下降沿触发
    $ r: D$ l: z  g8 k+ O
  58.         IT0 = 1;
    ) w& z+ C: r! i) P) i' }* ^8 [" ]
  59.         // 允许INT0中断7 \+ X5 M1 r: y% n( q# P1 n
  60.         EX0 = 1;: b$ P' L& g8 i( }# Z" [, R
  61.         // INT1中断触发类型为下降沿触发
      t6 b) c/ F0 d' I# O) ~
  62.         IT1 = 1;
    / T9 r- X) _2 j/ i* \9 y$ i8 z
  63.         // 允许INT1中断
    & L) u! X9 y4 U* U7 J( g' z+ K
  64.         EX1 = 1;
    # _3 h  M6 t9 z, y) Z. m
  65.         // 允许定时器0中断
    6 N1 D+ {, R* p5 v9 a
  66.         ET0 = 1;7 j8 X! g- P, P; j3 O2 K
  67.         // 允许全局中断+ l* p5 e' q# L
  68.         EA = 1;
    $ d6 A7 ~: T& G6 Y8 O$ G7 D
  69. }
    9 X. d- }: ^7 A5 p3 b' K3 a4 \
  70. 6 w  b+ L- s8 G; }( B. D
  71. static void INT0_Isr() interrupt 0{
    # P1 t* D) q* \3 {
  72.         // 矩形波次数累计归零' B/ T' X4 A1 z3 A! k
  73.         count = 0;
    ; W# Q* I- A" |2 ]$ H
  74.         // 重开定时器0中断
    , m( Q' R! a, s: W: K2 K' Y
  75.         ET0 = 1;6 ^0 J" B1 D5 C+ C
  76. }0 \" d9 E  _! Z# ?4 w* j
  77. $ L) C/ ~! I( ?
  78. static void Timer0_Isr() interrupt 1{/ U( c. y8 o, X3 h
  79.         // 输出矩形波
    / O; D2 X- J0 e4 x! f: A
  80.         OUT = ~OUT;
    ' W, h* S0 _& @: k, s* G' X* Y
  81.         // 累计矩形波次数. ?$ c* C4 i3 ?: Q4 z& K3 H2 I0 O
  82.         count++;
    # m- U3 L2 N' X) O' y& L
  83.         // 超过250个矩形波,准备停机
    ) ^2 t( W$ U  D1 `0 t1 X
  84.         if(count > 250){, _) G, h0 e) l+ K5 W
  85.                 count = 0;
    . ?) I$ ~8 |6 Q% }$ o. e3 L% i+ C0 j
  86.                 isReadyToHalt = 1;! Q, A: F- n. X3 m( W+ H
  87.         }
    ' z. h  D. i4 D# G+ c$ |  v4 U4 J
  88. }& q) `: h! a- Z# `! R: V

  89. ; V+ ?, N) t3 x* @2 G  H( A
  90. static void INT1_Isr() interrupt 2{: t+ u! A" q7 z! [- g! b- |  Y" v
  91.         // 矩形波次数累计归零1 I* p* O: Z# h2 a; T) V  E
  92.         count = 0;
    ( Z/ X. f2 n  B, n3 g3 b* @
  93.         // 重开定时器0中断
    4 I6 \$ j0 S* m% v
  94.         ET0 = 1;( \" G' g0 ~# f& |4 ?0 [
  95. }- o( }* {4 t% e3 r3 g
  96.   F  O) ]! ^: H. E& M

  97. . v' x9 t; G, O$ l- B1 N& G5 K7 _
  98. void main(){
    , p8 w" s7 K* f; |
  99.         // 初始化P3和P5口8 N+ M9 J4 H; G' v
  100.         GPIO_Init();$ Q9 Z8 O6 N: i
  101.         // 初始化定时器08 M! ]* }# W/ H9 d
  102.         Timer0_Init();7 T# }7 q, |7 W, u
  103.         // 初始化中断$ l2 R2 S0 c4 C) N2 z
  104.         Interrupt_Init();
    - D9 C# x  \- Q( x/ r; M
  105.         % U; c1 k2 L7 g! a- G! u0 g7 h
  106.         while(1){7 O5 n; X* c4 w* ?2 W2 H
  107.                 // 检测电量
      {. Z, z% `2 l  R
  108.                 if(PCON & (1 << 5)){' |1 M, t1 @3 q  d; I. o# h
  109.                         // 如果电量低,低压指示灯亮1 X; F! r) c9 Z, L( f
  110.                         LED = 0;) z. R& A/ b4 |& c# d( x9 b* b
  111.                         // 清电量检测硬件标志位
    / X% L- p# ^0 e( C
  112.                         PCON &= ~(1 << 5);
    * X& m' a% Q% G2 v3 D3 J
  113.                 }else{- k) ~$ c( ~0 D( h: n" P- y
  114.                         // 电量正常,低压指示灯灭# n! Z/ i# g! a! ~
  115.                         LED = 1;
    . P: A4 g& ]7 B4 }
  116.                 }1 Y; |. C2 @  O# E5 d& k" C+ ]

  117. $ K8 O! ~( {) N( X
  118.                 // 检测到停机标志" O3 T2 e* H% m* N/ [) H
  119.                 if(isReadyToHalt == 1){4 M: R9 g  i# H: n# I0 A
  120.                         // 暂时关闭定时器0中断! Q5 `+ E3 M2 }. C
  121.                         ET0 = 0;
    ' W* m1 I# }$ l: c2 k
  122.                         // 停机之前先把矩形波输出脚置低电平,以方便INT0和INT1唤醒CPU+ F  K0 F3 U. S8 p0 l5 g: f% S
  123.                         OUT = 0;3 H+ K% n5 K0 [$ m
  124.                         // 停机之前先把低压指示灯灭掉,以省电7 M! P2 y7 x, f  V4 D1 O5 M
  125.                         LED = 1;1 c) Z- Y- E+ X0 c- b. y7 L
  126.                         // 进入停机模式
    ) z: G, p+ R! i" q* s( k, w/ @) T4 e
  127.                         PCON |= 0x02;1 b; S- I2 x' J
  128.                         _nop_();7 C. c) T' F9 z$ e' w$ L( z
  129.                         _nop_();
    ; M9 m; B9 q( H; _2 y
  130.                         _nop_();
    , J$ `. e# L* ~$ \7 M5 Q/ m
  131.                         _nop_();
    / @! ?, s# O9 r3 U; Z2 {
  132.                         // 唤醒,清标志位
    0 o7 S% C% m- E0 U( k4 S
  133.                         isReadyToHalt = 0;
    1 `( l) o  J/ D6 j
  134.                         // 重开定时器0中断( u1 G3 G1 S4 |: L
  135.                         ET0 = 1;
    0 \  t9 c& M& Q$ u& [) N0 A
  136.                 }$ x4 N8 Y' n6 y# g- _, x9 ~
  137.         }' W7 d' x. N) ~) O
  138. }, {0 C# V0 J0 E/ b! t
复制代码

# P' x, L9 k3 f' v4 `4 ^$ k硬件参数配置:: v4 L: ^  W  H; W4 Y  k

" ^; A0 j: G8 v' B3 Z9 ^, H, [% \* v9 v. y# n% I# G. p
接收端:
7 R% p) a6 y" r1 z
  1. #include <INTRINS.H>
    ; m. c, P( M( G; Z4 k" V
  2. #include "STC15W.h"
    $ R8 m# n4 u$ T- O% R2 {! p3 t

  3. ; o* h' e% i: D

  4. 4 j  E7 K& d9 `' I$ ?
  5. /*4 P: g6 i- W, [

  6. 9 ?& H+ }5 l5 u
  7. *---------------------------*
    + G; M; P& R0 _/ N
  8. |1 (GPIO2)         \__/  (GPIO1)16|, }7 j" r2 s( U7 q. ^* X3 n
  9. |                                                        |
    : F$ p' ?& {+ f7 P  e
  10. |2 (GPIO3)                   (GPIO0)15|
    / b( K# _) l& h7 A6 |1 T3 H
  11. |                                                        |6 M3 I) C" r$ S$ o
  12. |3 (GPIO4)                                  14|
    3 v7 u0 P9 M: p8 R/ @
  13. |                                                        |
    - ^( y* v+ I. e) M" i6 K5 h
  14. |4 (GPIO5)                        (DATA)13|
      q+ f; h% u2 N( L" x9 u: x) r
  15. |                  STC15W204S                |
    ; V  a: T% P$ `% ?9 }% d8 S
  16. |5 (GPIO6)                   (LATCH)12|
    , d4 |' d4 T  D/ a
  17. |                                                        |
    6 o- l/ G, }% n  @- v+ X/ B7 H
  18. |6 (VCC)                         (CLK)11|
    . q' U* x& D: \2 g; \* I. Q
  19. |                                                          |6 X4 _. l. o7 ^9 [; s6 ~; j
  20. |7 (GPIO7)                         (TXD)10|. ?! H" @* F. {0 E1 S% I7 R
  21. |                                                        |
    : S& Q0 x3 L% K! E. _
  22. |8 (GND)                         (RXD) 9|
    / P4 r; u$ r8 Y6 f3 h( w5 s- @$ A
  23. *---------------------------*
    $ M5 I+ `" W  n  W# U- C# @- X
  24. Fosc = 12MHz
    3 w; `( y5 \9 T% |( h: W0 I
  25. " i5 s3 i# g# ?7 B$ u
  26. P1.0 -> 上9 h1 P. [# t. e  V" d+ J: a
  27. P1.1 -> 左
    " y& m+ ]7 e  M1 n3 n& O
  28. P1.2 -> 下
    7 t' `% f* O5 k3 n
  29. P1.3 -> 右4 [9 q# @4 v; _: D% s' M
  30. P1.4 -> SEL
    ; u0 h1 Q% d) o5 O1 h3 }& g
  31. P1.5 -> STA( w) U4 g) ~3 p! U  t) B. _  D
  32. P5.4 -> B5 o& {0 H5 \1 e6 M6 Z
  33. P5.5 -> A. H* a! Z  W# P3 T

  34. & i' J+ u( V( y. Q
  35. */3 U5 o  A& S/ j5 ?9 R( |( b7 |4 _
  36. % Q" U, l0 E0 {: w9 t) h
  37. 2 z8 A/ @" k# v$ j
  38. sbit CLK        = P3^2;
    . Z# ~4 Z% {; U- P! ]4 c& `( \
  39. sbit LATCH        = P3^3;
    * N' q6 `( E. X1 I* C
  40. sbit DATA        = P3^6;5 Y3 g- d" a( g( P" t: X

  41. 2 g9 c8 p( j' T' b1 S
  42. bit isReady = 0;  H) R, o; P& b' A  E, L
  43. static unsigned char key = 0;
    ! \0 L( e0 ?7 Q" ^8 o
  44. static unsigned char buf = 0;        // 双缓冲。这个缓冲区保存从P1和P5组合而来的键值3 |# |8 ?6 y: B' s
  45. static unsigned char bufReady = 0;        // 双缓冲。这个缓冲区保存上面那个缓冲区的备份4 E. y* g$ z" `
  46. static const unsigned char data mask[] = {0x80, 0x40, 0x10, 0x20, 0x01, 0x04, 0x02, 0x08};        // A B SELECT START UP DOWN LEFT RIGHT。为提升速度,这个表放到RAM中
    + H0 s' @% @0 e
  47. static unsigned char idx = 0;
    ' X6 O7 I. `2 ]2 K- o
  48. $ ^9 R( i! s7 M5 }1 S* M

  49. $ J; ~/ G& p8 b6 z2 |; b! s
  50. static void GPIO_Init(){& ?! y0 Z! m* |0 v. u$ E
  51.         // P1口和P5口用于接收并行信号,全部初始化为准双向,依靠内部弱上拉输出高电平' \% _8 T+ `  B8 }7 h/ g
  52.         P1M0 = 0;
    # W" e" [% O5 i
  53.         P1M1 = 0;4 ]+ q% n4 d" [; r; ~$ F9 h
  54.         P1= 0xFF;, n" N  i+ ?3 c% ~# T
  55.         P5M0 = 0;
    + _. w! W* `* d. H
  56.         P5M1 = 0;; }+ ?) M, w* c7 Q- L" }  S/ E
  57.         P5= 0xFF;
    7 R% @' p! G0 Z8 k) ^
  58.         // P3口初始化为准双向
    ( r+ ^7 j. H4 z; I
  59.         P3M0 = 0;' n) n* \- j0 @3 S/ m4 \8 m
  60.         P3M1 = 0;
    5 V4 r8 k, |+ y0 _  a% e6 y( Q
  61.         P3 = 0xFF;% H  o- n% a, j$ W
  62. }( m! a/ N" S' s0 f, z
  63. , p; M+ Y6 U" l
  64. static void Interrupt_Init(){5 G9 f1 a% x1 y# \: F1 |" I
  65.         // INT0中断(CLK)触发类型为上升沿+下降沿
    7 v! ?2 N5 i/ b/ {- W
  66.         IT0 = 0;/ t; M3 r- w4 u: \8 X6 Q' C
  67.         // 允许INT0中断1 P  m4 x6 g: U) e7 q# u9 a
  68.         EX0 = 1;
    3 r# w1 d5 {' ]# A" j
  69.         // INT1中断(LATCH)触发类型为上升沿+下降沿
    9 T' q$ m' T$ l( T4 g
  70.         IT1 = 0;( \3 Q4 W, w& A, O) e
  71.         // 允许INT1中断& n5 G% y( d, p  h  P+ W
  72.         EX1 = 1;
    . i0 W/ \" _6 q0 i6 E% y
  73.         // 开启全局中断- e' Z( |9 y; N# |6 Y; T5 t
  74.         EA = 1;: h) {% x. |5 S$ N4 E
  75. }' @% A2 W4 v" J8 G

  76. 6 {. u0 X* C) t# b4 t
  77. static void INT0_Isr() interrupt 0{
    3 ?4 r7 P( m7 u- c
  78.         // 只有已经成功锁存才允许CLK移位
    / o% D( I  o5 s. l% E' k
  79.         if(isReady == 0)
    2 I" p/ s2 h% N# s4 [. v
  80.                 return;
    % C+ T4 T; F' X; [* _7 Q% V+ ]: o
  81.         // 读当前引脚电平,如果是低电平则说明是下降沿,此时直接忽略该中断
    5 n* y! S) P! k+ ?+ z8 P# i" {6 N
  82.         if(CLK == 0)
    & q; s) a. [  Y
  83.                 return;
    6 h3 i( [. ^9 O
  84.         // CLK上升沿到来的时候,取锁存值的下一位输出, m6 F9 R. c/ r8 S
  85.         idx++;
    + `& s$ y3 ^' h- d& M) m# h4 x
  86.         DATA = key & mask[idx];
    ( ^3 f6 R) J; g! Y  Q) @2 s+ s, ]! H
  87.         // 如果已经完成7次移位,则一轮读取完成
    ' ^& [9 X3 E  U
  88.         if(idx >= 7)
    4 @3 `$ l* I6 t9 N
  89.                 isReady = 0;+ P2 m& M0 T) ^" R
  90. }
      f+ s: Z0 ]( D, d4 T4 E
  91.   t% N5 T( S% k# e8 k# O7 H
  92. static void INT1_Isr() interrupt 2{
    * Q  [  P) G2 W2 ?# U' F' x
  93.         // 读当前引脚电平,如果是低电平则说明是下降沿,此时直接忽略该中断' c/ i  ]/ N, I* w
  94.         if(LATCH == 0)  B; ~& j! t; W2 g6 x8 v9 r
  95.                 return;  F& g' y+ [, q- y- f
  96.         // 当LATCH上升沿到来的时候,锁存所有按键状态,同时把键值A输出到DATA5 z$ p7 H" e: U& J- T& [8 s
  97.         key = bufReady;
    / b8 x; m. e  {9 Q" y( V0 o7 [
  98.         DATA = key & 0x80;//mask[0];        // 为了加速运算,直接取表中的值而不是读表( D) m( j" C7 }& u" e# d9 o) w- w
  99.         idx = 0;
    . z/ T3 d9 f  n# ]
  100.         // 允许CLK进行移位* |# @% {0 g' T& Y! u9 f" |
  101.         isReady = 1;3 V/ }# X1 f1 y5 ~+ `
  102. }
    ; o/ K. B8 y  o6 u6 @7 G

  103. " [1 e* _! J5 j' `7 C  p9 M2 y! `
  104. void main(){1 c) z  U) h4 ]! B$ A$ r) _
  105.         GPIO_Init();# F( m0 V1 p- r! `, D- B
  106.         Interrupt_Init();4 t2 U. ~$ {2 v0 ?4 _
  107.         * f3 \! y  `+ `3 N% ]
  108.         while(1){
    5 V  `4 ~% E" C4 _
  109.                 //PCON |= 0x01;        // 进入省电模式
    8 a, S$ I+ C! s1 w: m" K9 i
  110.                 //_nop_();, [' q  d. h$ [  A2 Z+ l* l% Y! x
  111.                 //_nop_();$ U) \; H- Q! a3 x& n5 l
  112.                 //_nop_();. w/ Z5 `6 \  }6 g& Y0 [
  113.                 //_nop_();
    9 p1 Q; L( I0 e( K/ D; }
  114.                 buf = ~((P1 & 0x3F) | ((P5 << 2) & 0xC0));
    6 _' m# M" C6 F* k/ Z# Q8 Z
  115.                 bufReady = buf;
      z7 y% s- i5 z1 w6 D
  116.         }
    7 i2 @- E& S1 e/ ~
  117. }
    ( T+ ~: K" Y& ~! q
复制代码
' g8 E. ]7 J4 j# S3 V/ R
硬件参数配置无特殊要求,晶振频率选择12M即可。0 I' `8 F* ]8 x2 r1 a

2 n7 h4 f$ }8 C+ \$ h这是编译好的固件。

本帖子中包含更多资源

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

×

评分

参与人数 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, A' c6 q* Y6 [2 B3 {. X
不错的设计,想问一下楼主,FC的15针公头怎么解决?普通的公头太短了,插不进去FC的扩展接口。 ...

4 g7 Y/ A! A, k8 d5 N6 C# f" N坛友的改造方案。
回复

使用道具 举报

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

使用道具 举报

发表于 2019-5-25 12:07:18 | 显示全部楼层
精彩,楼主动手强,也写得很详细。/ o: k5 p8 D0 {8 u' v
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
" H$ u7 s, b6 c* r  N$ t$ L精彩,楼主动手强,也写得很详细。3 Y# T1 ], v. N$ h4 p6 s
2.4G方案是目前无线的最低延迟吗?

3 H! Q! I- `3 C& K我没用过其他无线手柄,所以实在不知道我自己做的这个手柄到底是不是最低延迟。2 J/ R! s+ A2 n& J  s) j7 j  U
不过根据网上的说法,延迟高低主要是由通信协议的复杂程度,以及数据传输速率决定的。这个模块虽然是2.4G无线模块,但由于协议很简单,所以延迟比较低。
+ g# Y: b/ I0 C8 B5 P! E+ V' f$ W我用这个手柄玩一些ACT游戏,比如超级马里奥、忍者龙剑传、热血系列,完全感觉不到延迟,和游戏机自带的手柄没有任何区别。唯一的区别就是这个手柄是用火花山寨手柄改造的,外壳是垃圾回收塑料,粗糙+脆弱,导电橡胶弹性不佳,手感不是一般的差。
3 T6 l2 A) D: Y$ P9 K: i) I我手里还有十几张板子,等我有空了我再做一套,到时候买一个好一点的手柄改造。
回复

使用道具 举报

 楼主| 发表于 2019-5-29 16:56:14 | 显示全部楼层
ppad 发表于 2019-5-28 17:27
7 y  T; a6 C; M6 k' p6 U给技术帝赞一个,有半成品发布吗,自己焊接改造就可以,编程实在不会啊 ...

4 \. V) D8 A% k, T. n很可惜,我手里没有多余的单片机了,LDO也找不到了,锂电池以及充电模块更是没有了。反正就是该用到的元件基本都没了,所以没法发布半成品。# e8 o. q6 j! {1 g8 _
两个板子倒是有十几张剩余。
$ \1 u9 L' }* `% p+ d: X. Q你要是有USB转TTL串口板,完全可以自己买这两种单片机,然后我给你编译好的固件,你自己用串口板下载到单片机里面就行了。两个2.4G无线模块也得通过串口板用AT命令设置参数,不过好在我在设计电路的时候就已经预留好了串口,可以直接在线下载和在线设置参数。总的来说并不麻烦。
回复

使用道具 举报

 楼主| 发表于 2019-5-29 17:00:34 | 显示全部楼层
孙大师 发表于 2019-5-28 18:55
' x5 j4 ^1 F& J! G非常好,楼主是技术帝,到目前我都还没开发fc的无线套件,等空了,开发一套套件,等玩家自己组装。 ...

' O1 M, d7 y" j. I能得到孙大师的赞誉,不胜荣幸!
. }& X9 j% ]2 i! D/ Z% T不如开发一个多功能手柄,比如用SFC手柄改造,L/R键配合其他组合键可以用来切换2P~4P、调节连发速度、软重启等各种功能。接收端插到15PIN扩展口。
回复

使用道具 举报

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

本版积分规则

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

GMT+8, 2026-10-27 11:36 , Processed in 0.718472 second(s), 14 queries .

Powered by Discuz! X3.5

© 2001-2026 Discuz! Team.

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