找回密码
 注册

QQ登录

只需一步,快速开始

查看: 26770|回复: 33

自制FC无线手柄

  [复制链接]
发表于 2019-5-22 14:16:45 | 显示全部楼层 |阅读模式
本帖最后由 雷精灵2046 于 2019-6-14 09:28 编辑 ( x7 `& O9 S: H" R1 l/ `

8 V6 _6 W7 Q3 s6 Q没有用复杂的分立元件搭建发射接收电路,直接用的现成的2.4G无线模块jdy-40。
0 U! q2 q5 T$ E$ L( v  v! a
0 E2 E+ }" _9 A0 z$ y) [! o8 ?2 O5 m$ \0 w
发射端靠3.7V锂电池供电,用了一片SOP8封装的STC单片机,负责产生连发脉冲,同时负责检测电池电量,电压低于3V左右的时候触发低压中断,低压指示LED就会亮起来告知该充电了。平时发射模块和单片机均处于睡眠状态,有按键按下才会唤醒,从而实现省电。实测睡眠状态下整机电流约1~2uA。板子洗了一下稍微干净了一点。因为对于微功耗设备来说,焊接残余的助焊剂可能会增加漏电流。9 g2 S8 X4 E, \- y
# l( x& {5 v' B( v7 M! ~; C
买了一个火花的FC山寨手柄,去掉里面的牛屎板子,并修正一下塑料挡板,把锂电池和充电模块装进去。
) [# G; M1 t. B5 G为了减少体积,充电模块裁剪得十分小,并且更换了充电电阻使之适应这个小小的锂电池。这么小容量的电池,也不需要多么大的充电电流是吧?, ~) ]9 y: i/ n0 V" H2 B
然后统统用热熔胶粘上。充电电流比较小,所以发热很少,不会熔化热熔胶。9 }& s& Z. z; b" w; I$ G
1 _& }/ y( [1 C: O/ {3 n" w
5 ~8 E# x% A& ?, [
' z3 Y; `* r* s( K2 ]
最后把按键、导电橡胶和电路板装上去。
8 r$ [" t$ J2 s# g0 V6 ?精心裁剪了电路板,正好扣上,不会阻碍其他元件,也不会影响后盖和拧螺丝。+ a$ _5 A6 h/ W3 k

: ]8 p$ o5 s8 t4 P
) {9 d! A- j. m4 |完工!
7 }6 N5 ]4 ]1 R: y& l  |5 t0 J4 D" {% I4 `! ]
8 [; _0 R6 D* S; n& B
这是充电的MicroUSB插座。旁边的小孔用于透出低压报警LED的光线。# w) r9 a0 _2 u$ @( h. ^

: e) Y3 q/ N, ]& a* [8 W9 M
4 g; [& X2 l  a# r接收端用一片DIP16封装的STC单片机模拟CD4021。为啥要用单片机模拟而不是直接用CD4021?因为jdy-40模块接收端在有按键按下的时候输出高电平,无按键按下输出低电平,和普通手柄正好相反。当然我也可以用两片74HC00或者74HC04之类的逻辑门进行反相,但那就增加了芯片的数量。对于FC手柄这种工作频率并不高的设备来说,STC单片机完全可以胜任模拟工作。& c; z' h) a& E: M; ?4 n

5 k1 A. P7 M8 ~7 f2 a* u. M2 f  F& W; b& B( z! }! x
" X( l' X: }9 U
电路设计有点小小的错误,所以有几根飞线。原本设计使用低压差LDO是XC6206,结果在做这个接收模块的时候,买的LDO居然找不到了!无奈只好用了AMS1117。幸好对于接收模块来说是5V降到3.3V,1117可以胜任。要是发射端手柄的话,3.7V降到3.3V,那就非得用6206不可了。5 S5 n7 R0 \. Y
7 v- m' Z. z1 I8 B
实测十分灵敏,延迟极小几乎感觉不出来。可惜这山寨手柄的手感并不佳,尤其是方向键,软塌塌的。看来我得买个剪线手柄改装。
; U% H6 T# I4 J. _/ e5 x# b3 G! K: R4 @% Y3 I# q9 B8 f
这是电路图,有兴趣的朋友可以参考。
3 n: ?  v1 b/ w! g' z& z' L( d3 [6 C& |9 b
- K8 t( ~/ s# U+ h! R( @" i2 M
我信奉开源主义,十分痛恨把技术藏着掖着。好东西大家分享嘛!所以两个单片机的源代码大公开!
# V2 O. L+ J' `$ g编译器:Keil 51。, u7 j8 s9 y7 @
' F& p3 H) E0 C; a7 E7 h
发射端:
  i0 B: v3 M3 p5 Q$ i/ Q
  1. #include <INTRINS.H>6 k3 K7 s+ Y/ e! U# a% r3 e6 L5 X& x% x
  2. #include "STC15W.h"9 Y$ p; T6 q* N3 k
  3. , g: z. b6 N# y* D

  4. * n8 |' J( R/ s7 h; W4 G
  5. /*
    ! r6 Y  ?; V! g5 V/ s  \& h: ?8 H5 ~
  6. --------------------------
    6 f0 E6 F, ~: m1 I5 t9 T+ C
  7. |1 (OUT)        \__/   (INT1) 8|
    7 d' H8 h. a1 {4 `
  8. |                                                   |
    1 U! P/ X/ ]* _! L5 I; q- N+ }
  9. |2 (VCC)                   (INT0) 7|1 w& W( a) E$ i4 j0 f( Y' s
  10. |                 STC15W204S                   |8 o) f9 W; D& W% h7 E9 D* E
  11. |3 (LED)                         (TXD) 6|
    2 K- _- f. s5 I- g9 ?
  12. |                                                   |
    3 }5 K6 A' t6 J$ b
  13. |4 (GND)                         (RXD) 5|
    / X$ _, n0 o' f* A3 b8 Q4 |
  14. --------------------------
    3 S. S8 ~* U0 e2 ^8 b- o% ^

  15. ' _5 \. Q8 f, k) a; z' d
  16. LED ---|<|---[===]--- VCC) A  R- m3 s& h. M, a
  17.            Red          330  S$ `3 h/ A' }6 B

  18. 0 w* e. ?6 z% ~/ w6 t! ?& E
  19. Fosc = 6MHz  n1 d) V) s) L* F
  20. */0 G( p* L3 Z1 X+ {1 O
  21. * v. f4 }7 p) X1 R

  22. # J8 E8 b# u6 m( Y5 p
  23. // 矩形波输出脚
    " D7 S: a: r, C3 `
  24. sbit OUT = P5^4;) i; c: @: T$ g9 w9 q
  25. // 低压指示灯引脚
    3 S8 y& Y! q( D: ^
  26. sbit LED = P5^5;
    : a3 ?1 a" x8 c) G3 }. n

  27. 8 o1 |& f# g4 i! {! Y7 n$ z
  28. // 停机标志位/ h! G0 k/ D( ?2 X9 ~' j% \% r
  29. bit isReadyToHalt = 0;
    2 t: i4 L; T6 [3 W# ~- w

  30. 1 G+ \# f% n% M2 t4 J; L5 D
  31. // 矩形波次数累计
    ' l$ \/ N3 [! b. H; x5 D/ X* J: p
  32. static volatile unsigned char count = 0;
    ! }8 _  W) _: n" ?, \* s, v$ I

  33. + O, @( B! @$ E7 [: ~
  34. & M# ?! c5 F9 U
  35. static void GPIO_Init(){) R( N' J5 E* K2 t" q
  36.         // P3口设置为准双向,默认靠内部弱上拉输出高电平" H9 q8 J1 i2 t8 r2 M5 F( h
  37.         P3M0 = 0;3 W+ Q8 C+ [9 h) W* D3 L  |6 U& g
  38.         P3M1 = 0;
    . K9 I+ k  s, ]( G
  39.         P3 = 0xFF;
    8 m% D4 F: n/ V3 [
  40.         // P5口设置为准双向,默认靠内部弱上拉输出高电平
    5 e9 E4 @7 z" Q
  41.         P5M0 = 0;
    % d( z" Q) @4 q* N
  42.         P5M1 = 0;
    + V! |/ n5 v" V
  43.         P5 = 0xFF;1 k& z" L6 v% G) P8 ~0 M) g# g! O8 x
  44. }
    " U; p6 B& m5 I

  45. ' k- }+ U' C- |
  46. static void Timer0_Init(){( s$ f1 G  |9 D# N" m2 H/ g" H
  47.         // 16毫秒@6.000MHz$ @- F" l4 h+ _7 p7 ?1 u4 G
  48.         AUXR &= 0x7F;        // 定时器时钟12T模式
    3 x/ }: Y. V  M, H6 @
  49.         TMOD &= 0xF0;        // 设置定时器模式
    ! a) C2 m  ~5 _7 H5 @
  50.         TL0 = 0xC0;                // 设置定时初值
    ) K- M% w4 f5 V3 v$ U4 C# k
  51.         TH0 = 0xE0;                // 设置定时初值
    . X6 @! v1 B3 O& q' C$ p) h
  52.         TF0 = 0;                // 清除TF0标志$ K1 q$ f+ D5 o3 ~- b, M
  53.         TR0 = 1;                // 定时器0开始计时
    3 O- ?0 W( }- j
  54. }
    ; z4 {& e5 z5 Z
  55. * O# ?0 _% f$ E2 n! s
  56. static void Interrupt_Init(){
    , j, q. e3 y6 C* \
  57.         // INT0中断触发类型为下降沿触发
    9 p4 H3 C% _* [
  58.         IT0 = 1;$ _( H+ @7 [$ O# T$ A; P$ Q$ d$ s: d  D6 E
  59.         // 允许INT0中断
    ; g7 Q* \; {( i1 e/ t
  60.         EX0 = 1;
    # h- ~' h+ I( B; N6 s$ U
  61.         // INT1中断触发类型为下降沿触发/ w. q+ E) L; `/ T3 \2 ]
  62.         IT1 = 1;
    : J1 b( Q3 `6 o0 A  I5 u& S
  63.         // 允许INT1中断
    2 \: p( m* Y/ n
  64.         EX1 = 1;- n$ G/ @4 i+ E1 t' T
  65.         // 允许定时器0中断/ Y7 a5 P  `2 i' U4 P: Y8 u
  66.         ET0 = 1;, g7 U# H9 p3 [
  67.         // 允许全局中断
    ( u; E% |- s* R' L7 ~4 ?% f
  68.         EA = 1;
    7 V7 H2 i; b  C7 I( V3 X
  69. }4 J% }2 n9 M4 I. A8 V9 d6 u
  70. - O0 W: l. q( U) ?* \8 j" |5 O
  71. static void INT0_Isr() interrupt 0{7 F2 O1 e7 _) g$ |
  72.         // 矩形波次数累计归零
    4 d- I9 p' S1 ?8 }
  73.         count = 0;# l4 w8 C+ W* Q0 d
  74.         // 重开定时器0中断
    2 ?' h  Q$ Z9 n* Q! s& Q. J
  75.         ET0 = 1;' n  w3 m, `  S; j
  76. }5 }: A$ R/ U$ G5 a' ]  V

  77. 2 h* w3 C4 f. T# a3 }. l2 Q" [: e
  78. static void Timer0_Isr() interrupt 1{" x9 \( }: v, J! d$ A
  79.         // 输出矩形波
    # x1 W5 a+ H% C5 J. B1 y3 D+ z" z1 Q
  80.         OUT = ~OUT;
    " Z) z( a! Q, Y
  81.         // 累计矩形波次数$ P& N  V8 ?, O+ R* t5 E$ ]
  82.         count++;: X% b2 ]! }/ m* X
  83.         // 超过250个矩形波,准备停机! G1 M& I% {1 B9 x
  84.         if(count > 250){
    " [! x/ r+ P+ M) M$ G
  85.                 count = 0;( K  i1 p1 A% l3 k8 N6 G7 w
  86.                 isReadyToHalt = 1;9 R% F( G9 ^/ N) _$ F
  87.         }
    / T5 T5 Q  S" l' v  l. G
  88. }
    4 n5 }/ L3 ]$ s$ |/ y; c7 ^

  89. / z+ S- C: b$ g. A1 A5 f4 U
  90. static void INT1_Isr() interrupt 2{
    ; F3 u8 A" W3 p$ @) r6 c
  91.         // 矩形波次数累计归零( H3 P* Z" y1 M6 z2 e$ v' z; L
  92.         count = 0;
    & C7 G7 \9 K( B9 K( s5 [
  93.         // 重开定时器0中断
    . m- E* _! G& I
  94.         ET0 = 1;1 a  P5 n3 e+ @+ t9 K/ ]
  95. }( s) r3 d6 T- m* _8 V3 G

  96. 6 W1 u* o; F* C& R" p7 U
  97. 7 V& j2 s  W& o6 _$ u
  98. void main(){
    8 |4 a6 H! a( E. x% U1 I
  99.         // 初始化P3和P5口
    * ~5 i& G7 X) B/ d
  100.         GPIO_Init();& D% n  }3 \4 T4 w! ^
  101.         // 初始化定时器06 f4 U% i! ?& E% |2 t9 k$ v
  102.         Timer0_Init();
    - v0 U+ U2 M+ G- [7 m- ?
  103.         // 初始化中断1 G; m, {, t# A% c0 i' _2 T
  104.         Interrupt_Init();! O5 s/ `$ I/ V
  105.         5 h! I, b- ~* u8 I( J
  106.         while(1){
    6 I. b- [8 T* B; G5 M
  107.                 // 检测电量
    . Y) N$ Y4 d/ _1 |# R
  108.                 if(PCON & (1 << 5)){
    7 w3 R0 u: T5 ?7 m1 S& `. @$ V
  109.                         // 如果电量低,低压指示灯亮5 @' I) a7 ^: e! Q
  110.                         LED = 0;8 W5 E8 x# ~) n& Z+ C4 y8 C1 F
  111.                         // 清电量检测硬件标志位- L3 @# w1 @7 w, U9 B, N
  112.                         PCON &= ~(1 << 5);
    : O6 b. S; x8 `! v" s" Q; ~5 K. i
  113.                 }else{
    * J- [! @3 Z. Z+ f$ b. J
  114.                         // 电量正常,低压指示灯灭* P3 V: W' m& }6 ?
  115.                         LED = 1;9 J7 _! v$ j' b" J
  116.                 }# l( Z" o' U: G" b4 E7 m. V

  117. 8 U) k7 K( k+ Z+ E  C
  118.                 // 检测到停机标志
    4 w3 h) S; U7 M/ E
  119.                 if(isReadyToHalt == 1){
    , V; q% H9 q/ B0 s8 q
  120.                         // 暂时关闭定时器0中断
    , G0 l, H& b0 o
  121.                         ET0 = 0;
    % e! \+ l& _1 _* A& f) F
  122.                         // 停机之前先把矩形波输出脚置低电平,以方便INT0和INT1唤醒CPU1 S+ G$ u5 [, q, J1 n
  123.                         OUT = 0;
    ( h& e, I! U$ [0 T7 v+ I- K7 u
  124.                         // 停机之前先把低压指示灯灭掉,以省电* `* J6 G: S0 k9 Z5 @3 @
  125.                         LED = 1;
    5 Q* c* _& p7 K# x
  126.                         // 进入停机模式1 R2 o2 j1 D0 z; V% m- \
  127.                         PCON |= 0x02;
    ' R, P7 R9 n1 f& [8 f2 }
  128.                         _nop_();8 j. U1 w0 A4 ]$ V
  129.                         _nop_();
    3 C! b& W: O% |6 o
  130.                         _nop_();
    % F- t1 H! Z6 Y9 v" n! d9 X! p
  131.                         _nop_();. y9 q1 l. [+ F7 n# X# v
  132.                         // 唤醒,清标志位
    9 w+ l' D1 |" _1 X5 K
  133.                         isReadyToHalt = 0;% O4 H8 l, y4 R' Q- j" X. m4 D  v
  134.                         // 重开定时器0中断
    . H) D  \8 X; d" f0 e
  135.                         ET0 = 1;* u9 x) X1 `7 M, E/ ~% C
  136.                 }
    : s' l0 ~! I* g  M7 n/ z$ h
  137.         }
    4 g' G2 I, j( ^' ]% k: U
  138. }
    % Q  w# ^9 C, U5 S) O
复制代码
! x7 X2 ]. ^4 N- T$ n0 j
硬件参数配置:6 r; L+ G) _# b8 \  s

' j1 g, p5 ~8 y7 K* P- D: P& M& }: ~3 J0 t" o
接收端:( I: h7 r2 i6 A, D
  1. #include <INTRINS.H>
    / h5 ~; V  C+ v* r+ j. m
  2. #include "STC15W.h"
    ' s. ?. g& n+ |
  3. : C+ Y) k7 v! ^! _
  4. - Y. ?- w# W- T" [5 ]
  5. /*
    ! m' S& n: {! o, [  x

  6. 4 U2 v; ~' a8 T; F
  7. *---------------------------*- J- |& P% y+ \- B: }  t
  8. |1 (GPIO2)         \__/  (GPIO1)16|
    4 i% q# [+ X+ B7 I3 v" H
  9. |                                                        |
    ' O' H( O" }) {$ ]  H3 @4 @
  10. |2 (GPIO3)                   (GPIO0)15|5 P7 I2 B9 j  |" d
  11. |                                                        |
    - ~6 E! U3 s% B- f5 W
  12. |3 (GPIO4)                                  14|
    1 [# g/ h/ `% [/ J* J( H5 I/ G5 \& h
  13. |                                                        |; j2 y' B; z" V% C
  14. |4 (GPIO5)                        (DATA)13|
    # b! s9 U3 B0 n$ y
  15. |                  STC15W204S                |
    ( |' z9 b" S- c
  16. |5 (GPIO6)                   (LATCH)12|. V/ r* \/ e3 R4 S
  17. |                                                        |4 q* f4 G7 [( f* f
  18. |6 (VCC)                         (CLK)11|
    ' N* X) a9 u% \# L& J
  19. |                                                          |
    9 o$ x2 I4 y4 ^
  20. |7 (GPIO7)                         (TXD)10|/ L8 l+ {; g( Z  L
  21. |                                                        |
    4 d# H5 t# [$ g& ^
  22. |8 (GND)                         (RXD) 9|1 r. T: R* E' t0 n$ h9 j
  23. *---------------------------*
    ! A% ]+ P7 O. k8 U5 G  Y8 }
  24. Fosc = 12MHz
    ( u1 @+ M: a# k+ `+ D. J8 n3 \
  25. ; W: I3 g. k7 A9 R9 R& q& z2 }
  26. P1.0 -> 上  Z, O' l! K$ S, W; g; p  ^) ]- q% P
  27. P1.1 -> 左
    * x. a; I/ i+ e" B5 F5 ~
  28. P1.2 -> 下
    ! ?/ j9 l5 _# k$ n
  29. P1.3 -> 右; V7 K3 U8 U+ I0 k' u5 V, ~
  30. P1.4 -> SEL
    ; D/ B5 ~: v8 r+ M. J
  31. P1.5 -> STA
    1 I1 L5 ]+ J# w8 W9 r* e; ~
  32. P5.4 -> B
    : s  Y! p9 g( Z2 U. v7 r5 _
  33. P5.5 -> A3 a& F) R- B3 ^9 O" l7 Z3 o" Q

  34. ' v8 t. v; ~* `+ F' n8 ?
  35. */
    $ {* d( f5 m. |7 q8 @

  36. # `! T8 c4 X6 q, j
  37. / P: `3 \* a7 M% f) _) j# q
  38. sbit CLK        = P3^2;2 V7 \! f$ Q/ w2 S
  39. sbit LATCH        = P3^3;- t* L+ i& |9 O/ x! v' G" g- [
  40. sbit DATA        = P3^6;9 A1 Y6 [0 k5 J7 u; o
  41. * p0 \, i& f& D. m
  42. bit isReady = 0;6 x" v( u3 w4 E4 x
  43. static unsigned char key = 0;
    9 d& a# j) |5 |
  44. static unsigned char buf = 0;        // 双缓冲。这个缓冲区保存从P1和P5组合而来的键值) ]5 I% ]- A6 e; u+ D3 W: ~
  45. static unsigned char bufReady = 0;        // 双缓冲。这个缓冲区保存上面那个缓冲区的备份  Q/ h9 g1 N6 ~% u7 b# ~  E! U$ E
  46. static const unsigned char data mask[] = {0x80, 0x40, 0x10, 0x20, 0x01, 0x04, 0x02, 0x08};        // A B SELECT START UP DOWN LEFT RIGHT。为提升速度,这个表放到RAM中% d3 p9 G; |" `0 Q# L
  47. static unsigned char idx = 0;3 k- |* {! J; L; m( U3 E6 _* G9 F

  48. 1 e6 |- r) j- y$ h

  49. " T* ~; N$ Y3 {$ Z& P
  50. static void GPIO_Init(){
    % d4 y) \5 `, l$ B- F1 ^/ f
  51.         // P1口和P5口用于接收并行信号,全部初始化为准双向,依靠内部弱上拉输出高电平! M5 v" u# V& o( z. k7 Q8 z
  52.         P1M0 = 0;1 I3 g  H7 x" F/ @7 X" v
  53.         P1M1 = 0;
    1 K" `2 i8 ?5 d/ }& Q
  54.         P1= 0xFF;  I2 ]1 [. S: l7 F4 q
  55.         P5M0 = 0;/ `  r8 P5 l7 u% X  E# J6 [# v
  56.         P5M1 = 0;4 r5 c: B: h. Y7 k
  57.         P5= 0xFF;* f, q+ q& v7 Y' Y7 u, x
  58.         // P3口初始化为准双向( o+ S; y" R) e- Y$ L9 ]
  59.         P3M0 = 0;
    5 H9 k3 O- A9 i# B. c9 a
  60.         P3M1 = 0;
    2 k" h0 m; N) i* ?
  61.         P3 = 0xFF;
    ' Z8 ~* V( O8 K
  62. }& j, I: _2 o: y6 [: Y- N

  63. ' O  Q5 v* B9 c! O1 H9 a
  64. static void Interrupt_Init(){
    8 s6 Q: U- N. k( c0 Q8 K
  65.         // INT0中断(CLK)触发类型为上升沿+下降沿
      c3 N# n: b0 k; {8 Q! c, m
  66.         IT0 = 0;
    0 G! U+ o, J. l( u2 g; c3 \5 x7 i
  67.         // 允许INT0中断6 I* ]5 }" o/ i+ S2 G+ E2 O, R- G0 z
  68.         EX0 = 1;
    8 ?7 v5 U( t, ]3 B8 c
  69.         // INT1中断(LATCH)触发类型为上升沿+下降沿
    6 e2 w4 p+ z5 e; ^
  70.         IT1 = 0;  p1 l9 W# O, S+ Y3 ]' J8 }
  71.         // 允许INT1中断0 _; n1 ~, `# v/ d
  72.         EX1 = 1;
    ' G* y# A, ?3 x, C) j
  73.         // 开启全局中断( T2 N+ `6 U& i1 u# }  v4 R7 C! m3 H
  74.         EA = 1;! J2 [! \& J5 V, P7 h
  75. }; U4 P, n. E# e( P$ C2 O, E

  76. : F, b7 z- C' T; b; \
  77. static void INT0_Isr() interrupt 0{
    8 d$ A$ ]" D. f5 y
  78.         // 只有已经成功锁存才允许CLK移位
    - Y1 c2 S2 b/ R' z  [" y, _6 j
  79.         if(isReady == 0)$ a; o5 G1 n$ s* L8 ~9 R
  80.                 return;
    / v# J5 z/ j" f9 e/ h
  81.         // 读当前引脚电平,如果是低电平则说明是下降沿,此时直接忽略该中断( R& w: g1 W0 L8 F* \* J3 i% L$ f2 Z( q5 i
  82.         if(CLK == 0)
    " O& i, G7 T- S( @! B
  83.                 return;! s7 x( P" \3 j  m
  84.         // CLK上升沿到来的时候,取锁存值的下一位输出6 p# P6 G  R4 Z% o0 S9 g
  85.         idx++;: Z7 y  u. _& o  X6 i. k
  86.         DATA = key & mask[idx];8 \2 j- U( u  b; G! [& t
  87.         // 如果已经完成7次移位,则一轮读取完成
    * F+ `& o, l& ~  g% Y+ j8 C2 `
  88.         if(idx >= 7)
    - l' Y# T$ I; u# y4 V; U
  89.                 isReady = 0;% H3 f8 s9 v5 q' H. G- N5 F1 j
  90. }
    ) S6 Z: l4 w' v6 b$ H7 w
  91. $ N, U. T/ s$ P: `, f
  92. static void INT1_Isr() interrupt 2{9 s' ?1 C6 e9 O  E% }9 {% G9 g
  93.         // 读当前引脚电平,如果是低电平则说明是下降沿,此时直接忽略该中断
    % i$ T9 Z9 c9 D3 ?) a9 o
  94.         if(LATCH == 0)- h" l! a. p- [
  95.                 return;
    ) w/ N& N0 U5 u8 B8 y: k
  96.         // 当LATCH上升沿到来的时候,锁存所有按键状态,同时把键值A输出到DATA
    ' q% F  q* c' T* L$ p9 d
  97.         key = bufReady;
    4 X  Z8 C) P) P: \
  98.         DATA = key & 0x80;//mask[0];        // 为了加速运算,直接取表中的值而不是读表2 T! w% J. q& A' W! \( g+ ~# r0 i% S
  99.         idx = 0;% M" r# Z: y8 f% k& {: V, v6 C
  100.         // 允许CLK进行移位
    2 i3 J" ]9 y5 c7 W3 [% X; K
  101.         isReady = 1;! l% T  J0 j3 h8 \
  102. }
    - v, ^4 ]6 j4 t- O% J
  103.   {- K$ ^" i- c& P
  104. void main(){
    ' K1 Q  t( l) i
  105.         GPIO_Init();$ d4 c/ x/ U% `3 k* ?4 y' ]
  106.         Interrupt_Init();. x3 @) r1 A) T! x$ E  b
  107.        
    # N1 N2 f3 d" _$ A+ v
  108.         while(1){; Z! e! S+ X6 W8 {' `
  109.                 //PCON |= 0x01;        // 进入省电模式
    0 T& K; n/ r. K
  110.                 //_nop_();: a: ^" ~5 R) d6 v5 \/ l
  111.                 //_nop_();; I  z2 t+ ^& K! U4 I8 w2 ^5 F
  112.                 //_nop_();1 M7 N% `0 _9 X/ E% \" W
  113.                 //_nop_();
    $ @* a9 e# r/ p4 ^& o  j
  114.                 buf = ~((P1 & 0x3F) | ((P5 << 2) & 0xC0));
    $ p7 g) j) [! q
  115.                 bufReady = buf;
    1 V& l( Q/ |3 D
  116.         }
    ' ^8 E7 E1 v* r5 F& X
  117. }
    : j+ a4 F6 l& e  J+ V: q/ l/ N9 J
复制代码
& h& H' J3 ?/ o
硬件参数配置无特殊要求,晶振频率选择12M即可。
0 W4 b( j! S6 S% W1 I& ~. r, C2 ?- c' L+ r" B8 p
这是编译好的固件。

本帖子中包含更多资源

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

×

评分

参与人数 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
( g5 ?& V5 {' a2 V不错的设计,想问一下楼主,FC的15针公头怎么解决?普通的公头太短了,插不进去FC的扩展接口。 ...
* X9 t- r, {% |' t$ T3 r
坛友的改造方案
回复

使用道具 举报

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

使用道具 举报

发表于 2019-5-25 12:07:18 | 显示全部楼层
精彩,楼主动手强,也写得很详细。2 r. E2 ]0 h7 ^- y" l) }  k: L
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
( A& L( J8 W+ Q  |+ ?精彩,楼主动手强,也写得很详细。
/ u, s( l; J. M0 I# T" F6 D% V8 S2.4G方案是目前无线的最低延迟吗?
- i- V. U. S) l) |, L; s, x
我没用过其他无线手柄,所以实在不知道我自己做的这个手柄到底是不是最低延迟。6 Z4 u. y0 `1 h% M/ A/ A( A
不过根据网上的说法,延迟高低主要是由通信协议的复杂程度,以及数据传输速率决定的。这个模块虽然是2.4G无线模块,但由于协议很简单,所以延迟比较低。! k7 i1 h9 Z5 Y, @  p0 X/ M% c
我用这个手柄玩一些ACT游戏,比如超级马里奥、忍者龙剑传、热血系列,完全感觉不到延迟,和游戏机自带的手柄没有任何区别。唯一的区别就是这个手柄是用火花山寨手柄改造的,外壳是垃圾回收塑料,粗糙+脆弱,导电橡胶弹性不佳,手感不是一般的差。& Y5 J$ n/ N. G, y; _0 G6 N& A2 \) A
我手里还有十几张板子,等我有空了我再做一套,到时候买一个好一点的手柄改造。
回复

使用道具 举报

 楼主| 发表于 2019-5-29 16:56:14 | 显示全部楼层
ppad 发表于 2019-5-28 17:27* r# R) g& d/ W, U$ F0 \
给技术帝赞一个,有半成品发布吗,自己焊接改造就可以,编程实在不会啊 ...
8 J* |% ?8 ^6 Y% f
很可惜,我手里没有多余的单片机了,LDO也找不到了,锂电池以及充电模块更是没有了。反正就是该用到的元件基本都没了,所以没法发布半成品。
9 g& Z/ D4 H% z7 t4 i) b+ i两个板子倒是有十几张剩余。# ?% `; q+ D1 l' a
你要是有USB转TTL串口板,完全可以自己买这两种单片机,然后我给你编译好的固件,你自己用串口板下载到单片机里面就行了。两个2.4G无线模块也得通过串口板用AT命令设置参数,不过好在我在设计电路的时候就已经预留好了串口,可以直接在线下载和在线设置参数。总的来说并不麻烦。
回复

使用道具 举报

 楼主| 发表于 2019-5-29 17:00:34 | 显示全部楼层
孙大师 发表于 2019-5-28 18:557 w; i, j2 Q4 j7 ?- Z+ g
非常好,楼主是技术帝,到目前我都还没开发fc的无线套件,等空了,开发一套套件,等玩家自己组装。 ...
$ x0 Z% p7 B: P) U- k( V
能得到孙大师的赞誉,不胜荣幸!
! C: K  k9 _- t8 t1 j* w不如开发一个多功能手柄,比如用SFC手柄改造,L/R键配合其他组合键可以用来切换2P~4P、调节连发速度、软重启等各种功能。接收端插到15PIN扩展口。
回复

使用道具 举报

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

本版积分规则

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

GMT+8, 2026-9-20 22:03 , Processed in 0.104434 second(s), 15 queries .

Powered by Discuz! X3.5

© 2001-2025 Discuz! Team.

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