找回密码
 注册

QQ登录

只需一步,快速开始

查看: 26406|回复: 33

自制FC无线手柄

  [复制链接]
发表于 2019-5-22 14:16:45 | 显示全部楼层 |阅读模式
本帖最后由 雷精灵2046 于 2019-6-14 09:28 编辑
# J! }4 s: ^- z* Y- \& \7 Q2 G. @, e' W* k, h
没有用复杂的分立元件搭建发射接收电路,直接用的现成的2.4G无线模块jdy-40。
, E3 d/ |. S/ l+ b4 i3 B$ m( b# b' d. o  |' t3 N0 l2 E3 r! D& o
1 k: m- Q8 U) L1 y4 ?0 q+ g
发射端靠3.7V锂电池供电,用了一片SOP8封装的STC单片机,负责产生连发脉冲,同时负责检测电池电量,电压低于3V左右的时候触发低压中断,低压指示LED就会亮起来告知该充电了。平时发射模块和单片机均处于睡眠状态,有按键按下才会唤醒,从而实现省电。实测睡眠状态下整机电流约1~2uA。板子洗了一下稍微干净了一点。因为对于微功耗设备来说,焊接残余的助焊剂可能会增加漏电流。
% j; G7 g; R" \9 L+ R1 b7 K! \) V* F2 Q. o: ~! _! D0 B
买了一个火花的FC山寨手柄,去掉里面的牛屎板子,并修正一下塑料挡板,把锂电池和充电模块装进去。  m& Z) q5 A: L8 `- q/ _  S$ i) B
为了减少体积,充电模块裁剪得十分小,并且更换了充电电阻使之适应这个小小的锂电池。这么小容量的电池,也不需要多么大的充电电流是吧?
! Z1 G! m3 d% g1 O" w  z然后统统用热熔胶粘上。充电电流比较小,所以发热很少,不会熔化热熔胶。
. @5 j! Q1 E  J; [  d
% f! E- q; M  K0 Y- e0 G& y  e! \5 l+ N7 q$ M3 B' s

2 c/ s# S; H6 c$ R% f* j, N: F最后把按键、导电橡胶和电路板装上去。
2 x9 P9 E. N3 M精心裁剪了电路板,正好扣上,不会阻碍其他元件,也不会影响后盖和拧螺丝。' a  t( P( T+ ^8 C* ?" q

$ i1 t: H/ k  P( m0 U
( j( \( X8 Z, M1 t5 N- q完工!$ }6 k9 G  y+ R
7 a$ s6 E4 O# Q1 ~- {
  C  B; `% J! e* X% D
这是充电的MicroUSB插座。旁边的小孔用于透出低压报警LED的光线。
  U& j3 J( x& R" b/ \0 K  i# g, A* l# h9 O" k
3 @, r2 G9 T, A3 |" F5 T# c9 C
接收端用一片DIP16封装的STC单片机模拟CD4021。为啥要用单片机模拟而不是直接用CD4021?因为jdy-40模块接收端在有按键按下的时候输出高电平,无按键按下输出低电平,和普通手柄正好相反。当然我也可以用两片74HC00或者74HC04之类的逻辑门进行反相,但那就增加了芯片的数量。对于FC手柄这种工作频率并不高的设备来说,STC单片机完全可以胜任模拟工作。
& m, o9 r' t9 j0 g0 z- v5 o+ S+ k
/ B, K; N4 w, i/ c8 h3 g9 m- f1 O
/ i: r/ \' _$ h& e2 ?
电路设计有点小小的错误,所以有几根飞线。原本设计使用低压差LDO是XC6206,结果在做这个接收模块的时候,买的LDO居然找不到了!无奈只好用了AMS1117。幸好对于接收模块来说是5V降到3.3V,1117可以胜任。要是发射端手柄的话,3.7V降到3.3V,那就非得用6206不可了。& a$ l; n' o; c! [) y' c4 x
" s0 s7 J% c9 F% m0 s/ P  z
实测十分灵敏,延迟极小几乎感觉不出来。可惜这山寨手柄的手感并不佳,尤其是方向键,软塌塌的。看来我得买个剪线手柄改装。
$ }* k. ?. F2 o" |8 {
; a1 Z. I7 Z* P* e, t: j这是电路图,有兴趣的朋友可以参考。
# [2 @( f! {* U: K- _3 S; N3 J" w* F7 }" h% q5 y

' P, W) G: M- H' L2 X! e我信奉开源主义,十分痛恨把技术藏着掖着。好东西大家分享嘛!所以两个单片机的源代码大公开!1 c( `; U4 d# P) P( S
编译器:Keil 51。
1 d3 c7 Z- }" Q; l& l0 s. E3 g* m8 H1 n5 M) M- Q& r' {; M
发射端:
" ~# @5 [5 t0 n+ h) W2 q* W  M
  1. #include <INTRINS.H>
    # I- ^) B  T  M3 F9 K, d
  2. #include "STC15W.h". E% O$ x  ^" F" `  _7 G' K
  3. - W% Z' r% b$ c! B( j" T* ]

  4. % [+ f3 k" N, E  P, t  Z, o5 q
  5. /*
    ) n0 t0 j6 y4 _+ }" v
  6. --------------------------( {+ y7 T0 k) q7 h: r6 q1 }( {
  7. |1 (OUT)        \__/   (INT1) 8|( j* T9 h9 z+ g; ~" v) C
  8. |                                                   |
    ! l) P8 r! B& I) n
  9. |2 (VCC)                   (INT0) 7|* R" e! ~  X' N7 Z! L
  10. |                 STC15W204S                   |; Z) l4 [" Y8 i6 A% i! u. u
  11. |3 (LED)                         (TXD) 6|+ s$ N2 X* A, Z$ u1 V2 z' ?* B
  12. |                                                   |7 p* Q% m8 ^+ P7 f: g
  13. |4 (GND)                         (RXD) 5|
    . C2 n9 w( e( Q5 r$ B2 I
  14. --------------------------4 Y- z( p) v& n! P
  15. % F7 C$ [" e. X. r; T3 t5 F, Q
  16. LED ---|<|---[===]--- VCC4 e1 F8 T' E- U; O' K% p
  17.            Red          330
    ( o, \5 Z% g) M% H* c

  18. 2 A( F' J1 M4 y9 X6 R
  19. Fosc = 6MHz& ?( i; l  L% m1 o# z
  20. */2 z2 b" d# V* p0 a: K

  21. ' F$ s2 b& a$ S! }

  22.   k: G2 }% B( N7 Y
  23. // 矩形波输出脚5 _. K4 {$ ?* j' z
  24. sbit OUT = P5^4;
    + T# j3 `; }+ X, h/ Q1 E
  25. // 低压指示灯引脚% \7 J1 w- ?9 j1 |
  26. sbit LED = P5^5;# `+ y" R) U6 `( x/ B. a, y
  27. & e/ a; [8 b' ^; l7 U# e3 g! E
  28. // 停机标志位4 u# J7 {0 `" l* L3 n4 }
  29. bit isReadyToHalt = 0;
    ; Z) d! a+ Y/ |, v; b

  30. - J8 B- A  U. m0 N: L0 u) b+ D
  31. // 矩形波次数累计
    1 u5 h8 A' B2 X4 R* h+ P9 I
  32. static volatile unsigned char count = 0;
    ! C- |2 C, B: p) M; l5 Q. C
  33. 2 D" B- W0 ]. Y# o' S

  34. 0 j! {! @- d+ @! e' {; I
  35. static void GPIO_Init(){8 a. Z2 s$ Y) g- V3 D2 N
  36.         // P3口设置为准双向,默认靠内部弱上拉输出高电平
      t. L$ k6 R. e9 g5 C
  37.         P3M0 = 0;
    , J( v7 @3 k+ h  V/ K4 @; F
  38.         P3M1 = 0;
    ; l  |; w$ W; Z1 b! _
  39.         P3 = 0xFF;
    , ]& K2 R0 w  w+ ^
  40.         // P5口设置为准双向,默认靠内部弱上拉输出高电平3 l( f- b5 Z2 Q8 K
  41.         P5M0 = 0;
    & u) X3 f0 l, l' `( c
  42.         P5M1 = 0;6 A" @1 [3 c/ a4 b
  43.         P5 = 0xFF;
      b# o. M0 ]& j1 c- J
  44. }3 G7 k7 ?- v, X3 Q4 o- B
  45. 7 q, v, N  G4 j
  46. static void Timer0_Init(){- l2 p4 a) d, S$ D) P
  47.         // 16毫秒@6.000MHz& H$ L. v. R5 t% E/ x8 `
  48.         AUXR &= 0x7F;        // 定时器时钟12T模式
    1 V" r4 C7 B% I
  49.         TMOD &= 0xF0;        // 设置定时器模式
    2 o  T8 L9 p3 {$ X# U
  50.         TL0 = 0xC0;                // 设置定时初值- A. @% Z9 [+ L; P
  51.         TH0 = 0xE0;                // 设置定时初值+ W8 k7 A! X* {# e% D
  52.         TF0 = 0;                // 清除TF0标志& ~! Q, S* u9 {
  53.         TR0 = 1;                // 定时器0开始计时1 Z0 H& z5 J+ T# ?
  54. }: M9 X& Q. H6 s

  55. 4 s! S8 C  m4 N
  56. static void Interrupt_Init(){
    " T& }& S& G, A0 F" ~2 ^8 M; P! D; D
  57.         // INT0中断触发类型为下降沿触发
    ' E! S) P1 b4 B+ u; x% d: f
  58.         IT0 = 1;
    ' c" g5 `$ f8 k. T7 @
  59.         // 允许INT0中断
    ' {% |* t2 S% }  V; a1 e
  60.         EX0 = 1;$ Q2 d- E' v. i# ~& b  l
  61.         // INT1中断触发类型为下降沿触发* i# d& m5 h1 J& k, F
  62.         IT1 = 1;
    ) J: a" b1 M" @# A- R/ ]
  63.         // 允许INT1中断
    3 r" O$ [' ]# {; d
  64.         EX1 = 1;# d. N$ I$ H5 ]( v, o
  65.         // 允许定时器0中断
    $ r) g% X7 V5 ^7 ~& S
  66.         ET0 = 1;
    9 E. ^& q( ^+ `; z& i) Y" a0 y: \1 A
  67.         // 允许全局中断
    0 C2 H( _4 \4 B+ t. E0 V
  68.         EA = 1;& ]& R5 h4 o- o2 p
  69. }. A9 Z3 ^; F6 p% H

  70. ( P: i$ B9 F) M6 |8 e0 M
  71. static void INT0_Isr() interrupt 0{( G) `/ U( y+ L( A5 R
  72.         // 矩形波次数累计归零
    " _5 G; }/ i- U
  73.         count = 0;7 N3 c1 k' e& D: ~6 N, D
  74.         // 重开定时器0中断6 ^3 R" k. L/ t$ a; J& c
  75.         ET0 = 1;* z6 V! P- X2 a4 b. I! x. X
  76. }1 t* Z: p" ~6 R9 ?
  77. 5 O! t3 u" y, Y, U6 s
  78. static void Timer0_Isr() interrupt 1{
    $ T& ]$ f# O3 N. x2 X# b
  79.         // 输出矩形波' ]# L3 t: w8 S1 R
  80.         OUT = ~OUT;
    / t: Z. D% k2 Q$ ^8 B2 r% p; D# ?
  81.         // 累计矩形波次数% s/ M( ~# q9 e! ]- Y3 v
  82.         count++;1 O( g+ r, {2 I
  83.         // 超过250个矩形波,准备停机
    - d$ D4 K2 v3 M9 t8 E. ?' B
  84.         if(count > 250){
    3 ]6 B- F: h4 d2 t
  85.                 count = 0;
    ) \0 S0 D5 ~; W6 `/ U7 E: w
  86.                 isReadyToHalt = 1;, Z3 b2 _6 o3 X3 a
  87.         }
    ! c' L' r5 c  G
  88. }+ @- D4 y5 e4 m" G8 e
  89. - c! r; z7 Q8 u
  90. static void INT1_Isr() interrupt 2{
    ! Q9 b5 J* D. m% z  C& Y
  91.         // 矩形波次数累计归零; s" J4 X4 b3 b+ g% T; s. y
  92.         count = 0;/ o& s# C0 a, u* s7 e. [
  93.         // 重开定时器0中断
    0 b1 ~4 ?( X9 w: f& w' A2 f
  94.         ET0 = 1;, c: X- D$ X: a6 ^5 M: t3 e
  95. }9 o, w$ n" F+ X3 h; ^4 P5 x
  96. 9 k7 q- q. ?' M  L$ [

  97. ( |0 H% K1 m( y  X/ Z8 ^1 z" C
  98. void main(){
    & p* M' A. _& r8 M2 F; f6 `
  99.         // 初始化P3和P5口
      k# R4 b4 [3 E7 O* `+ b7 |6 e
  100.         GPIO_Init();2 _' x; T; J4 q
  101.         // 初始化定时器0
    / I  c% B& l( S
  102.         Timer0_Init();5 a$ Z4 p" Q8 F: F9 g. B) [0 @
  103.         // 初始化中断" O  K% R" L( @; ~: M$ y
  104.         Interrupt_Init();
    & e8 y9 O- B" |  Y4 A# ?* H0 g
  105.         * H# e3 o- \" p* B+ Q
  106.         while(1){
    3 a3 W" X% @' {  D# o( d  W- W
  107.                 // 检测电量( h1 {$ i2 |( e0 b  \2 L
  108.                 if(PCON & (1 << 5)){2 V7 \' Z1 d( z6 D, T
  109.                         // 如果电量低,低压指示灯亮0 y& o, ?: q+ t0 ]# d' W
  110.                         LED = 0;& b$ |$ U. [3 j
  111.                         // 清电量检测硬件标志位
    % y2 j, P3 \& |) K; I3 Z1 D
  112.                         PCON &= ~(1 << 5);
    $ @0 U; D- U* n; h, ]
  113.                 }else{& ~4 r6 Q1 ^) t- t
  114.                         // 电量正常,低压指示灯灭
    2 x. J# j/ h# U  W
  115.                         LED = 1;% \( `1 B: {( o  J4 m# q; o
  116.                 }) b2 x3 w/ n! o/ X1 R# m2 l
  117.   w, V. Z( u+ D
  118.                 // 检测到停机标志# l+ z7 I% n. R3 A
  119.                 if(isReadyToHalt == 1){
    % A1 T- _$ V. g3 U3 b3 n1 ^
  120.                         // 暂时关闭定时器0中断
    ) F2 R2 o. m$ p& K6 o: s0 ]8 E( n
  121.                         ET0 = 0;
    8 E2 Z* [* v3 N* w( n2 H# F
  122.                         // 停机之前先把矩形波输出脚置低电平,以方便INT0和INT1唤醒CPU2 U6 g# t) s+ c: E6 R5 B
  123.                         OUT = 0;$ v5 z  t9 M9 \- |$ v- c' N9 r" K: C
  124.                         // 停机之前先把低压指示灯灭掉,以省电
    4 l7 ~( ~0 U9 u% U
  125.                         LED = 1;
    . G2 N7 {3 _& _" |: v. ^
  126.                         // 进入停机模式
    ' v$ M( v+ G! B# D
  127.                         PCON |= 0x02;
    / l& m4 ^! ]# H; M. K
  128.                         _nop_();' B0 s$ i) n  `" E1 x
  129.                         _nop_();+ G* W1 c# b  c/ ~
  130.                         _nop_();
    ) ~1 W' d5 p( J7 ~  p% a; Q0 \
  131.                         _nop_();
    3 `1 C+ H4 D2 K# f0 ^
  132.                         // 唤醒,清标志位
    . G2 h7 q- r' _5 o$ |/ D' [
  133.                         isReadyToHalt = 0;
    7 R$ ?" [; m8 L
  134.                         // 重开定时器0中断
    " z  W( ~5 ]; s- F. a7 ~' x4 B
  135.                         ET0 = 1;
    3 @7 ?+ z: \0 Z- u7 `3 f
  136.                 }: W6 ]7 V, T0 v
  137.         }* ?( e' J3 Z0 m6 G
  138. }6 O2 y  X$ X) c6 z
复制代码

$ y  X+ C0 h6 A2 T+ m: V) B7 I硬件参数配置:* Y9 H" a& M6 [8 D  h+ H; B$ E# K
5 Z2 K4 G/ c' z9 ~9 Q' t( l& R2 [5 W& z
$ ~. J  {7 W1 L3 p
接收端:
1 [' L$ Q  ^0 R" ?
  1. #include <INTRINS.H>. o0 d) X" n* ^# m7 P# r  [; Y
  2. #include "STC15W.h") B" c* n& C. _+ j8 Z/ c

  3. # L' S- q' s  ~) a

  4. ( `5 N* Y: ?8 W& G
  5. /*
    , t& j& `. c" C/ L1 @7 y' x
  6. 3 ^! X5 B# a) i0 e- S: g9 M
  7. *---------------------------*! a; }& }  s- V5 Z. I! s7 {% j- k
  8. |1 (GPIO2)         \__/  (GPIO1)16|6 Y$ ]/ l9 f! m* n
  9. |                                                        |, X$ }* j) I7 i' q: T9 j' D
  10. |2 (GPIO3)                   (GPIO0)15|
    & H" V" Y. m3 n% U2 t% p, }
  11. |                                                        |
    # z6 d+ a# L) z7 E) q/ Y
  12. |3 (GPIO4)                                  14|
    3 z: F5 ?9 c7 i1 @+ ?0 w9 K
  13. |                                                        |
    * _+ [, D" q3 F$ ]3 e; U9 W$ M
  14. |4 (GPIO5)                        (DATA)13|" v8 q( e6 d& \8 e% O4 b
  15. |                  STC15W204S                |
    7 N5 l8 Q! a2 X
  16. |5 (GPIO6)                   (LATCH)12|
    * [9 ~& u. X4 F  c
  17. |                                                        |
    8 E1 U+ O/ ~! [3 x
  18. |6 (VCC)                         (CLK)11|
    ' J5 }. {: ?. @, g
  19. |                                                          |. W, d: M' O2 [! c9 j# h+ `
  20. |7 (GPIO7)                         (TXD)10|& V! M* s: b6 Q
  21. |                                                        |5 P! N. h, @- D% \( n7 E! K
  22. |8 (GND)                         (RXD) 9|7 |2 z0 {2 U4 Y; C
  23. *---------------------------*
    " A  C" E- F& Z8 x* o
  24. Fosc = 12MHz  I6 T/ [2 S4 [! g# m7 w9 k
  25. 1 r7 `+ ~( U$ t+ y* `' P
  26. P1.0 -> 上
    ( k2 _, Y+ [# K" h7 v1 S; a" B, e% V
  27. P1.1 -> 左* m# s$ s" T! g' C( J
  28. P1.2 -> 下( L9 `  e8 Q6 t3 m
  29. P1.3 -> 右
    ) V5 w, q2 L5 @7 e; L8 T
  30. P1.4 -> SEL
    7 j* V* ^' e( B6 }: A; w
  31. P1.5 -> STA, \2 k$ l7 V% `6 S" m' i- S9 u
  32. P5.4 -> B/ O6 ]- M5 i) y- d( h5 {% o
  33. P5.5 -> A' l1 E4 G* d# D: Q6 W" C2 x: ?
  34. ' `, q1 {5 q% z/ A4 n( P! l
  35. */7 C, ~6 Q9 g* s7 h

  36. ( s9 [; a- ^7 H
  37. 9 g+ |( M; }% p8 f
  38. sbit CLK        = P3^2;3 c3 l; I) l: L2 K
  39. sbit LATCH        = P3^3;* i6 K/ P" [! f! l9 q1 @6 D. w: L
  40. sbit DATA        = P3^6;
    1 }1 y" X7 g% \3 Y
  41. 4 W& Q- N. r# Y. ~* p+ l8 v) p
  42. bit isReady = 0;
    ; [! `$ Z" G* v- K: d: f
  43. static unsigned char key = 0;* @5 {+ o% O" G2 \4 R  c
  44. static unsigned char buf = 0;        // 双缓冲。这个缓冲区保存从P1和P5组合而来的键值  M" d7 k2 M8 G' \& p
  45. static unsigned char bufReady = 0;        // 双缓冲。这个缓冲区保存上面那个缓冲区的备份
      z) K' \% V5 ?6 P" y% f
  46. static const unsigned char data mask[] = {0x80, 0x40, 0x10, 0x20, 0x01, 0x04, 0x02, 0x08};        // A B SELECT START UP DOWN LEFT RIGHT。为提升速度,这个表放到RAM中
    # i  V' B+ G% ~0 U
  47. static unsigned char idx = 0;& [$ T3 X+ \! g
  48. # l2 @3 y  J; s8 ?4 I4 s, F& y

  49. 0 t6 Z9 ]9 B5 P0 ?5 V
  50. static void GPIO_Init(){
    : H+ |% |  M+ ?  n/ R# t0 D
  51.         // P1口和P5口用于接收并行信号,全部初始化为准双向,依靠内部弱上拉输出高电平
    : E" r5 a9 R0 ~3 w5 z
  52.         P1M0 = 0;5 a; g4 v- E$ y4 E" L8 b1 ^
  53.         P1M1 = 0;
    ; E! f, |2 t' L. P
  54.         P1= 0xFF;+ P9 i# G# O0 e! g  i' ~, R
  55.         P5M0 = 0;
    # @; }+ ~6 V2 A: G2 U* j
  56.         P5M1 = 0;
    , U; W1 o8 w1 l( o' v/ }- N$ T4 f
  57.         P5= 0xFF;! k$ @+ q8 ]* b2 k3 n
  58.         // P3口初始化为准双向9 B- Q5 i1 ^, ]- C7 J+ p) j/ ~
  59.         P3M0 = 0;
    ) K- F- J$ {2 A- O' P  s, v+ ]
  60.         P3M1 = 0;/ l5 y! F2 H& o5 |9 H* L5 R
  61.         P3 = 0xFF;
    9 d  V6 w) H2 r: ?3 ~' p: ]
  62. }
    4 d+ r% U, r7 p2 i/ }7 B
  63. $ q' t6 V" R# o. g+ X1 p
  64. static void Interrupt_Init(){
    / u" ?) ~5 f1 d7 U& r( ^  C5 n9 c
  65.         // INT0中断(CLK)触发类型为上升沿+下降沿
    * Z: d2 ^0 [( Y, Y" B; ]
  66.         IT0 = 0;
    ( v4 z8 G- s1 J) ~
  67.         // 允许INT0中断
    ; o8 }2 `6 ~, b8 n1 @; r- H/ ~% S
  68.         EX0 = 1;4 G  v; V4 I1 A6 n6 D6 a( s. I
  69.         // INT1中断(LATCH)触发类型为上升沿+下降沿
    * u* x2 W+ y- A
  70.         IT1 = 0;
    + C+ T" S9 E6 O9 u
  71.         // 允许INT1中断
    8 {( l' b! M6 O% b- j' S- x1 l
  72.         EX1 = 1;
    % C2 X% D" k2 d. N
  73.         // 开启全局中断
    9 u5 u4 H  g0 R- A4 {( e* b/ N
  74.         EA = 1;* y/ P) x3 {- o
  75. }9 X1 x  u# @9 ~$ t4 b. n
  76. ! n. v  `! v3 V9 k9 e" V9 ?
  77. static void INT0_Isr() interrupt 0{. m! O% k+ E* ]( m; L2 x
  78.         // 只有已经成功锁存才允许CLK移位1 x8 Z! e2 h" Z5 S0 a2 ]
  79.         if(isReady == 0)
    6 Z6 R- A$ B3 o4 ]
  80.                 return;
    / a3 L1 I7 @3 |' W8 W/ k
  81.         // 读当前引脚电平,如果是低电平则说明是下降沿,此时直接忽略该中断2 L/ I. f. I0 g6 |" m, ]4 ?
  82.         if(CLK == 0)
    ! T, q  Z+ h- D4 J
  83.                 return;- W9 z* @) \% P  G5 }- `# h
  84.         // CLK上升沿到来的时候,取锁存值的下一位输出3 f) K( t) p0 T- K' i
  85.         idx++;4 U5 k2 J: x- `  [5 B
  86.         DATA = key & mask[idx];& v) Z3 v2 G2 q' j# r( u
  87.         // 如果已经完成7次移位,则一轮读取完成
    ) J) n- ]) |* d: s3 K: @
  88.         if(idx >= 7)
    4 g# Q* n* b% Q5 n1 Q8 c$ x
  89.                 isReady = 0;" J& \+ y1 @3 X: K8 C
  90. }% u8 [' _+ N, b
  91. ( A9 y& b% @0 n  C: R
  92. static void INT1_Isr() interrupt 2{. U1 E7 ^2 C6 ^# t
  93.         // 读当前引脚电平,如果是低电平则说明是下降沿,此时直接忽略该中断
    # L  x7 |+ t0 w6 ?" g/ ~
  94.         if(LATCH == 0)5 ^. b% P9 m3 `& G$ Y
  95.                 return;
    1 V( B/ w, A3 @2 I3 f1 U2 ^
  96.         // 当LATCH上升沿到来的时候,锁存所有按键状态,同时把键值A输出到DATA
    ' x2 n& l" M1 o. y7 q$ K# U3 b
  97.         key = bufReady;
    . A7 R  \* |! K7 d$ e2 t- p9 y
  98.         DATA = key & 0x80;//mask[0];        // 为了加速运算,直接取表中的值而不是读表
    & I& }9 b, f$ j" |5 I
  99.         idx = 0;
    ' {8 }/ }: m; ~$ k+ [
  100.         // 允许CLK进行移位6 W/ H6 [5 a) M% m6 t& x2 H& W9 z4 ?5 I
  101.         isReady = 1;" m2 i4 k1 n2 q% Q
  102. }
    ! N( |1 s+ y3 a& q+ j# Z4 U% B

  103. 6 y+ H! @' V' b* w( i- {
  104. void main(){
    8 _6 G# K' S% e. M, m0 d7 Z, ?, Z
  105.         GPIO_Init();
    % m% w( j/ P# ?0 `  T1 @6 i
  106.         Interrupt_Init();
    , i9 ]3 r; Y* z% W  R3 i) }
  107.        
    ( z; s# w9 I3 w- f# M; g# _7 L2 C
  108.         while(1){
    " T7 N$ z+ w' Q1 x4 [# c
  109.                 //PCON |= 0x01;        // 进入省电模式
    4 L$ b& b( D9 V/ [6 `) C; {& \: L
  110.                 //_nop_();
    9 ]1 J3 C4 D0 o7 K1 ]4 m; H  w' G) s0 Z
  111.                 //_nop_();
    3 P) m' A% c# A+ w5 d" n$ ~
  112.                 //_nop_();  W7 A3 s& n* d
  113.                 //_nop_();; m, M8 |( K! F+ ^
  114.                 buf = ~((P1 & 0x3F) | ((P5 << 2) & 0xC0));
    ! u, v: o: L5 m
  115.                 bufReady = buf;- ^9 J2 ~2 {$ m% ~( N9 b
  116.         }
    5 e' s. e1 X/ }: T! A1 [4 O2 V' |
  117. }7 H$ u% m1 j8 a$ A" q# N! p- g- {
复制代码
( @/ @  p( U/ y2 u8 _
硬件参数配置无特殊要求,晶振频率选择12M即可。  [+ {* e1 h8 Y: S# w* }& \' ]
# ~. w  U* ]; `, p7 [' 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:055 j# H, e. q' T9 r( X. N$ D
不错的设计,想问一下楼主,FC的15针公头怎么解决?普通的公头太短了,插不进去FC的扩展接口。 ...

" {9 b. ~4 g$ I& @& M: h! H坛友的改造方案
回复

使用道具 举报

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

使用道具 举报

发表于 2019-5-25 12:07:18 | 显示全部楼层
精彩,楼主动手强,也写得很详细。3 r3 ]7 F: t$ d+ t
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
6 X2 Q' f" L9 t+ P1 m精彩,楼主动手强,也写得很详细。
1 i8 m* x& A6 u/ h0 J0 Z2.4G方案是目前无线的最低延迟吗?
& u) `. H/ @1 T& ~" ?. m
我没用过其他无线手柄,所以实在不知道我自己做的这个手柄到底是不是最低延迟。  o  d0 U$ K+ N' }# |
不过根据网上的说法,延迟高低主要是由通信协议的复杂程度,以及数据传输速率决定的。这个模块虽然是2.4G无线模块,但由于协议很简单,所以延迟比较低。
- N6 d' @- C' B: r我用这个手柄玩一些ACT游戏,比如超级马里奥、忍者龙剑传、热血系列,完全感觉不到延迟,和游戏机自带的手柄没有任何区别。唯一的区别就是这个手柄是用火花山寨手柄改造的,外壳是垃圾回收塑料,粗糙+脆弱,导电橡胶弹性不佳,手感不是一般的差。5 d/ M8 q. G- i. q, z
我手里还有十几张板子,等我有空了我再做一套,到时候买一个好一点的手柄改造。
回复

使用道具 举报

 楼主| 发表于 2019-5-29 16:56:14 | 显示全部楼层
ppad 发表于 2019-5-28 17:27. L- W9 y1 a: N6 S
给技术帝赞一个,有半成品发布吗,自己焊接改造就可以,编程实在不会啊 ...

; |6 k( \! z( {! D9 c; e2 f4 X- T: B很可惜,我手里没有多余的单片机了,LDO也找不到了,锂电池以及充电模块更是没有了。反正就是该用到的元件基本都没了,所以没法发布半成品。8 o  V' H$ M. q8 G$ q
两个板子倒是有十几张剩余。, W  X2 }7 k" f+ @- ]# t$ V
你要是有USB转TTL串口板,完全可以自己买这两种单片机,然后我给你编译好的固件,你自己用串口板下载到单片机里面就行了。两个2.4G无线模块也得通过串口板用AT命令设置参数,不过好在我在设计电路的时候就已经预留好了串口,可以直接在线下载和在线设置参数。总的来说并不麻烦。
回复

使用道具 举报

 楼主| 发表于 2019-5-29 17:00:34 | 显示全部楼层
孙大师 发表于 2019-5-28 18:55. J3 |: r; D1 e
非常好,楼主是技术帝,到目前我都还没开发fc的无线套件,等空了,开发一套套件,等玩家自己组装。 ...
5 e3 M# u& p; g. P7 G# i* |( ?( r$ q
能得到孙大师的赞誉,不胜荣幸!
5 R! p- Q4 p: s2 ]不如开发一个多功能手柄,比如用SFC手柄改造,L/R键配合其他组合键可以用来切换2P~4P、调节连发速度、软重启等各种功能。接收端插到15PIN扩展口。
回复

使用道具 举报

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

本版积分规则

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

GMT+8, 2026-8-28 10:41 , Processed in 2.020750 second(s), 14 queries .

Powered by Discuz! X3.5

© 2001-2025 Discuz! Team.

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