找回密码
 注册

QQ登录

只需一步,快速开始

查看: 24615|回复: 32

自制FC无线手柄

  [复制链接]
发表于 2019-5-22 14:16:45 | 显示全部楼层 |阅读模式
本帖最后由 雷精灵2046 于 2019-6-14 09:28 编辑
8 ]- C$ l6 B. {4 n$ U% V3 R1 v# Z- R
没有用复杂的分立元件搭建发射接收电路,直接用的现成的2.4G无线模块jdy-40。) E. g3 k/ A" A- ^. D6 k' w- z
9 Q  z* L: s4 j3 g
& T& L, F+ G. `. Y+ I. k
发射端靠3.7V锂电池供电,用了一片SOP8封装的STC单片机,负责产生连发脉冲,同时负责检测电池电量,电压低于3V左右的时候触发低压中断,低压指示LED就会亮起来告知该充电了。平时发射模块和单片机均处于睡眠状态,有按键按下才会唤醒,从而实现省电。实测睡眠状态下整机电流约1~2uA。板子洗了一下稍微干净了一点。因为对于微功耗设备来说,焊接残余的助焊剂可能会增加漏电流。
8 z9 N7 [; a, ^3 X4 z8 d
; |+ n1 ^; L; J" \% n7 ~0 b买了一个火花的FC山寨手柄,去掉里面的牛屎板子,并修正一下塑料挡板,把锂电池和充电模块装进去。
5 Y) h4 T  X  p% [3 Q# m. _为了减少体积,充电模块裁剪得十分小,并且更换了充电电阻使之适应这个小小的锂电池。这么小容量的电池,也不需要多么大的充电电流是吧?
' Z# s) V: @' h6 I/ {* ~然后统统用热熔胶粘上。充电电流比较小,所以发热很少,不会熔化热熔胶。
0 d8 g$ I3 p$ o$ B1 C+ H" h
; U; Z6 k3 v. a  \) {6 _
$ q" E! Z. G, ]+ t. n8 M& U% [' m
最后把按键、导电橡胶和电路板装上去。
- p) [! f) o5 p/ V精心裁剪了电路板,正好扣上,不会阻碍其他元件,也不会影响后盖和拧螺丝。6 E1 {$ v  N7 ~8 n+ c4 `' l+ `& r

; v6 m- g% d- X
0 J3 ~6 Y& ~' g完工!% R6 Z$ g6 t9 s( v9 ~- K, D8 w3 w
) y# ~  j% `8 q, ]- @, D4 z0 S

* U& F2 T$ b( B3 v& I这是充电的MicroUSB插座。旁边的小孔用于透出低压报警LED的光线。
; Z  u9 T0 S8 }. x* s3 ]
) k! R# c% O+ Z, O$ B& A# ]+ @% Q9 K" V$ O; S& ~
接收端用一片DIP16封装的STC单片机模拟CD4021。为啥要用单片机模拟而不是直接用CD4021?因为jdy-40模块接收端在有按键按下的时候输出高电平,无按键按下输出低电平,和普通手柄正好相反。当然我也可以用两片74HC00或者74HC04之类的逻辑门进行反相,但那就增加了芯片的数量。对于FC手柄这种工作频率并不高的设备来说,STC单片机完全可以胜任模拟工作。/ I& P' ?& f; c$ x# S' m8 _1 x

; j1 w$ n0 S9 }: ?/ p/ T; R
5 B, S' h' j; _" Z6 K& @& s& j) A+ R
电路设计有点小小的错误,所以有几根飞线。原本设计使用低压差LDO是XC6206,结果在做这个接收模块的时候,买的LDO居然找不到了!无奈只好用了AMS1117。幸好对于接收模块来说是5V降到3.3V,1117可以胜任。要是发射端手柄的话,3.7V降到3.3V,那就非得用6206不可了。( s! v3 j3 P' h- Q# b

) P; S& S, b! W, o/ l9 N! s实测十分灵敏,延迟极小几乎感觉不出来。可惜这山寨手柄的手感并不佳,尤其是方向键,软塌塌的。看来我得买个剪线手柄改装。
! \$ i0 G9 h( F( l9 B( V/ h
" q3 L4 [, F/ G+ ^9 `这是电路图,有兴趣的朋友可以参考。8 O5 H& z  b8 @' B. T

8 B# P8 x" G8 a5 q/ R8 X/ y6 G. P; Q# d; D. A, c
我信奉开源主义,十分痛恨把技术藏着掖着。好东西大家分享嘛!所以两个单片机的源代码大公开!
0 H5 B% S; Z* W* L6 A# Z. B编译器:Keil 51。
9 E7 {, R6 ?( Y. i- F. a
0 j* p7 i1 d  |. |5 }$ N发射端:
9 r& L; i1 b+ r6 g4 p  P
  1. #include <INTRINS.H>
    3 \( A7 Q& ]; w/ d2 P
  2. #include "STC15W.h"
    0 N/ H2 I# Q* z/ s& q3 |1 {( a- Q

  3. $ [- x- O; U; C6 k  n% n
  4. , c5 t+ p' n' h2 f/ _4 y6 L  @
  5. /*4 u) U, U7 ]4 d/ S$ g
  6. --------------------------
    % Q4 i: P9 f* l
  7. |1 (OUT)        \__/   (INT1) 8|0 G  Y% x& [! [* N( S6 Y
  8. |                                                   |
      q3 K+ T" b. s" p( a) N: e; j
  9. |2 (VCC)                   (INT0) 7|
    3 M# m* _) U5 \1 v- x
  10. |                 STC15W204S                   |
    ! ^0 F4 D' x/ `+ M, t3 e
  11. |3 (LED)                         (TXD) 6|
    7 k( T5 G) Y* G
  12. |                                                   |
    ; q8 m$ v) `  L
  13. |4 (GND)                         (RXD) 5|8 U% l) o# `1 H- J, k# [
  14. --------------------------0 o2 ?' P& G& f+ ~( |' p
  15. $ b: T0 `# A/ }6 G2 K2 e$ z
  16. LED ---|<|---[===]--- VCC
    : n, q4 J& e( l$ N
  17.            Red          330
    # Q* v2 b7 m  N/ q
  18. 7 P- X7 A" A* U3 T* N
  19. Fosc = 6MHz/ \+ \; S2 g+ U: P
  20. */0 v  Q5 V+ m! P/ `3 m

  21. ! ?% m" T: |* t

  22. 8 N. J7 [5 K: C" K" u& D/ w, l: z
  23. // 矩形波输出脚
      |4 _, L: m  s9 r* ?9 o* l4 A
  24. sbit OUT = P5^4;
      m. S6 \2 r; c: v" }, J
  25. // 低压指示灯引脚
    ' C" H9 I& F7 a' }9 `; ]$ T* q
  26. sbit LED = P5^5;" E3 _4 X% i( d: ^& K

  27. , f- ?* t1 K8 M
  28. // 停机标志位" o- @" T8 P; D& }
  29. bit isReadyToHalt = 0;
    2 I0 i, H% j# s9 K# x$ _

  30. - `8 Q. h! E9 G9 i0 {5 p8 O8 ]
  31. // 矩形波次数累计0 }# T+ h/ t6 Z: I; y7 x
  32. static volatile unsigned char count = 0;
    3 y/ [0 m' |) X/ N
  33. 6 C2 x+ K, i  m+ C1 ~' J  Y0 R

  34. ) o) V. _! j7 h8 b
  35. static void GPIO_Init(){# o6 J8 S; H* I+ @/ U" W0 j
  36.         // P3口设置为准双向,默认靠内部弱上拉输出高电平; M" n5 f  @4 k, t6 b
  37.         P3M0 = 0;, K# F3 l. c& f0 V7 N2 i" Z
  38.         P3M1 = 0;
    ( i5 |  \$ U, Y9 X( z2 T% E1 b$ k
  39.         P3 = 0xFF;
    ( i6 s+ o# h  |" ]! _, I7 g" Q
  40.         // P5口设置为准双向,默认靠内部弱上拉输出高电平+ k  m2 r$ A0 Y' O1 G- R$ x7 O
  41.         P5M0 = 0;) D$ }& U' D  `/ ?" h
  42.         P5M1 = 0;. ^0 m, p* ]2 r  H
  43.         P5 = 0xFF;" ^6 P7 I  G# c, G1 y( g2 s
  44. }" J2 Y+ ~' ^* W" k5 P0 J( g

  45. 8 [  S. P( r3 B* e3 B9 I8 k1 m
  46. static void Timer0_Init(){
    ! _0 I- }9 y' T4 d, W6 s
  47.         // 16毫秒@6.000MHz
    / [" S, j" D/ G% c4 G; G; d# c! H7 Q
  48.         AUXR &= 0x7F;        // 定时器时钟12T模式/ h2 `' h! B; U: G# {$ z& I
  49.         TMOD &= 0xF0;        // 设置定时器模式2 }0 N) w7 E" H2 m5 ]# |0 v! t) k
  50.         TL0 = 0xC0;                // 设置定时初值. V0 d4 {  w2 ]  m3 s; H, `
  51.         TH0 = 0xE0;                // 设置定时初值
    / ~+ y$ r- ]/ U- E' X; s7 B( ?! l
  52.         TF0 = 0;                // 清除TF0标志
    $ P8 q, ~8 o& M" `. \+ i
  53.         TR0 = 1;                // 定时器0开始计时' B" k. r  r% o9 @  E% u
  54. }3 ~7 L0 m$ p' l6 |& f& L7 v

  55. ; g1 @/ @9 g$ B. b* L- I
  56. static void Interrupt_Init(){( I3 \1 n) B! `( W; B, v) I! d) ^
  57.         // INT0中断触发类型为下降沿触发0 ^- T2 w7 x( g
  58.         IT0 = 1;
    # {! i1 m/ R" n* `  O
  59.         // 允许INT0中断5 R  S0 Z4 k+ Q) Y: Q. D) Z
  60.         EX0 = 1;; Z1 ^2 g1 Y% I) O/ N8 L# @
  61.         // INT1中断触发类型为下降沿触发+ [/ |2 u( N6 [+ A/ E, U4 @
  62.         IT1 = 1;9 ~) ^3 C( b9 ~3 x/ N0 H
  63.         // 允许INT1中断
    8 A6 ?- i; H2 G- N& T
  64.         EX1 = 1;
    6 [7 t) G  V# @. n- {
  65.         // 允许定时器0中断
      v6 }2 M5 K8 W' l
  66.         ET0 = 1;1 q' |, a: k+ G  R3 U
  67.         // 允许全局中断& u) v7 q& Y- v6 ?5 m8 E
  68.         EA = 1;) M( _3 T; c$ Q
  69. }, b9 s- z/ Q! d( M' k9 q/ M( S
  70. ' x" ]/ `: ~' G* a* }1 }
  71. static void INT0_Isr() interrupt 0{
    . I1 h* V+ e- L8 x( ^5 I/ U2 U
  72.         // 矩形波次数累计归零( S/ y0 M0 t; b/ s$ s: l
  73.         count = 0;
    $ J. z( ]4 b/ H4 n2 h1 J4 T
  74.         // 重开定时器0中断
    5 B& g, H) P0 }/ a0 p( V$ R
  75.         ET0 = 1;" a% t! M# e& o) }
  76. }. ^6 L# Y, Y* B, I# H
  77. # @+ F: m0 r- T6 C7 [
  78. static void Timer0_Isr() interrupt 1{6 V' K2 x# v5 n9 @
  79.         // 输出矩形波& a' @/ ^( ~" C% I) K$ \7 e
  80.         OUT = ~OUT;$ v+ }4 j, B" F3 d
  81.         // 累计矩形波次数; Y' Y! R0 p7 m2 n3 ?
  82.         count++;: @# q) w7 L$ [: W( }5 p5 {
  83.         // 超过250个矩形波,准备停机
    # U2 v0 h- ~. v% ?" f( j
  84.         if(count > 250){1 [# U( i  W0 y& Q, C
  85.                 count = 0;
    ! r; w6 c) F% n  X
  86.                 isReadyToHalt = 1;
    / k: a9 B3 }$ x( t" V2 T
  87.         }
    ( n$ Y" C& I1 J5 z1 [
  88. }
    & ^% f3 j0 C3 A% U. w0 V  |
  89. ; A- G& c: a5 U) B* P  A5 D
  90. static void INT1_Isr() interrupt 2{- y- _2 f$ `6 v/ L, g5 M+ g
  91.         // 矩形波次数累计归零' y7 {2 g$ i/ l0 N0 O5 M( e
  92.         count = 0;
    " ]8 y; s# [9 O$ V$ }
  93.         // 重开定时器0中断
    6 Q2 R$ H- {/ s! L
  94.         ET0 = 1;
    8 ~% a  E$ F  v; @3 f5 r* l
  95. }
    : B, k9 p" x- H4 s9 N8 c0 }

  96. $ X& Y( _/ Y! i  T: }" R
  97. 1 B4 d+ ^& @0 U( g* Y
  98. void main(){
    2 f- \: [& N8 ^; S
  99.         // 初始化P3和P5口5 o  ?3 a3 e' s; ~( V; h
  100.         GPIO_Init();
    * l! R5 B$ Z! j9 ?& {
  101.         // 初始化定时器0/ o+ o# M8 X7 b/ H6 e
  102.         Timer0_Init();3 y2 m* K+ c7 x, z
  103.         // 初始化中断# y$ Y& h1 x7 C7 z- f4 H
  104.         Interrupt_Init();
    - W$ Y, Z2 j8 L# n! M) f. H
  105.         5 D/ y  s( x, i
  106.         while(1){. @" U# M4 Z2 I
  107.                 // 检测电量
    ) q: P" I6 h- U0 i
  108.                 if(PCON & (1 << 5)){/ d0 t; Q7 ?! m* G+ h- K* }5 v
  109.                         // 如果电量低,低压指示灯亮  x* Z& l, E9 S$ J0 r+ E7 v' l. m* B
  110.                         LED = 0;
    5 r# M. X( s1 c/ R1 l
  111.                         // 清电量检测硬件标志位2 l6 N6 T8 P' a2 r" R
  112.                         PCON &= ~(1 << 5);
    . T% ]  H- `+ {, T4 n
  113.                 }else{' ^" ?4 v9 ~) p8 a" e+ n
  114.                         // 电量正常,低压指示灯灭
    1 ~1 x% A" V, z, C, y
  115.                         LED = 1;% f4 g5 q" n: y, f
  116.                 }
    " ?; V, A" _# ]& f$ X

  117. % B9 x0 w3 O* z
  118.                 // 检测到停机标志, z" _3 ]3 h+ Z
  119.                 if(isReadyToHalt == 1){( r( N5 o0 p' w
  120.                         // 暂时关闭定时器0中断. ~6 x3 v9 t, ^: @' B3 B+ F% G% ?
  121.                         ET0 = 0;* O: K5 q7 j+ r1 \9 e
  122.                         // 停机之前先把矩形波输出脚置低电平,以方便INT0和INT1唤醒CPU
    , s' U  x8 F/ }" Y! \
  123.                         OUT = 0;
    2 {$ X6 ^' v& z& x9 ~  O; D
  124.                         // 停机之前先把低压指示灯灭掉,以省电
      J0 {2 `4 E' k% `
  125.                         LED = 1;$ e* k1 H2 a4 v7 M2 m- N
  126.                         // 进入停机模式
    ; x; P, N0 W/ F$ a- j% [
  127.                         PCON |= 0x02;
    2 S" i; T* u* B2 |( N5 `+ Z
  128.                         _nop_();
    # g' W1 J9 K6 H& \& A
  129.                         _nop_();$ d1 @$ C& P3 Y; }
  130.                         _nop_();, }; ]0 b( Y+ G  D
  131.                         _nop_();
    / H2 o; a' n# C; R2 C3 f
  132.                         // 唤醒,清标志位
    6 `4 t1 W7 b0 b1 f1 E2 ?
  133.                         isReadyToHalt = 0;3 s8 ~; F8 k6 [
  134.                         // 重开定时器0中断4 ~! G; U* P3 R! ~# }
  135.                         ET0 = 1;9 c: _; e8 ~' `' Z' g* b
  136.                 }- p5 G: r/ j! X! s( @4 w0 s& ?, S
  137.         }
    $ q, V0 |" W! ?
  138. }. e. ~8 L4 E! \5 A5 Y7 R4 Z
复制代码

$ U! {1 Q7 d& R% Y: y/ }5 `- `硬件参数配置:/ b# E! [9 U+ I  d* ]
3 B4 }' C0 J% N7 X9 Y6 B: v
1 k, T' ]/ Q- A5 \! W# W
接收端:
6 V' C2 R8 M# x* Z  P4 k
  1. #include <INTRINS.H>
    ) l4 E* O8 b/ z$ o
  2. #include "STC15W.h"
    4 |% S' A& b7 {4 o8 k

  3. # f: q* t8 Z" b
  4. ( {8 C6 U2 ~0 b* @
  5. /*
    - h( L4 T* m/ t! g% H

  6. 1 h: i& w# _7 j
  7. *---------------------------*
    3 {, n, D+ q5 b7 c; f. V
  8. |1 (GPIO2)         \__/  (GPIO1)16|
    * h) f- B& M5 G+ s
  9. |                                                        |
    : i+ @. z( R! \  G/ ^0 j
  10. |2 (GPIO3)                   (GPIO0)15|' D( e" `& I6 A5 d1 n' o' M
  11. |                                                        |7 S- u8 e& ^4 a' ?
  12. |3 (GPIO4)                                  14|( s. E& t% o$ t2 }# P9 i" C
  13. |                                                        |9 j* B* ~( d# e5 I
  14. |4 (GPIO5)                        (DATA)13|* x2 f6 [5 Y) e
  15. |                  STC15W204S                |
    ( _4 i* E( X2 M3 {
  16. |5 (GPIO6)                   (LATCH)12|
    * l- L4 I' V6 E3 v
  17. |                                                        |% ?2 l5 z9 t, n0 H
  18. |6 (VCC)                         (CLK)11|
    * X; D4 e' t' @" G  O
  19. |                                                          |3 Z% N+ g: B9 V* C# z- W( k
  20. |7 (GPIO7)                         (TXD)10|  a3 d8 T0 v, i$ X4 s) i
  21. |                                                        |
    & ^0 c: G, Z4 V  N0 X" e1 I
  22. |8 (GND)                         (RXD) 9|
    - Z3 T7 |9 I% y# j
  23. *---------------------------*, c" y- k* w3 h1 K4 K
  24. Fosc = 12MHz
    6 Z/ M6 t4 G, p- S4 o
  25. ( R, @# _+ F: h" l9 ^# B
  26. P1.0 -> 上
    9 _/ R" n1 `% Y/ P4 N
  27. P1.1 -> 左8 F3 }" b9 _+ i; B- }
  28. P1.2 -> 下
    5 u' M4 ^7 `1 U; R% P4 t
  29. P1.3 -> 右# m3 o- N4 w5 K
  30. P1.4 -> SEL) t; s0 a, [8 `% K; R$ S0 @5 o& ~
  31. P1.5 -> STA
    * w/ o3 O# w0 m$ y: m$ @& Y( p# I
  32. P5.4 -> B7 f( Q/ l& o, a( I, x
  33. P5.5 -> A
      t* H5 y- W0 H+ ^7 O
  34. * O3 ?$ Z" r: k; L5 Y
  35. */1 `6 Q+ L# w) k
  36. + W3 ^5 e: [; H8 f

  37. ! s& \& Y) |  a1 z4 Y
  38. sbit CLK        = P3^2;
    : ~0 e! ]0 t* J) L7 s( m- s
  39. sbit LATCH        = P3^3;4 @% c8 C- N  }5 E$ p+ E4 w6 y3 X! F
  40. sbit DATA        = P3^6;" Q" Q1 _$ R. k! c/ a9 a: [* {

  41. 7 Y/ C6 y# f8 x" l' u
  42. bit isReady = 0;
    - J, F4 a4 ?8 Q8 P! }+ o, D3 S
  43. static unsigned char key = 0;
    7 Z7 S) V) x) j1 [. f( N2 r
  44. static unsigned char buf = 0;        // 双缓冲。这个缓冲区保存从P1和P5组合而来的键值, q: I+ ~& O+ m9 `
  45. static unsigned char bufReady = 0;        // 双缓冲。这个缓冲区保存上面那个缓冲区的备份1 n/ h% ]& N7 l; j: L
  46. static const unsigned char data mask[] = {0x80, 0x40, 0x10, 0x20, 0x01, 0x04, 0x02, 0x08};        // A B SELECT START UP DOWN LEFT RIGHT。为提升速度,这个表放到RAM中
    0 g& r5 _- q4 D* P/ K/ r, F
  47. static unsigned char idx = 0;) i/ E; r2 i/ h) }* S6 o5 Y1 \/ Y

  48. ' i4 H: T# ^7 w2 q
  49. - P9 u1 x$ F" n
  50. static void GPIO_Init(){4 d" u( _5 C, e- T* R2 H, Q
  51.         // P1口和P5口用于接收并行信号,全部初始化为准双向,依靠内部弱上拉输出高电平$ U. y* i4 F, k% ?( b7 _7 K2 g
  52.         P1M0 = 0;' v; k5 a) C, q+ O
  53.         P1M1 = 0;9 S7 j" z: |# e0 C1 U& _
  54.         P1= 0xFF;5 C/ Z+ Y7 @0 G( d9 ~
  55.         P5M0 = 0;
    # U% q6 m9 x+ I% q2 M9 ?
  56.         P5M1 = 0;  U9 m  T) l+ t" p/ Y, t- M
  57.         P5= 0xFF;/ A( i7 O, x( N  `" \
  58.         // P3口初始化为准双向4 c" z6 o- A4 P4 l; D1 S; E5 ]
  59.         P3M0 = 0;1 t7 v8 t) I8 q  L& h, R/ p  Q
  60.         P3M1 = 0;' F+ p# D" v$ U7 P# T/ x: M3 j! A
  61.         P3 = 0xFF;! r! ~9 ]: v4 K% ^! {$ d5 H7 M7 V$ Y/ f
  62. }& e! T% E8 J; |

  63.   u3 [6 I  M2 V8 d  O  ~: t
  64. static void Interrupt_Init(){
    " z% p- Q6 G1 D' t5 c2 @, Y6 d1 N
  65.         // INT0中断(CLK)触发类型为上升沿+下降沿" L$ L& o7 {9 k8 Q- \
  66.         IT0 = 0;  F- x3 C4 h) P9 Y
  67.         // 允许INT0中断
      \6 v' E" w8 D4 V
  68.         EX0 = 1;
    # I# l7 @! A) g7 b' I  u2 h
  69.         // INT1中断(LATCH)触发类型为上升沿+下降沿( l4 \  @% `% T
  70.         IT1 = 0;
    7 O. |' t3 y+ g" |
  71.         // 允许INT1中断
    2 l9 z  _8 x6 `3 D4 v3 V) m
  72.         EX1 = 1;2 S/ Y7 G9 K! f7 P
  73.         // 开启全局中断
    ( h5 x% S# ^# ?5 z# m
  74.         EA = 1;
    3 K' N; i/ p3 Q2 t( {* W2 g% x
  75. }8 a0 v, @# l+ S7 g* F
  76.   K5 w$ H8 \' U+ U. ^3 u0 o
  77. static void INT0_Isr() interrupt 0{
    / w5 V" Q) f$ X$ b0 j0 {5 R
  78.         // 只有已经成功锁存才允许CLK移位
    5 ^- z7 S5 |$ z4 R6 ^& j. w
  79.         if(isReady == 0)
    % m5 v6 ^3 b; v' H4 c
  80.                 return;1 k7 k/ t. d; \& Z1 F9 o7 g1 u
  81.         // 读当前引脚电平,如果是低电平则说明是下降沿,此时直接忽略该中断
    0 Q% S' T& a+ n, k
  82.         if(CLK == 0)3 s7 ~6 S, L1 Z1 U. }# |5 _/ A+ o
  83.                 return;
    # i, v  B& X, S  f2 y
  84.         // CLK上升沿到来的时候,取锁存值的下一位输出
    ! r0 V& V0 @$ ?: S) j) Q& d2 l
  85.         idx++;
    9 p4 D) \% j6 i* J. v3 q
  86.         DATA = key & mask[idx];
    / S! M& N6 ~: o  x" k6 Z" {0 {( ^  f5 h
  87.         // 如果已经完成7次移位,则一轮读取完成
    0 f% B. |3 d7 G& J
  88.         if(idx >= 7)  E% B: k5 D: p4 s4 X5 }8 D' w) J9 ^
  89.                 isReady = 0;
    8 v3 u0 ?* o' |" u5 M
  90. }8 c+ y. X0 M7 I5 ?& q
  91. . E7 S5 ^6 A2 Q, P; b/ _
  92. static void INT1_Isr() interrupt 2{; ^/ @! ^& \# A
  93.         // 读当前引脚电平,如果是低电平则说明是下降沿,此时直接忽略该中断
    $ w; j  X. B. x7 z
  94.         if(LATCH == 0)( F" c2 B7 l7 C2 l5 d
  95.                 return;
    . l1 ~  w4 V' p' W% `
  96.         // 当LATCH上升沿到来的时候,锁存所有按键状态,同时把键值A输出到DATA
    " D8 A4 h* d$ I5 f8 q9 \
  97.         key = bufReady;
    * e- o* F% r. z: Y
  98.         DATA = key & 0x80;//mask[0];        // 为了加速运算,直接取表中的值而不是读表
    0 Z$ |: T: D0 k" A1 x' J
  99.         idx = 0;
    * k: l# b# n/ V. s7 S2 Y
  100.         // 允许CLK进行移位
    6 ~0 R- j8 l6 V; n5 {2 ^
  101.         isReady = 1;5 z; I: _/ l0 n* \1 R: W
  102. }
    : c% r; U# l2 O; \

  103. ; q/ v$ L0 d0 W8 X$ K
  104. void main(){; y& `: V2 @3 Y. X* o
  105.         GPIO_Init();
    % e0 E% f8 M: e7 J6 Q
  106.         Interrupt_Init();
    9 C/ V3 \# _) d* \
  107.        
      @* y. I! l0 v# ?( y& H
  108.         while(1){
    : W3 g/ W8 m6 j4 f
  109.                 //PCON |= 0x01;        // 进入省电模式  T8 L2 @3 v9 `* k  n# B
  110.                 //_nop_();( r) z( Q% q- e5 |
  111.                 //_nop_();4 |+ K* E! ^" f2 a% m! Y, Q8 K
  112.                 //_nop_();
    + y6 p0 N, i1 ]* t* }( n. B0 R
  113.                 //_nop_();
    9 G* w; I, B( }6 f
  114.                 buf = ~((P1 & 0x3F) | ((P5 << 2) & 0xC0));
    + T4 [+ O: r, `! k1 f/ l  ^& W3 T
  115.                 bufReady = buf;
    2 m/ T8 N; o  }/ E- H- ?5 ?
  116.         }
    5 ]& D, e/ H, K! d, ]& M$ m- S
  117. }& ~9 l0 B9 C: y7 y
复制代码
+ k8 |. i# I8 Z
硬件参数配置无特殊要求,晶振频率选择12M即可。
1 A7 _* K$ N5 k: y3 S, J( J1 J( L/ w! i: @
这是编译好的固件。

本帖子中包含更多资源

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

×

评分

参与人数 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
1 p2 z  g; I4 @# z不错的设计,想问一下楼主,FC的15针公头怎么解决?普通的公头太短了,插不进去FC的扩展接口。 ...

6 @% \. j7 h! X6 X3 l* _0 J坛友的改造方案
回复

使用道具 举报

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

使用道具 举报

发表于 2019-5-25 12:07:18 | 显示全部楼层
精彩,楼主动手强,也写得很详细。
# {. g0 T: {: N2.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& x( U, V" e6 m( E2 O  A
精彩,楼主动手强,也写得很详细。
1 G" Q! g- W+ }1 z+ k7 s! Z. n! z2.4G方案是目前无线的最低延迟吗?
  c  E6 q9 c8 Z7 A8 T% K
我没用过其他无线手柄,所以实在不知道我自己做的这个手柄到底是不是最低延迟。
/ J5 K4 M( q/ Q4 N不过根据网上的说法,延迟高低主要是由通信协议的复杂程度,以及数据传输速率决定的。这个模块虽然是2.4G无线模块,但由于协议很简单,所以延迟比较低。8 z7 @/ x% C& G* M4 s
我用这个手柄玩一些ACT游戏,比如超级马里奥、忍者龙剑传、热血系列,完全感觉不到延迟,和游戏机自带的手柄没有任何区别。唯一的区别就是这个手柄是用火花山寨手柄改造的,外壳是垃圾回收塑料,粗糙+脆弱,导电橡胶弹性不佳,手感不是一般的差。& P2 B: s. \4 B# J" q
我手里还有十几张板子,等我有空了我再做一套,到时候买一个好一点的手柄改造。
回复

使用道具 举报

 楼主| 发表于 2019-5-29 16:56:14 | 显示全部楼层
ppad 发表于 2019-5-28 17:27
, [1 j. E1 D% ~& |- L# @; {: _+ m/ U& G给技术帝赞一个,有半成品发布吗,自己焊接改造就可以,编程实在不会啊 ...
% P- L( C8 `8 }2 j+ Y( g
很可惜,我手里没有多余的单片机了,LDO也找不到了,锂电池以及充电模块更是没有了。反正就是该用到的元件基本都没了,所以没法发布半成品。) j- J. `5 `( g; j+ P
两个板子倒是有十几张剩余。- }* B: v7 m% \5 o. p" ^
你要是有USB转TTL串口板,完全可以自己买这两种单片机,然后我给你编译好的固件,你自己用串口板下载到单片机里面就行了。两个2.4G无线模块也得通过串口板用AT命令设置参数,不过好在我在设计电路的时候就已经预留好了串口,可以直接在线下载和在线设置参数。总的来说并不麻烦。
回复

使用道具 举报

 楼主| 发表于 2019-5-29 17:00:34 | 显示全部楼层
孙大师 发表于 2019-5-28 18:55' ~1 s0 |% r8 [; G" l; `& w
非常好,楼主是技术帝,到目前我都还没开发fc的无线套件,等空了,开发一套套件,等玩家自己组装。 ...
; h' _1 T4 d5 T; g
能得到孙大师的赞誉,不胜荣幸!5 Q' i8 t$ |$ J  y7 _6 e% X' u
不如开发一个多功能手柄,比如用SFC手柄改造,L/R键配合其他组合键可以用来切换2P~4P、调节连发速度、软重启等各种功能。接收端插到15PIN扩展口。
回复

使用道具 举报

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

本版积分规则

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

GMT+8, 2026-4-10 17:31 , Processed in 0.127437 second(s), 14 queries .

Powered by Discuz! X3.5

© 2001-2025 Discuz! Team.

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