找回密码
 注册

QQ登录

只需一步,快速开始

查看: 21982|回复: 27

自制FC无线手柄

  [复制链接]
发表于 2019-5-22 14:16:45 | 显示全部楼层 |阅读模式
本帖最后由 雷精灵2046 于 2019-6-14 09:28 编辑 * C+ k0 ]7 O+ e3 x8 m( Y
: V  e2 u8 B* U9 V. B
没有用复杂的分立元件搭建发射接收电路,直接用的现成的2.4G无线模块jdy-40。
" |- I1 U( |2 ~& ?) z+ \2 d+ X1 A% G: j& F
" n) _" t, m2 {* \
发射端靠3.7V锂电池供电,用了一片SOP8封装的STC单片机,负责产生连发脉冲,同时负责检测电池电量,电压低于3V左右的时候触发低压中断,低压指示LED就会亮起来告知该充电了。平时发射模块和单片机均处于睡眠状态,有按键按下才会唤醒,从而实现省电。实测睡眠状态下整机电流约1~2uA。板子洗了一下稍微干净了一点。因为对于微功耗设备来说,焊接残余的助焊剂可能会增加漏电流。
" [/ l3 s3 C7 X2 \
$ V7 w) P) m5 z5 Q% M5 y, X买了一个火花的FC山寨手柄,去掉里面的牛屎板子,并修正一下塑料挡板,把锂电池和充电模块装进去。
& [4 J; q; x, y7 r  Q$ z* v( F3 Y为了减少体积,充电模块裁剪得十分小,并且更换了充电电阻使之适应这个小小的锂电池。这么小容量的电池,也不需要多么大的充电电流是吧?
( P! m6 U. t( X" N. r  ?+ u然后统统用热熔胶粘上。充电电流比较小,所以发热很少,不会熔化热熔胶。( d  z% o9 }9 d' _7 Q; u
& g0 ^& F3 O8 n; V5 k; I
; }7 q0 x1 E6 X6 L) K% ], J4 d1 H5 W
: r4 E' f1 e/ r
最后把按键、导电橡胶和电路板装上去。
9 U! g: E- p+ V+ n精心裁剪了电路板,正好扣上,不会阻碍其他元件,也不会影响后盖和拧螺丝。3 e8 B9 o. F* d

4 ?+ X4 Y5 x( R4 D: Z- D8 B$ U
( c# ^/ Z. P# C: p! Q" \* E完工!
- k- }0 V% [$ s# Z: l) ^1 g/ A- C7 c* m; W
* ]) b0 E1 T/ M9 ]% x! k+ ^
这是充电的MicroUSB插座。旁边的小孔用于透出低压报警LED的光线。
. G% u6 L( r3 h' h: h. V
/ \4 [# K  _  x& e: k& n+ {
/ M* d1 K5 `  ?% Q' t, X6 h9 r接收端用一片DIP16封装的STC单片机模拟CD4021。为啥要用单片机模拟而不是直接用CD4021?因为jdy-40模块接收端在有按键按下的时候输出高电平,无按键按下输出低电平,和普通手柄正好相反。当然我也可以用两片74HC00或者74HC04之类的逻辑门进行反相,但那就增加了芯片的数量。对于FC手柄这种工作频率并不高的设备来说,STC单片机完全可以胜任模拟工作。
! `: z; y  ], \2 B; F8 A/ p) X6 p; C  e. v/ Q  J
  [* O, ^+ I1 ^: j& v0 D' i3 L

  z7 k- X. M. H电路设计有点小小的错误,所以有几根飞线。原本设计使用低压差LDO是XC6206,结果在做这个接收模块的时候,买的LDO居然找不到了!无奈只好用了AMS1117。幸好对于接收模块来说是5V降到3.3V,1117可以胜任。要是发射端手柄的话,3.7V降到3.3V,那就非得用6206不可了。
$ K( q7 X5 J+ {9 S2 B
/ a+ j% ]1 c( H6 s实测十分灵敏,延迟极小几乎感觉不出来。可惜这山寨手柄的手感并不佳,尤其是方向键,软塌塌的。看来我得买个剪线手柄改装。7 v3 ^7 F- s6 k6 ^0 B

: o4 E* j% j9 S3 i" [' G/ v这是电路图,有兴趣的朋友可以参考。
5 h* Y5 h: ?% v0 d- V# O0 h4 j) y! G9 s& t  Z3 B' h

# a6 [  V' q8 o9 m; Y& x我信奉开源主义,十分痛恨把技术藏着掖着。好东西大家分享嘛!所以两个单片机的源代码大公开!3 t  p* x( x1 u+ Y8 V
编译器:Keil 51。( Z5 q% P7 \. }

0 Q  K; m1 ~" `0 c4 c  t发射端:
# x7 E/ E/ N9 O2 t/ f
  1. #include <INTRINS.H>
    * l( L8 I, a9 T
  2. #include "STC15W.h"  X1 r/ L. z+ Z

  3. : P& e1 e$ G# c/ Y4 ?% Z& X/ D

  4. 8 t- K6 W4 i; T7 Z! ^
  5. /*. l. K7 w# `5 u8 p; h
  6. --------------------------) b8 t* Z% D6 K! |% Y. ]8 ?
  7. |1 (OUT)        \__/   (INT1) 8|
    / z# X/ w6 G7 i7 _4 j6 @( U
  8. |                                                   |( a' k# K8 V" b0 d, ^
  9. |2 (VCC)                   (INT0) 7|
    & ]. G/ Q4 C% o: u
  10. |                 STC15W204S                   |
    1 u+ n2 U" p6 V9 }6 a
  11. |3 (LED)                         (TXD) 6|
    : c8 W/ |5 W  Y, D8 a8 p, O
  12. |                                                   |
    ( |% b5 w3 K- {1 g( _* V& }
  13. |4 (GND)                         (RXD) 5|
    % i1 h3 o* W+ h2 V# G5 A; S* L5 g6 Z
  14. --------------------------
    3 q5 a. Q. @, ?! Q  e/ b
  15. 7 x) I9 ~% ~- E9 v
  16. LED ---|<|---[===]--- VCC) K4 d, m1 D7 D, S# k2 k9 L
  17.            Red          330
    ! {1 F: g, {& M1 f' s& a! X
  18. ; _' L" H- ^- a* Y3 z
  19. Fosc = 6MHz
    % R: ^: f, P7 d( ?. y2 B3 I
  20. */; G$ N* O: E& j! m3 `' Q4 M$ D
  21. . \0 W, U) P! p5 G; U" Y

  22. ) s* {: e. p/ _9 W2 V$ |
  23. // 矩形波输出脚
    # a; E9 d/ @" C
  24. sbit OUT = P5^4;
    9 q. ?3 T  Y. W! x
  25. // 低压指示灯引脚
    ( x7 T+ _" G9 O' p
  26. sbit LED = P5^5;
    ( ^) n4 D5 ]: L: S" c

  27. 8 t' L1 d$ E( F3 j+ y0 o. ]
  28. // 停机标志位
    & i3 I- H6 ]8 F! ]3 n4 f  W8 q
  29. bit isReadyToHalt = 0;7 _. N, g! J/ w( B

  30. 9 [& ]9 d' w4 M& b/ S
  31. // 矩形波次数累计
    , ~! K; [+ t5 i6 N) @8 R
  32. static volatile unsigned char count = 0;$ B0 J& p1 _3 X  {* ~* k
  33.   z  J9 @& E, w6 Z( Z" T
  34. . s7 e" v6 w9 S; _0 H& E
  35. static void GPIO_Init(){
    : b3 Y6 z5 E! J; ~& R7 G- o1 x
  36.         // P3口设置为准双向,默认靠内部弱上拉输出高电平
    6 n6 z2 v# Y. r
  37.         P3M0 = 0;( P+ ~9 o: g  Q8 h2 a
  38.         P3M1 = 0;* L3 G6 F8 `' c$ m7 q  [  B9 X
  39.         P3 = 0xFF;
    1 Z6 Z+ J7 {3 t" G1 t/ J
  40.         // P5口设置为准双向,默认靠内部弱上拉输出高电平
    / |& I" \1 v$ {$ {6 m: `- T
  41.         P5M0 = 0;
    ) |! ~6 q2 }9 [# Q9 _$ z% m( d( l
  42.         P5M1 = 0;
    ) ]# Q; d7 @; u+ J, a3 N+ ~
  43.         P5 = 0xFF;
    # |  d) H9 i& J% v2 {
  44. }
    6 m, ]5 ~/ Z, k; ~& K) x: e

  45. 5 n& |' B4 S1 ]5 B. X9 j6 G
  46. static void Timer0_Init(){: R% M3 T7 q7 g) V  k' R( q$ v
  47.         // 16毫秒@6.000MHz
    - A/ e( T* \' ^8 M2 t: J6 H
  48.         AUXR &= 0x7F;        // 定时器时钟12T模式
    + p; t3 _" ]& C7 H3 h4 y
  49.         TMOD &= 0xF0;        // 设置定时器模式
    1 W( v1 Y% P& c: U9 I/ f' ~
  50.         TL0 = 0xC0;                // 设置定时初值
    $ N" M0 L' o! N0 D" G4 v' o
  51.         TH0 = 0xE0;                // 设置定时初值3 X' ]7 T7 m0 R3 i/ R
  52.         TF0 = 0;                // 清除TF0标志8 [. o* }2 ~0 h$ v9 A9 E$ m- Q
  53.         TR0 = 1;                // 定时器0开始计时
    * t" e( J- l  B0 u: b4 H) ^* Z
  54. }
    0 m# M' X2 K' h
  55. 8 t) U4 Q- t2 j/ Y$ O
  56. static void Interrupt_Init(){6 ~6 E+ }0 L7 p% l9 w- Y- r
  57.         // INT0中断触发类型为下降沿触发
    6 P+ L' z+ s% ^+ [3 d- p! F; }9 s
  58.         IT0 = 1;$ i& R) N/ O; t
  59.         // 允许INT0中断
    1 H  C( s! Y! [9 k$ d
  60.         EX0 = 1;
    + d# j- T3 A$ J
  61.         // INT1中断触发类型为下降沿触发
    : b+ V/ R# K1 @/ s9 E
  62.         IT1 = 1;
    6 J) k% S- U% s; V7 z
  63.         // 允许INT1中断1 M! C* I/ E8 W
  64.         EX1 = 1;
    5 [4 e+ i* v6 n0 C: Z( ], W
  65.         // 允许定时器0中断" D* X0 Q  w9 a0 }' P
  66.         ET0 = 1;9 \- p$ v) Z6 x! Y. }$ O; L6 T
  67.         // 允许全局中断
    ! S" O. @5 z+ p: L+ H- R
  68.         EA = 1;. e5 n0 I+ Y, ?
  69. }
    / v7 C% ?+ q+ |/ C0 |

  70. 4 x+ [5 P, Z  s
  71. static void INT0_Isr() interrupt 0{
    % P7 I. [# i0 n* G
  72.         // 矩形波次数累计归零+ q' @* R! o# M9 Y& P
  73.         count = 0;$ A$ q# U4 L" v
  74.         // 重开定时器0中断
    , |( w3 x* o% U, e9 |! b1 h& O
  75.         ET0 = 1;5 }8 p2 h3 f. h  i/ x+ R
  76. }0 h: ?9 Y' L! N! E8 |; s

  77. * c8 k/ `9 z0 y- G+ [
  78. static void Timer0_Isr() interrupt 1{
    , [* g! e% M: B
  79.         // 输出矩形波+ k; I6 i2 g: L- R* J' V
  80.         OUT = ~OUT;4 V- G6 C5 @1 l6 \
  81.         // 累计矩形波次数
    6 A' i  q' h  {' A) z7 S, [2 T
  82.         count++;- r. A. P! X+ ^/ b
  83.         // 超过250个矩形波,准备停机1 Y; {1 x7 M$ l- y) v1 u' g
  84.         if(count > 250){3 J4 W! G4 V8 ^8 c
  85.                 count = 0;7 X) \+ @: J2 ]4 ]
  86.                 isReadyToHalt = 1;
    . O) I' j: }% k' m! K
  87.         }
    & G: w6 j5 U  Z; F
  88. }0 L; M: b! U0 S+ h7 ?, [' L

  89. ! R/ }2 f! O2 M6 n
  90. static void INT1_Isr() interrupt 2{+ j* ^0 ]  N0 N( z- [2 N
  91.         // 矩形波次数累计归零
    / E  k: V- o4 k4 @7 A6 @2 O+ `
  92.         count = 0;: w( ?3 ~4 U5 `' T% M, m
  93.         // 重开定时器0中断
    5 d; m: s  Y2 T% R$ w0 O/ e
  94.         ET0 = 1;
    ( f! S1 Y1 i0 \" r8 `
  95. }: T0 w2 R3 N( X. R/ _

  96. 3 Q* X+ n3 f8 b
  97. ( m2 W/ J8 N! q; O1 b' R( g: u0 ]# L
  98. void main(){* t* r, Y6 @0 f* V- h% d; x
  99.         // 初始化P3和P5口
    ! Y3 X+ t2 g3 J9 @* F: P# A
  100.         GPIO_Init();
    3 h# {( C. W9 I4 z9 K6 c
  101.         // 初始化定时器0
    + W* I. y) z1 u, W  R, c
  102.         Timer0_Init();/ v6 A" C, I, u6 x! {% X7 O9 M
  103.         // 初始化中断) U9 s1 i% ?* Y! Y5 H, v2 ~
  104.         Interrupt_Init();
    ) d9 y9 C/ D( L( \; ]8 @
  105.         $ z, ^# x" t1 Z! q
  106.         while(1){
    5 r/ x$ j: I+ y
  107.                 // 检测电量  M7 [2 C7 e: |/ `& z7 P4 k# K
  108.                 if(PCON & (1 << 5)){( j+ g3 C. K0 }' Q- q7 z& |0 U
  109.                         // 如果电量低,低压指示灯亮
    ! q, {2 L$ L3 _
  110.                         LED = 0;
    ( E0 m& r7 A& ~# G, n
  111.                         // 清电量检测硬件标志位
    0 b5 _" D+ \  t- y; i/ z. M
  112.                         PCON &= ~(1 << 5);
    ) j, p" z1 d, O; K. t
  113.                 }else{4 i. O) S! O9 \
  114.                         // 电量正常,低压指示灯灭
    + A1 P( _$ y4 j+ I
  115.                         LED = 1;7 E0 k3 d' A* y8 `
  116.                 }
    2 ~7 t" S; X4 D- j
  117. - a1 q- C0 K3 B1 D
  118.                 // 检测到停机标志9 Y' n6 D4 N3 ]9 V
  119.                 if(isReadyToHalt == 1){, m  m8 U: N) L1 n- A- F
  120.                         // 暂时关闭定时器0中断
    * [' o9 G, z% u2 [' x( @9 G
  121.                         ET0 = 0;
    ' M8 ]* U# M+ f6 ~9 D+ s
  122.                         // 停机之前先把矩形波输出脚置低电平,以方便INT0和INT1唤醒CPU
    - o" t. u: Y9 K; S8 M- l
  123.                         OUT = 0;" o1 e& T; r/ [- k
  124.                         // 停机之前先把低压指示灯灭掉,以省电
    9 ?8 J8 R$ F5 S# a  H! \/ q: k
  125.                         LED = 1;1 v" q( Y' o5 U0 l! S
  126.                         // 进入停机模式; y0 f8 ?5 d+ j! d% z  k4 B
  127.                         PCON |= 0x02;
    & E( ]& B7 F9 n0 G9 T3 O
  128.                         _nop_();' @" V: ]$ B! p2 `( ]. M4 Y
  129.                         _nop_();# h2 ]/ F& B" O
  130.                         _nop_();
    % s0 W9 S2 N* d) c- q
  131.                         _nop_();. O! f7 n9 }" {% C2 M. \/ N+ r8 n
  132.                         // 唤醒,清标志位
    ; c1 A# C5 S0 P* `( [" b8 i% c
  133.                         isReadyToHalt = 0;
    4 `! O( j9 h% v
  134.                         // 重开定时器0中断
    + ^, \: h( h* S
  135.                         ET0 = 1;+ \, B0 [4 b8 [' s% N  ]# l
  136.                 }
      h3 J2 N2 [  p  n' f, g
  137.         }. V( r8 [, m( w, c3 j2 c! Z
  138. }( P8 A& u% j8 j9 P
复制代码

. }7 V& d" {! e0 [硬件参数配置:5 P6 Q+ l4 G% p$ F5 B; ~1 x% r
3 N; X8 L2 `$ G" |8 X# i6 X) d

- S; @+ d4 l* V) G( d7 ~0 o% `接收端:
9 p+ y1 L0 N  e; m
  1. #include <INTRINS.H>/ Z* T/ N3 ]/ V( C# }  n5 |7 H. O
  2. #include "STC15W.h"
    5 _( x  h+ w# o! Y: U
  3. * ^* D2 I! j- b6 e

  4. 4 A8 i# D0 G' S7 p/ n6 j
  5. /*5 K) i2 D! e9 x0 L
  6. % Z; p( H% i2 X6 Y2 }0 ]" p
  7. *---------------------------*' n  \" C6 }0 w2 _0 p. T
  8. |1 (GPIO2)         \__/  (GPIO1)16|; i9 g# `: ~0 K. v# p3 ?. x2 L7 D
  9. |                                                        |
    ' u8 }% H$ J( F& {
  10. |2 (GPIO3)                   (GPIO0)15|' t5 }, \; s' R1 \  y9 ~
  11. |                                                        |
    # Z2 i2 N2 \+ M7 N! |! C$ D8 k
  12. |3 (GPIO4)                                  14|
    ; }9 J% J6 f8 U9 T4 B3 z0 \
  13. |                                                        |1 J$ z5 a; t6 j1 s  c. g% l) [6 s
  14. |4 (GPIO5)                        (DATA)13|$ f% `' O% \7 r, ]. s
  15. |                  STC15W204S                |
    $ l1 {9 a9 }2 @3 v
  16. |5 (GPIO6)                   (LATCH)12|  ^$ ]# m# y* ~- `5 y+ [; H7 S
  17. |                                                        |
    5 D$ k- s6 i" C
  18. |6 (VCC)                         (CLK)11|
    5 [2 O2 [- r$ J( `) p5 I
  19. |                                                          |
    - U; P' f9 _4 M* F4 W" c& `
  20. |7 (GPIO7)                         (TXD)10|2 T0 l2 i4 N+ i
  21. |                                                        |! z: F1 F, `' |
  22. |8 (GND)                         (RXD) 9|
    : U9 X- t7 `! c" G9 M0 r" R
  23. *---------------------------*
    , v% j& D9 L0 ?2 q5 v3 W& K2 u) s" P
  24. Fosc = 12MHz3 }1 ~' ]3 x+ c* G
  25. 1 R1 e; N6 m" K# \# O( x9 c3 }
  26. P1.0 -> 上
    , b0 q$ h) F+ D' g
  27. P1.1 -> 左- F5 g( @' @/ D7 \3 A
  28. P1.2 -> 下* Q- I3 w% @! ^8 g$ h. T6 j
  29. P1.3 -> 右
    ( ]8 E; b- r4 C3 Y9 H6 Y7 Q8 |# Y
  30. P1.4 -> SEL( I* |% P. M: Z3 f* R" `
  31. P1.5 -> STA$ m) J% Z. v" K" a" m* ~
  32. P5.4 -> B
    7 J: |- @- ]. j: U4 Z2 }/ j
  33. P5.5 -> A0 K) a  ^! D( |) m3 |
  34. % Q. H! Q1 ?0 o
  35. */0 M6 p6 F, Q8 X; S
  36. 8 j5 f$ M& k# h( x& t- t) d9 s7 p2 ~

  37. 2 m6 C) e5 l: K: `1 G% H' F1 e
  38. sbit CLK        = P3^2;2 v. {/ n6 w( u' [
  39. sbit LATCH        = P3^3;
    4 G; V2 J- Q9 @2 n
  40. sbit DATA        = P3^6;7 G+ R6 Y% U( V1 L: E

  41. ) }  \+ w, @1 ~+ `; ?
  42. bit isReady = 0;
    2 M! P& B" ?2 h) l( X* s: F
  43. static unsigned char key = 0;
    ; S0 o: L& h/ N9 s/ |
  44. static unsigned char buf = 0;        // 双缓冲。这个缓冲区保存从P1和P5组合而来的键值
    , i" m# D7 }9 |! D1 M* T
  45. static unsigned char bufReady = 0;        // 双缓冲。这个缓冲区保存上面那个缓冲区的备份
    : u8 v/ _& N1 ~- J# S
  46. static const unsigned char data mask[] = {0x80, 0x40, 0x10, 0x20, 0x01, 0x04, 0x02, 0x08};        // A B SELECT START UP DOWN LEFT RIGHT。为提升速度,这个表放到RAM中7 f9 ]7 a5 j. {; |4 A3 R
  47. static unsigned char idx = 0;
    4 I' ?2 M6 y# y) u

  48. 8 T8 z, X4 v. v7 L5 u, |; R$ k% s

  49. ; H0 a2 K, N2 ?
  50. static void GPIO_Init(){+ s& e, [( F1 v  ]; B
  51.         // P1口和P5口用于接收并行信号,全部初始化为准双向,依靠内部弱上拉输出高电平0 c' D! x# U) [) k$ n
  52.         P1M0 = 0;% n5 Y( M( u9 g3 P3 a* C
  53.         P1M1 = 0;: b% W4 g: o* L0 `
  54.         P1= 0xFF;& a2 C  J4 H0 P0 @2 v
  55.         P5M0 = 0;
    4 H2 F) g' x, w# r
  56.         P5M1 = 0;
    ! W& z: y1 a6 H* {
  57.         P5= 0xFF;
    / z& r- j0 s( m  a% K
  58.         // P3口初始化为准双向2 S; C( h" d+ ^: B$ r5 s
  59.         P3M0 = 0;
    1 w; _, G( O2 O# S6 g/ x# G
  60.         P3M1 = 0;
      ~; w0 w& r% _) g" {
  61.         P3 = 0xFF;. b" q: m8 D; |2 H& T% q; D. [
  62. }. o* ]0 B7 f# N7 @# b' `
  63. 9 o. t. l0 U2 F* y! A
  64. static void Interrupt_Init(){8 u! X! Q, X( q8 m& W0 ?
  65.         // INT0中断(CLK)触发类型为上升沿+下降沿0 j; h$ s9 I2 q* a
  66.         IT0 = 0;& n" `7 f; |' M. w, O- t
  67.         // 允许INT0中断
    " S! d; a/ o9 z* E# k
  68.         EX0 = 1;: b. q8 a% \' n% h
  69.         // INT1中断(LATCH)触发类型为上升沿+下降沿
    8 m& w9 D5 }9 b& j, h) F
  70.         IT1 = 0;; J+ \6 B" ]$ E: A2 T! _  l
  71.         // 允许INT1中断
    3 n' s4 g4 E9 \$ C$ C: i
  72.         EX1 = 1;! \+ _( Y5 J  j7 i# S- I/ F
  73.         // 开启全局中断# s# `' s& j! m5 Z
  74.         EA = 1;
    & b4 a/ K; b  f4 O$ M( w& D0 c
  75. }
    9 E' q: ]$ N0 {0 P  c+ j# q( ~  K5 m1 ^

  76. : W! A6 C: F  Y: w  J5 }% Y
  77. static void INT0_Isr() interrupt 0{# X8 k4 q% B' \, ?- Z& ], s
  78.         // 只有已经成功锁存才允许CLK移位+ j2 P0 a: [* f- N  X
  79.         if(isReady == 0)3 k3 ~( |+ Q! k% W1 l( k$ H# k
  80.                 return;; U$ O4 T- ^( L
  81.         // 读当前引脚电平,如果是低电平则说明是下降沿,此时直接忽略该中断2 P4 y8 `  u) `  `  Z
  82.         if(CLK == 0)% d7 i( U$ d$ j$ f
  83.                 return;
    1 W( S: U7 Z$ P% e5 L
  84.         // CLK上升沿到来的时候,取锁存值的下一位输出
    0 A0 N" f3 I+ o% n  S8 w/ V
  85.         idx++;7 @+ T' M6 v0 e( {- ]. Y
  86.         DATA = key & mask[idx];3 `- b" y& B9 F  k5 A5 A
  87.         // 如果已经完成7次移位,则一轮读取完成; [) d2 ?, ~1 Q! @; Q: q8 k$ Q! H5 O
  88.         if(idx >= 7)
    " Z7 u- K8 Y! o& m1 E1 Z5 {
  89.                 isReady = 0;, D1 j6 z  Q" q! k* W
  90. }
    ( a5 N% O, o  n" _) m5 u
  91. 8 Z* l, Y% [7 s; ]/ q. _
  92. static void INT1_Isr() interrupt 2{- q* ]" ~' `% |) e7 F7 l+ P
  93.         // 读当前引脚电平,如果是低电平则说明是下降沿,此时直接忽略该中断  u  T" r$ ]0 x3 _5 ]: }
  94.         if(LATCH == 0)% b) o4 F6 ?$ E0 y; ?! h, z2 Y
  95.                 return;7 \- W5 o0 u. ], _% h) C
  96.         // 当LATCH上升沿到来的时候,锁存所有按键状态,同时把键值A输出到DATA
    & P& p/ f) u& B: F. H
  97.         key = bufReady;
    2 G7 C, W. M: g% {9 O
  98.         DATA = key & 0x80;//mask[0];        // 为了加速运算,直接取表中的值而不是读表
    ; r+ b# z! k# J+ o) g" G
  99.         idx = 0;" a: V; w: D6 }7 {8 v" s2 @
  100.         // 允许CLK进行移位4 {0 R$ r8 s/ C7 c; Z5 s
  101.         isReady = 1;7 U! s8 H) z3 Z! ~7 v+ Z) T1 k
  102. }4 y1 Q3 }$ u, r4 L3 c# O) m
  103. 3 i  {8 u, _% P, H0 @, H5 F* z2 R
  104. void main(){
    5 N5 {/ g1 S4 ]5 ?
  105.         GPIO_Init();$ a% @  `0 X/ {
  106.         Interrupt_Init();& V: K& f7 f* p6 l* s" b( C
  107.         ( |# P+ q. _1 d3 z6 P- _" f# D
  108.         while(1){# z; _6 @& c: y+ K8 K( t* H
  109.                 //PCON |= 0x01;        // 进入省电模式
      `$ P; i1 Z8 O5 u
  110.                 //_nop_();
    5 H  s+ O4 g9 k$ _7 f
  111.                 //_nop_();
    3 a6 @4 |, f4 h* N5 J: ?
  112.                 //_nop_();
    $ y+ i' A" |5 L7 J- h
  113.                 //_nop_();: }1 R4 E0 \) F0 ?( p
  114.                 buf = ~((P1 & 0x3F) | ((P5 << 2) & 0xC0));
    - H9 |5 \& ^8 ]3 x  W  H, t  A
  115.                 bufReady = buf;: B1 K! S& }0 l; x: X0 |' T
  116.         }
    ; j% d$ |" N4 u9 p+ \% c" N9 B% C( X
  117. }- ]% U! w) p. @, J
复制代码

0 @- m4 Y* Y& p3 O5 r; U硬件参数配置无特殊要求,晶振频率选择12M即可。
! v8 L  [# L4 X# r3 M8 J' z6 w; _$ g# I/ O/ e$ J
这是编译好的固件。

本帖子中包含更多资源

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

×

评分

参与人数 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. A$ H% I1 o% H' B, W
不错的设计,想问一下楼主,FC的15针公头怎么解决?普通的公头太短了,插不进去FC的扩展接口。 ...
6 A1 O1 s; q7 N2 p
坛友的改造方案
回复

使用道具 举报

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

使用道具 举报

发表于 2019-5-25 12:07:18 | 显示全部楼层
精彩,楼主动手强,也写得很详细。: y, w7 r; b6 y0 W' Q2 X2 s
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
" o" a$ S$ B1 ]! \- _9 z, W( Q/ a8 V* j精彩,楼主动手强,也写得很详细。  J6 n& F3 i& C& d& b  R0 C7 ~
2.4G方案是目前无线的最低延迟吗?

6 _8 }  G1 a2 H我没用过其他无线手柄,所以实在不知道我自己做的这个手柄到底是不是最低延迟。
( O/ e, Z, V/ q$ m3 }不过根据网上的说法,延迟高低主要是由通信协议的复杂程度,以及数据传输速率决定的。这个模块虽然是2.4G无线模块,但由于协议很简单,所以延迟比较低。3 O% |5 z! K: b$ c% P7 u! k
我用这个手柄玩一些ACT游戏,比如超级马里奥、忍者龙剑传、热血系列,完全感觉不到延迟,和游戏机自带的手柄没有任何区别。唯一的区别就是这个手柄是用火花山寨手柄改造的,外壳是垃圾回收塑料,粗糙+脆弱,导电橡胶弹性不佳,手感不是一般的差。
" |- R0 U7 t! }  a* r我手里还有十几张板子,等我有空了我再做一套,到时候买一个好一点的手柄改造。
回复

使用道具 举报

 楼主| 发表于 2019-5-29 16:56:14 | 显示全部楼层
ppad 发表于 2019-5-28 17:27
0 |- Y& K* j1 z# X, H! i% k给技术帝赞一个,有半成品发布吗,自己焊接改造就可以,编程实在不会啊 ...
. B" R2 f7 k$ h8 R$ x; @" |# z, k
很可惜,我手里没有多余的单片机了,LDO也找不到了,锂电池以及充电模块更是没有了。反正就是该用到的元件基本都没了,所以没法发布半成品。0 `" `' R4 o6 ~
两个板子倒是有十几张剩余。! u5 [0 {; M+ k) P+ r+ t/ [! Q# e
你要是有USB转TTL串口板,完全可以自己买这两种单片机,然后我给你编译好的固件,你自己用串口板下载到单片机里面就行了。两个2.4G无线模块也得通过串口板用AT命令设置参数,不过好在我在设计电路的时候就已经预留好了串口,可以直接在线下载和在线设置参数。总的来说并不麻烦。
回复

使用道具 举报

 楼主| 发表于 2019-5-29 17:00:34 | 显示全部楼层
孙大师 发表于 2019-5-28 18:55: f6 D# p% K# i9 l
非常好,楼主是技术帝,到目前我都还没开发fc的无线套件,等空了,开发一套套件,等玩家自己组装。 ...
  n3 {! ?8 M9 X: ^5 K" O
能得到孙大师的赞誉,不胜荣幸!
% N" C7 X+ f/ c; y+ K  |1 E6 q! B不如开发一个多功能手柄,比如用SFC手柄改造,L/R键配合其他组合键可以用来切换2P~4P、调节连发速度、软重启等各种功能。接收端插到15PIN扩展口。
回复

使用道具 举报

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

本版积分规则

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

GMT+8, 2025-7-1 15:41 , Processed in 0.100673 second(s), 15 queries .

Powered by Discuz! X3.5

© 2001-2025 Discuz! Team.

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