找回密码
 注册

QQ登录

只需一步,快速开始

查看: 25172|回复: 32

自制FC无线手柄

  [复制链接]
发表于 2019-5-22 14:16:45 | 显示全部楼层 |阅读模式
本帖最后由 雷精灵2046 于 2019-6-14 09:28 编辑
- h; S4 H. C4 i, W; G, F3 v, y4 T+ Q9 F; x, @7 p4 ^* s
没有用复杂的分立元件搭建发射接收电路,直接用的现成的2.4G无线模块jdy-40。
% h9 Q: A6 k# n' v8 `' k  m0 W8 z4 F) U
9 e3 v$ N/ [4 G, `3 ?
发射端靠3.7V锂电池供电,用了一片SOP8封装的STC单片机,负责产生连发脉冲,同时负责检测电池电量,电压低于3V左右的时候触发低压中断,低压指示LED就会亮起来告知该充电了。平时发射模块和单片机均处于睡眠状态,有按键按下才会唤醒,从而实现省电。实测睡眠状态下整机电流约1~2uA。板子洗了一下稍微干净了一点。因为对于微功耗设备来说,焊接残余的助焊剂可能会增加漏电流。
' U1 [  I3 d8 W! j
7 C' U8 N+ S4 ~# v$ m- a, R# K( O" ?买了一个火花的FC山寨手柄,去掉里面的牛屎板子,并修正一下塑料挡板,把锂电池和充电模块装进去。4 H! I. S7 M; G9 c' g4 S
为了减少体积,充电模块裁剪得十分小,并且更换了充电电阻使之适应这个小小的锂电池。这么小容量的电池,也不需要多么大的充电电流是吧?
" Z  O$ W8 y8 h5 A, Q6 y# B然后统统用热熔胶粘上。充电电流比较小,所以发热很少,不会熔化热熔胶。
! n* J) l; ^( i( d" Y6 t# e4 F8 r
: ]) x) x' B9 o- U2 }+ e
, D. @3 R( i! g. r; R
最后把按键、导电橡胶和电路板装上去。
" m2 W5 ^7 j* I  U9 A; W- _- h精心裁剪了电路板,正好扣上,不会阻碍其他元件,也不会影响后盖和拧螺丝。$ y* _$ [6 A& q1 M7 [. P8 l7 D8 V
( }6 ?- A: H! }- O+ R  a5 N

( D+ x6 b% k/ E% \3 G完工!
5 P( A7 |9 W. _* M3 o2 ^: Y- K. ]! g; F. r9 I( ^

& M1 r7 M& L' w7 [- F这是充电的MicroUSB插座。旁边的小孔用于透出低压报警LED的光线。* L  B$ H9 y1 B

3 h' m. \4 J* e" u1 z
5 V. l* a1 C" s: i接收端用一片DIP16封装的STC单片机模拟CD4021。为啥要用单片机模拟而不是直接用CD4021?因为jdy-40模块接收端在有按键按下的时候输出高电平,无按键按下输出低电平,和普通手柄正好相反。当然我也可以用两片74HC00或者74HC04之类的逻辑门进行反相,但那就增加了芯片的数量。对于FC手柄这种工作频率并不高的设备来说,STC单片机完全可以胜任模拟工作。4 _" l4 `& m( i% K) G

0 C. v7 c- m% t1 O# D( Z
8 ^/ s4 J' P& m- ?6 `0 R
+ ]3 \, ?6 Q% ^' [8 \! o7 W/ u电路设计有点小小的错误,所以有几根飞线。原本设计使用低压差LDO是XC6206,结果在做这个接收模块的时候,买的LDO居然找不到了!无奈只好用了AMS1117。幸好对于接收模块来说是5V降到3.3V,1117可以胜任。要是发射端手柄的话,3.7V降到3.3V,那就非得用6206不可了。. y: e/ I9 b8 ~+ y' b
5 a6 |2 R8 u/ S& C& U1 [9 R
实测十分灵敏,延迟极小几乎感觉不出来。可惜这山寨手柄的手感并不佳,尤其是方向键,软塌塌的。看来我得买个剪线手柄改装。: \. Z0 T! v7 h

8 n7 G9 S* {1 r1 h5 B2 Z* a% I8 d这是电路图,有兴趣的朋友可以参考。3 k2 W7 C# G/ e* d  n5 ?
' ?! ~" X3 r; M0 d
3 \4 E  z' i5 Z
我信奉开源主义,十分痛恨把技术藏着掖着。好东西大家分享嘛!所以两个单片机的源代码大公开!+ q8 o+ F/ S7 q4 {! j
编译器:Keil 51。
' R* A8 |7 m4 m' M8 _
' M7 N9 {' T1 e' Q+ ?发射端:
& g* l! [+ V% r% ^% _9 M: K
  1. #include <INTRINS.H>
    " K. E/ w* u3 x: {
  2. #include "STC15W.h"
    % |# D  j: M$ D1 L8 ^
  3. " V3 X4 W) a6 {, U
  4. & s! C# i2 ?) u/ M4 A& `6 h! r
  5. /*
    9 y" Z! @2 l0 c& R. D( c' f5 V
  6. --------------------------
    , f/ X0 I4 u- o$ B' p2 R( _
  7. |1 (OUT)        \__/   (INT1) 8|' s; {' C; P4 c& q/ j
  8. |                                                   |/ C- p& x% J+ R+ p3 a
  9. |2 (VCC)                   (INT0) 7|& t5 E( p% F4 G4 Q% C$ X8 H
  10. |                 STC15W204S                   |- }& N- Z9 U, @& f
  11. |3 (LED)                         (TXD) 6|
    : U0 j; \) ?& ~: V  M0 ]: Z/ t
  12. |                                                   |
    0 ]! s1 w9 Q' R+ Z% s8 R
  13. |4 (GND)                         (RXD) 5|2 X; p5 I' \/ _& w- o* Q. Q
  14. --------------------------7 L( {4 v5 B! O& c' Y- l

  15. , l) x! Y8 y1 D# v; _
  16. LED ---|<|---[===]--- VCC
    2 Y8 m+ n7 m7 i
  17.            Red          330
    * C# G6 q/ U% m1 _8 t8 j6 T

  18. * I3 `7 _; P- l  k8 O, w/ O
  19. Fosc = 6MHz
    8 D8 p# n  I2 \  I' q3 _9 I4 W, o
  20. */9 p- y$ U& s! Q# L( P7 v6 _

  21. ' L. o# b1 ^/ z! T

  22. $ X. Q- k; R# D6 X4 y9 H& ~
  23. // 矩形波输出脚
    ( B2 ]* ~% F: r, E
  24. sbit OUT = P5^4;/ }. w; J% ?- C) ?) l- w. ^
  25. // 低压指示灯引脚$ E0 u/ a. W" c& Q8 {+ ]$ x2 w, J
  26. sbit LED = P5^5;- p. o4 U! i$ u" u

  27. ! n: u$ H% x2 C5 A4 c
  28. // 停机标志位( E9 O: J/ [0 O9 k  f& O
  29. bit isReadyToHalt = 0;
    " }1 P7 r1 p# l! @5 Q

  30. " M1 ^0 n: w0 `2 Q8 x+ r
  31. // 矩形波次数累计
    9 @* Y7 e! V/ }8 I* }* R* y
  32. static volatile unsigned char count = 0;
    + V+ r, X. b: U8 x5 N+ c* }5 f
  33. + j. n  O( D, H! s9 [8 M: w  Z
  34. : P5 L* ~% b4 \& B3 r7 ]
  35. static void GPIO_Init(){
    4 g1 r2 k/ F# o; g
  36.         // P3口设置为准双向,默认靠内部弱上拉输出高电平% @! m: g3 |1 D+ ]
  37.         P3M0 = 0;
    4 U* x5 ^1 z8 K1 j# h8 t9 P5 Y. \  k
  38.         P3M1 = 0;& L8 u& S) m8 N) a2 P4 X
  39.         P3 = 0xFF;
    0 ]# p, Z6 r" ~2 _% N3 W& Y2 R
  40.         // P5口设置为准双向,默认靠内部弱上拉输出高电平. h% {2 t) ~5 _6 |# L3 o
  41.         P5M0 = 0;
    & p+ h% ?2 n4 j5 y
  42.         P5M1 = 0;. s- B) G0 S& O1 k! W2 P, D
  43.         P5 = 0xFF;
    9 `, e9 E0 W; I; w
  44. }4 O- ?+ ?' R: T
  45. / Y0 R$ y0 \- J6 v/ H, S
  46. static void Timer0_Init(){
    % i% i( L( n( z
  47.         // 16毫秒@6.000MHz
    . j" J" \+ ?  K6 o0 X5 M
  48.         AUXR &= 0x7F;        // 定时器时钟12T模式4 j/ }& r9 q$ O0 G- R2 F5 x
  49.         TMOD &= 0xF0;        // 设置定时器模式+ c- l. S$ s0 W6 d
  50.         TL0 = 0xC0;                // 设置定时初值
    + V( X7 _1 f0 b% g) r! M" x
  51.         TH0 = 0xE0;                // 设置定时初值8 T  f+ |) [2 f! ^# j
  52.         TF0 = 0;                // 清除TF0标志* h* w4 f3 A) @$ S( _4 L
  53.         TR0 = 1;                // 定时器0开始计时: F: u, m& B, g* K) u/ r
  54. }
    ; R! @& C( U8 @7 w
  55. ' R8 k' R0 E( ]) M5 i: w7 P
  56. static void Interrupt_Init(){7 ~; @; e; n) m0 n7 R
  57.         // INT0中断触发类型为下降沿触发
    4 k/ c6 H8 A3 u. S. `
  58.         IT0 = 1;
    & |* k! T+ Y( t4 s; ~  a
  59.         // 允许INT0中断
    - u7 P& v* Y3 n) Z5 ~, l7 h
  60.         EX0 = 1;; r5 [6 Z/ E! E' t* x) X
  61.         // INT1中断触发类型为下降沿触发0 Q# X6 \" r! j+ X
  62.         IT1 = 1;7 L" [1 I& J) `8 \# i# r2 L1 t" X
  63.         // 允许INT1中断7 ?# B7 `9 j4 n4 D3 ^* m
  64.         EX1 = 1;
    9 I: ?' y. \/ d0 O+ J% c* C9 s
  65.         // 允许定时器0中断& r+ a) `; s% m8 j
  66.         ET0 = 1;* y! b1 }2 O/ W
  67.         // 允许全局中断1 b& C5 S# R8 j7 u* v6 c
  68.         EA = 1;; f1 N4 r" G* Y! B5 B
  69. }- q7 B/ f( A' \0 d0 t" s
  70. 5 n$ v+ L8 `. ~! V
  71. static void INT0_Isr() interrupt 0{" T2 E. Y" Z2 r
  72.         // 矩形波次数累计归零
    ; i1 t. m- Q* `6 Y) e
  73.         count = 0;
    ! ~" Z* U, U- ]
  74.         // 重开定时器0中断
    + k( x5 }1 t  b: }
  75.         ET0 = 1;1 b, N" [3 ?& x6 J0 B; S
  76. }/ `$ v; x( u' b4 U
  77. 3 l8 P: `% q" S( {3 {7 z8 }
  78. static void Timer0_Isr() interrupt 1{
    % z: P+ x9 _3 i0 l4 q
  79.         // 输出矩形波
    8 z, S( A6 `! c5 J7 m% F( m  Y! r
  80.         OUT = ~OUT;
    9 b( \7 X$ }" x& ^
  81.         // 累计矩形波次数6 y6 }# P5 C9 r, m6 m) T$ i2 `
  82.         count++;  U* j* p8 P8 `6 @% {# [
  83.         // 超过250个矩形波,准备停机! l9 F, ~3 F. @: n6 O& ]+ E
  84.         if(count > 250){5 ]5 s) M' O; w: @
  85.                 count = 0;4 G& q" B9 y7 L  X, c" w
  86.                 isReadyToHalt = 1;
    % o8 m; I2 A- r5 `6 w
  87.         }
    0 Q1 d, N. t' R2 r- Q
  88. }' |) G# V. a8 k: U

  89. & O3 I4 j& Y* v. }
  90. static void INT1_Isr() interrupt 2{
      G- j/ ?& }; m9 X
  91.         // 矩形波次数累计归零
    & X( b; f& R  l8 D
  92.         count = 0;- `+ r. y4 L; V/ ^
  93.         // 重开定时器0中断/ S, a2 _; V4 P! a7 f
  94.         ET0 = 1;
    9 t6 w6 I9 Y9 K3 d7 @
  95. }
      n) B! D+ V. }+ I9 h
  96. 9 Q- Y/ l3 P  K/ _1 g* V9 v

  97. 7 q& _9 }$ f' w' D6 _
  98. void main(){# j( l; {* p& g- T, D" w  v
  99.         // 初始化P3和P5口
    + x1 m( t$ R) [# I$ S: r
  100.         GPIO_Init();1 M" _& J( H# ~7 z: _1 @4 \% X( d" V
  101.         // 初始化定时器0
    3 p4 t3 r8 I. U7 W. _# o2 t! ]- C
  102.         Timer0_Init();# E# d; B0 d" D
  103.         // 初始化中断5 R8 h" I$ R% ]# O; a" G
  104.         Interrupt_Init();
      ^" {4 W% ~8 w, |; r
  105.         4 D3 v+ `) R1 j/ h
  106.         while(1){) b& Z& T4 L3 V/ }( s; f& Y
  107.                 // 检测电量3 |8 o5 Y' `' n# D3 a
  108.                 if(PCON & (1 << 5)){. d5 Y4 W" b9 N; ^1 I
  109.                         // 如果电量低,低压指示灯亮& P9 m0 q' q# K) J; Z( n* z
  110.                         LED = 0;( \) Q- k# C% k1 A) S& {1 ], r
  111.                         // 清电量检测硬件标志位: L) c! l$ j( ~% @! l3 L: r
  112.                         PCON &= ~(1 << 5);
    " h0 [+ S% p' I2 A" L
  113.                 }else{
    5 m$ ~; z7 R' V  Q1 n% @  J' D
  114.                         // 电量正常,低压指示灯灭/ K& |4 G7 O2 O
  115.                         LED = 1;
    ! U# l) `5 o2 S2 p
  116.                 }  ]  w* U; w$ s8 Q; d( P
  117. - D% V4 F- R0 U$ a* @+ o
  118.                 // 检测到停机标志# y- W" Y* w$ \8 w4 c( @( X
  119.                 if(isReadyToHalt == 1){
    7 r# r$ z4 _3 m1 A+ `/ E. V
  120.                         // 暂时关闭定时器0中断' Q2 q' `5 y6 a0 i) C' x6 D6 T
  121.                         ET0 = 0;2 {1 W3 j+ D1 l1 `9 Z
  122.                         // 停机之前先把矩形波输出脚置低电平,以方便INT0和INT1唤醒CPU
    . X  p, \2 ?7 G8 b
  123.                         OUT = 0;0 U4 Y( e5 x6 U9 A% x* F
  124.                         // 停机之前先把低压指示灯灭掉,以省电- e/ Q2 M& P- l9 |. S$ T& h5 Q2 |4 E
  125.                         LED = 1;' Y% x% U  b- M) f  i4 [
  126.                         // 进入停机模式
    " \( u8 d" }4 \# B/ ]4 m
  127.                         PCON |= 0x02;% d$ s$ H$ ?' }8 M- a8 f
  128.                         _nop_();, v. e& D0 T3 b" c, i' x
  129.                         _nop_();0 n4 v4 ?+ X% t
  130.                         _nop_();+ V# W* k$ |! E- L" [6 ]9 N
  131.                         _nop_();3 ?' K# b' i& a8 K: _# I
  132.                         // 唤醒,清标志位6 O4 y0 g9 j% t
  133.                         isReadyToHalt = 0;# F' F$ q  {8 H+ S/ v0 |
  134.                         // 重开定时器0中断
    , Z( `( V$ f9 D7 f/ B
  135.                         ET0 = 1;
    # K# C6 I/ }$ k: K+ N9 e
  136.                 }
    / e  P9 T$ `2 [( G- ?3 ?) @
  137.         }5 z9 c' j  h2 X: ^7 j! d- k
  138. }* z$ O8 _0 I. S* r, D
复制代码

9 B2 ^; @- K6 K. |1 b  Y硬件参数配置:$ g8 _( h! i/ B
$ A2 z( ]7 X- w* W4 X

2 X* {" G# i+ p接收端:
6 b  v9 D5 v' k. ~; W
  1. #include <INTRINS.H>
    1 d4 O; j, i! X2 Z$ K& W- V) |
  2. #include "STC15W.h"6 Q! O' @) N- Q* S+ i

  3. 3 z3 S2 B7 x/ A' {9 c) y6 x2 Z
  4. 6 [( Q! U2 J. m# t# B& S% J
  5. /*# E9 M% T* W' k) x* Z6 X' v: d
  6. 1 y  ^9 b9 _! t2 T' `
  7. *---------------------------*
    # A7 O' f: ~5 C4 K# w; _! N1 p
  8. |1 (GPIO2)         \__/  (GPIO1)16|
    " B1 L) |7 L1 h
  9. |                                                        |6 v: F# X' E2 ]3 q6 m% j$ c: l
  10. |2 (GPIO3)                   (GPIO0)15|" k; x. K* M. h
  11. |                                                        |9 f0 F% f7 w* G: Z
  12. |3 (GPIO4)                                  14|0 c+ e; c1 D: n; o2 N# t5 V, Q
  13. |                                                        |5 N6 e/ D9 g: v0 H/ e
  14. |4 (GPIO5)                        (DATA)13|
    ! J* e. q6 R* ^# K$ n
  15. |                  STC15W204S                |
    + K6 r  \  |5 i4 x+ D( K, U
  16. |5 (GPIO6)                   (LATCH)12|
    + N; r  u1 D8 \4 W
  17. |                                                        |
    , V) g) s, k# B7 _. R6 t
  18. |6 (VCC)                         (CLK)11|3 A) ?/ G, T# ]
  19. |                                                          |+ L% E% g" i: m- v" a$ ^0 s
  20. |7 (GPIO7)                         (TXD)10|
    & W. \4 V( r# q' o, x
  21. |                                                        |3 K7 D. ]: }; t# a7 J
  22. |8 (GND)                         (RXD) 9|  l: I) S- |$ G& o0 q5 b
  23. *---------------------------*
    , q: F" n" t3 ~
  24. Fosc = 12MHz' D+ P: g. n( R6 V+ [. ?: A, ~

  25. 1 F' _; F$ X" W9 Z! w4 u
  26. P1.0 -> 上. m+ L+ A% K# @, d
  27. P1.1 -> 左
    8 I" w( ^* b  `6 H2 B, n% h4 t
  28. P1.2 -> 下
    ( t8 S# ]- d% D! e& x% `
  29. P1.3 -> 右
    0 F5 h+ A7 H2 g7 B
  30. P1.4 -> SEL
    & E' Y% X* a# d0 ^* R
  31. P1.5 -> STA) ]1 P2 l* [! `! y, Q
  32. P5.4 -> B
    9 ~7 x) n( i; c* b: `
  33. P5.5 -> A9 s5 z$ P4 u6 y! I- ^$ S9 e

  34. * p) J+ D+ h5 ~+ M' V2 {7 M9 V( T" b2 A
  35. */
    3 V* B8 E9 P1 i8 C

  36. & v7 R! e- p8 W# _

  37. ' @  |: A/ }! p# Z
  38. sbit CLK        = P3^2;) Y+ m# L( s5 z
  39. sbit LATCH        = P3^3;
    6 ^; @2 [' {9 a2 ~: f; Q0 E: {
  40. sbit DATA        = P3^6;* M8 A* Y- j: v5 A( X
  41. 7 O1 D2 s) ^# M4 D5 H) `, @( S
  42. bit isReady = 0;
    4 w. y% p( z3 R9 s
  43. static unsigned char key = 0;
    9 e8 h) s) x6 p! E2 k
  44. static unsigned char buf = 0;        // 双缓冲。这个缓冲区保存从P1和P5组合而来的键值
      p7 w1 O  u+ B4 J+ g
  45. static unsigned char bufReady = 0;        // 双缓冲。这个缓冲区保存上面那个缓冲区的备份
    : L8 ^  h8 n3 k5 F. d
  46. static const unsigned char data mask[] = {0x80, 0x40, 0x10, 0x20, 0x01, 0x04, 0x02, 0x08};        // A B SELECT START UP DOWN LEFT RIGHT。为提升速度,这个表放到RAM中
    , u" p+ ?1 g3 y9 s9 k( O  j
  47. static unsigned char idx = 0;
    " M! M6 K, |0 L# A6 W, @4 P6 f! w
  48. 2 S4 l+ Y$ b! n8 v4 C( e" |5 H

  49. 4 Y0 Z9 g! J) R) P
  50. static void GPIO_Init(){! y. j- [8 ?# U) k# ?# \  \
  51.         // P1口和P5口用于接收并行信号,全部初始化为准双向,依靠内部弱上拉输出高电平
    4 [6 i) x' O, U- M5 C
  52.         P1M0 = 0;5 @( t* i* F4 O% j1 F. p, @5 U
  53.         P1M1 = 0;
    8 t7 A) `6 Q  C% w9 X+ z
  54.         P1= 0xFF;
    ) s# l  l0 ?5 z- J" Q7 |
  55.         P5M0 = 0;4 h3 `( @6 y6 R/ e' T- \
  56.         P5M1 = 0;; |. T  I3 @3 t. t1 V" t0 t
  57.         P5= 0xFF;* {$ h2 P% {# k5 u$ U4 S) w8 `7 \
  58.         // P3口初始化为准双向
    ( f: U( o0 x) a0 r# a* m5 G
  59.         P3M0 = 0;
    % M0 `0 c' W: v9 `4 C+ P) \, m# t" J
  60.         P3M1 = 0;
    6 ^- z: m) d) k( G$ I. z
  61.         P3 = 0xFF;
    " _2 r" [2 {& x+ g
  62. }; r! r' t/ Y% _* P; U9 Y
  63. 5 @+ X2 N2 P+ L- B  U& F9 @: U
  64. static void Interrupt_Init(){9 r3 }2 }  H6 v3 P5 m2 j
  65.         // INT0中断(CLK)触发类型为上升沿+下降沿
    3 y0 Y9 `1 t( X: k- ]1 i7 O
  66.         IT0 = 0;4 N, L* L/ ~$ L0 }
  67.         // 允许INT0中断" d# D, X# R" W* H) K. n# j& @4 J
  68.         EX0 = 1;4 P' O3 u; `0 N
  69.         // INT1中断(LATCH)触发类型为上升沿+下降沿
    ) G: g+ J  A0 z3 Y& C
  70.         IT1 = 0;/ M2 b3 ~/ G0 m' K# T
  71.         // 允许INT1中断& F% P2 ^. n* C
  72.         EX1 = 1;
    1 N( ]  r* S+ Y9 c
  73.         // 开启全局中断4 U/ \: D. C' ?/ K- m5 R: m, P* `
  74.         EA = 1;
    / }: c1 }" |8 j0 P4 h9 f* W) K
  75. }
    . ]) Q% f% `, j! D' k! z' E" j9 ^
  76. % h" A8 i! M' e* o/ q
  77. static void INT0_Isr() interrupt 0{' ?0 r% d% O% I, x* s7 k) J. T
  78.         // 只有已经成功锁存才允许CLK移位/ }5 x! U- Z- Q; ]/ C
  79.         if(isReady == 0)
    , X" }' [% C& r
  80.                 return;
    ) b* ]. l, R: s; Q2 P
  81.         // 读当前引脚电平,如果是低电平则说明是下降沿,此时直接忽略该中断
    , E' g) ]6 X& ?! c, w) f: J0 @
  82.         if(CLK == 0)
    2 T/ X3 A. g# D+ T% n+ N& Y0 e
  83.                 return;
    0 v4 y8 ^5 W  n
  84.         // CLK上升沿到来的时候,取锁存值的下一位输出$ t9 ?8 N  P" y# W5 y
  85.         idx++;
    ! K/ h- P0 s, y
  86.         DATA = key & mask[idx];8 L3 |/ p3 S* S# I
  87.         // 如果已经完成7次移位,则一轮读取完成% O2 R, @. R. v- v( K7 Z$ T
  88.         if(idx >= 7)! p5 L# l; P# R  t( n' Z
  89.                 isReady = 0;. y0 m4 W! W. H, @+ ?7 z
  90. }6 w7 Z# n6 o+ G1 X6 j8 T& [( i: G0 y
  91. % u) T/ i( N- b
  92. static void INT1_Isr() interrupt 2{
    & c3 k  M) M. i
  93.         // 读当前引脚电平,如果是低电平则说明是下降沿,此时直接忽略该中断6 ^9 q+ ^$ ^% n  x/ P- w8 ]
  94.         if(LATCH == 0)
    , }4 Z$ `1 l! Y; U* l3 a0 @% c
  95.                 return;
    ' Z; a& _& ]& W$ b" z: _
  96.         // 当LATCH上升沿到来的时候,锁存所有按键状态,同时把键值A输出到DATA
    9 M" @0 t3 R/ @3 C3 }( R( t
  97.         key = bufReady;) }8 i% {, w5 b% C$ K
  98.         DATA = key & 0x80;//mask[0];        // 为了加速运算,直接取表中的值而不是读表
    . J5 e2 _; H3 W$ o- F& V- `
  99.         idx = 0;
    9 r4 |8 Z0 q7 Q1 t: h
  100.         // 允许CLK进行移位
    4 z  }1 U. O: |1 n; e
  101.         isReady = 1;' ]- L4 V# w% w
  102. }0 m+ c! J% G# G+ ?3 T/ G9 g

  103. # Y4 ?, H/ X! X( h* G; s+ V2 |0 h/ d
  104. void main(){
    2 n8 V! W# ]+ p4 I+ A1 m8 }
  105.         GPIO_Init();3 k( _4 ^, a& Y  h- `5 H+ m
  106.         Interrupt_Init();6 h9 y% ~( j7 P' M2 \, ~3 b
  107.         $ [% G4 a$ m; j8 G2 G* y" p2 \
  108.         while(1){# s  C4 ]! V! _) S
  109.                 //PCON |= 0x01;        // 进入省电模式0 |" Q4 [1 \7 R5 ?2 N
  110.                 //_nop_();
    - H( U8 Y0 v: L4 {4 X/ }+ P9 ]
  111.                 //_nop_();' s  Z, v9 _& b
  112.                 //_nop_();/ X1 ~& i9 f! {. q  C
  113.                 //_nop_();
    + Y: t/ r) O5 p9 p" d7 m
  114.                 buf = ~((P1 & 0x3F) | ((P5 << 2) & 0xC0));: L9 I# K$ `% M
  115.                 bufReady = buf;
    6 u$ I* ~& a) `: [$ z3 c
  116.         }
    5 W6 E6 y2 ]% M# x
  117. }! }7 a! S5 ^2 n1 c- {2 }' c
复制代码
! G+ [" j" f) ]+ V! h
硬件参数配置无特殊要求,晶振频率选择12M即可。3 i7 g) H2 q6 t' S9 k% y8 u. D
( [/ o2 `6 U& A1 f5 ]  c
这是编译好的固件。

本帖子中包含更多资源

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

×

评分

参与人数 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, N+ u' p; o" U. C4 p6 h  r
不错的设计,想问一下楼主,FC的15针公头怎么解决?普通的公头太短了,插不进去FC的扩展接口。 ...

! P5 O1 y0 z) t) e% ?# ^; T7 h坛友的改造方案
回复

使用道具 举报

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

使用道具 举报

发表于 2019-5-25 12:07:18 | 显示全部楼层
精彩,楼主动手强,也写得很详细。# C6 V, }- e4 J
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:078 l/ l9 a- y- B  b
精彩,楼主动手强,也写得很详细。/ B5 j  V& Z1 h5 I! A. A3 R9 O
2.4G方案是目前无线的最低延迟吗?
8 P8 y/ K3 q/ E+ D) a7 z1 @2 N& @, Q
我没用过其他无线手柄,所以实在不知道我自己做的这个手柄到底是不是最低延迟。
% ?8 {& |& L9 o不过根据网上的说法,延迟高低主要是由通信协议的复杂程度,以及数据传输速率决定的。这个模块虽然是2.4G无线模块,但由于协议很简单,所以延迟比较低。
. k% }6 p' Y; t( e0 i- z2 B6 H我用这个手柄玩一些ACT游戏,比如超级马里奥、忍者龙剑传、热血系列,完全感觉不到延迟,和游戏机自带的手柄没有任何区别。唯一的区别就是这个手柄是用火花山寨手柄改造的,外壳是垃圾回收塑料,粗糙+脆弱,导电橡胶弹性不佳,手感不是一般的差。( F/ J: D9 r5 x4 U
我手里还有十几张板子,等我有空了我再做一套,到时候买一个好一点的手柄改造。
回复

使用道具 举报

 楼主| 发表于 2019-5-29 16:56:14 | 显示全部楼层
ppad 发表于 2019-5-28 17:27! o0 i2 z6 p' i9 y4 ^
给技术帝赞一个,有半成品发布吗,自己焊接改造就可以,编程实在不会啊 ...

2 D( M3 t+ M1 D& c5 S' k很可惜,我手里没有多余的单片机了,LDO也找不到了,锂电池以及充电模块更是没有了。反正就是该用到的元件基本都没了,所以没法发布半成品。9 O( T  Z- i# U- R; H) a
两个板子倒是有十几张剩余。
3 \% m. Z. H# a8 f  L2 c1 l你要是有USB转TTL串口板,完全可以自己买这两种单片机,然后我给你编译好的固件,你自己用串口板下载到单片机里面就行了。两个2.4G无线模块也得通过串口板用AT命令设置参数,不过好在我在设计电路的时候就已经预留好了串口,可以直接在线下载和在线设置参数。总的来说并不麻烦。
回复

使用道具 举报

 楼主| 发表于 2019-5-29 17:00:34 | 显示全部楼层
孙大师 发表于 2019-5-28 18:55
6 Q% B7 D! ^; }非常好,楼主是技术帝,到目前我都还没开发fc的无线套件,等空了,开发一套套件,等玩家自己组装。 ...
4 [  w0 E  m9 L% h' v! \
能得到孙大师的赞誉,不胜荣幸!
4 v' g3 L9 u3 y: m2 Q& E6 Z不如开发一个多功能手柄,比如用SFC手柄改造,L/R键配合其他组合键可以用来切换2P~4P、调节连发速度、软重启等各种功能。接收端插到15PIN扩展口。
回复

使用道具 举报

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

本版积分规则

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

GMT+8, 2026-5-30 08:27 , Processed in 0.122866 second(s), 14 queries .

Powered by Discuz! X3.5

© 2001-2025 Discuz! Team.

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