找回密码
 注册

QQ登录

只需一步,快速开始

查看: 24232|回复: 29

自制FC无线手柄

  [复制链接]
发表于 2019-5-22 14:16:45 | 显示全部楼层 |阅读模式
本帖最后由 雷精灵2046 于 2019-6-14 09:28 编辑 4 s) P! K' _8 S& }, q

( t8 S8 U0 N- L9 }. z! U# K7 k% Z没有用复杂的分立元件搭建发射接收电路,直接用的现成的2.4G无线模块jdy-40。
# }' Q! O( h5 Z% c
% \5 M; r" k% f3 c) {- f
  m/ t9 C& q0 c& L9 y, o0 a0 m发射端靠3.7V锂电池供电,用了一片SOP8封装的STC单片机,负责产生连发脉冲,同时负责检测电池电量,电压低于3V左右的时候触发低压中断,低压指示LED就会亮起来告知该充电了。平时发射模块和单片机均处于睡眠状态,有按键按下才会唤醒,从而实现省电。实测睡眠状态下整机电流约1~2uA。板子洗了一下稍微干净了一点。因为对于微功耗设备来说,焊接残余的助焊剂可能会增加漏电流。
2 k& k2 ?$ a# |5 `, z0 Q: I) I- k
3 Y3 P* ]6 R9 s买了一个火花的FC山寨手柄,去掉里面的牛屎板子,并修正一下塑料挡板,把锂电池和充电模块装进去。9 `* m! V' f8 t5 R7 Y
为了减少体积,充电模块裁剪得十分小,并且更换了充电电阻使之适应这个小小的锂电池。这么小容量的电池,也不需要多么大的充电电流是吧?/ G/ e7 \! v% J* F! W2 P( y
然后统统用热熔胶粘上。充电电流比较小,所以发热很少,不会熔化热熔胶。
- t  w0 c1 g) _4 D( K7 L- v% \  {& L3 c+ y& o

0 m+ @5 Z+ i3 j
3 i1 Q  Z  p6 s! \. ~7 p3 m( E最后把按键、导电橡胶和电路板装上去。
. ^& `2 z3 ]3 {( T1 _& [1 \精心裁剪了电路板,正好扣上,不会阻碍其他元件,也不会影响后盖和拧螺丝。# z- t7 _1 Z1 ]- m! P5 [2 u7 ]  [: v4 G

# W: K" O& i" i7 `; k
3 k: K- V/ ~* a8 C/ {& k& m" j3 r完工!* L% K. y. l2 ~% R: F) A: D
/ s3 I9 J! Q, ?/ }

* S  r7 c3 P. [6 @这是充电的MicroUSB插座。旁边的小孔用于透出低压报警LED的光线。1 W4 W) _7 \& ~- a0 C0 y8 ?
4 k# x8 g' z8 Y8 G- o
4 p! _+ ^/ G# V" K5 a  M# `  M
接收端用一片DIP16封装的STC单片机模拟CD4021。为啥要用单片机模拟而不是直接用CD4021?因为jdy-40模块接收端在有按键按下的时候输出高电平,无按键按下输出低电平,和普通手柄正好相反。当然我也可以用两片74HC00或者74HC04之类的逻辑门进行反相,但那就增加了芯片的数量。对于FC手柄这种工作频率并不高的设备来说,STC单片机完全可以胜任模拟工作。
) E/ j$ X5 h  ?
$ P* w0 K; o0 j$ [7 N  U: x
. x- w* D- |% e8 F5 B6 b* L# L
- X! a1 i. e& R3 p' x/ r电路设计有点小小的错误,所以有几根飞线。原本设计使用低压差LDO是XC6206,结果在做这个接收模块的时候,买的LDO居然找不到了!无奈只好用了AMS1117。幸好对于接收模块来说是5V降到3.3V,1117可以胜任。要是发射端手柄的话,3.7V降到3.3V,那就非得用6206不可了。& o2 x/ W2 e: f3 w% X4 U5 q

5 Q* i3 Y# ]: s9 W" g: G8 K实测十分灵敏,延迟极小几乎感觉不出来。可惜这山寨手柄的手感并不佳,尤其是方向键,软塌塌的。看来我得买个剪线手柄改装。
. ?$ n, m: L* z, W+ c6 R2 w
8 {- {* v" p. b( q这是电路图,有兴趣的朋友可以参考。
( M0 O  a1 e$ c% X! B* }7 X6 ~2 C! p* m$ R

6 N0 ?/ F; g5 l" v- H2 _: G我信奉开源主义,十分痛恨把技术藏着掖着。好东西大家分享嘛!所以两个单片机的源代码大公开!
/ ~. R2 k" b' h3 t编译器:Keil 51。
! T" u( m, i4 k9 W" q1 P. O: K4 ~% e" J& F% E$ E% t3 U
发射端:
: S: d4 \7 b1 H/ Z' b
  1. #include <INTRINS.H>5 w" ?, K2 p3 H$ T0 b
  2. #include "STC15W.h"( b- ^/ l7 t" H' U: r# p

  3. + O9 E3 \; `  |* Z# u8 {& X" q
  4. ! O) b, z4 H% _& O& O6 F4 k
  5. /*
    " f7 @5 e( [1 r
  6. --------------------------
    - V- v5 ~* X- ~7 R
  7. |1 (OUT)        \__/   (INT1) 8|0 [3 y7 b! ~% c) g8 i( n! x
  8. |                                                   |
    ! r1 S" Q$ }$ v6 v; i
  9. |2 (VCC)                   (INT0) 7|
    3 e( ~3 k7 p9 X4 P- R! F. Y, k
  10. |                 STC15W204S                   |
    8 g4 W$ `/ Q8 Z1 ^
  11. |3 (LED)                         (TXD) 6|
    : Y: e. t  ]% S7 v; a8 b5 Z
  12. |                                                   |
    9 e. e( x" r% D) M6 C+ L
  13. |4 (GND)                         (RXD) 5|
    2 e2 n2 h1 |) r. _: ~
  14. --------------------------
    9 _2 |5 \. b  T/ V# j

  15. - S3 A  C9 Y  D; X: d& n
  16. LED ---|<|---[===]--- VCC) w. ?5 O0 I" h+ Y9 h1 d+ v
  17.            Red          330
    . ^1 A0 s. F. N+ g9 ~

  18.   n  P' w7 W' ~. @
  19. Fosc = 6MHz- `' Z" `' q" U1 C7 W6 t6 p$ }
  20. */
    $ F( e2 E1 l- {" v! q
  21. 5 p, ?! Z9 V" b' b0 y5 x& K

  22.   D+ N& d1 p, D
  23. // 矩形波输出脚' ?: `& Q# B/ |- D5 d
  24. sbit OUT = P5^4;: U! |; W( u$ V0 p2 F# `( Y$ D
  25. // 低压指示灯引脚! W+ {5 P5 H! t7 ^
  26. sbit LED = P5^5;. B% D3 e4 g' }; j  S$ b! n
  27. . j' S& ^" x1 N6 F" U3 G9 [, I
  28. // 停机标志位& Y' d- |9 T# g8 M: u" E. Q+ m
  29. bit isReadyToHalt = 0;
    0 ^7 R: p+ K! R* t

  30. 2 E' X$ ]0 v( y* n) G3 f0 A
  31. // 矩形波次数累计
    5 G+ U9 ~" X. o
  32. static volatile unsigned char count = 0;+ S  O. D: `; k8 `8 y0 {! O& g

  33. * m, E/ t8 ]) x, |- ~& p2 X

  34. 6 d3 y/ u# o9 A# I6 w2 T5 {" T
  35. static void GPIO_Init(){+ f( Y; c7 n# B
  36.         // P3口设置为准双向,默认靠内部弱上拉输出高电平
    " D* {4 N+ K$ G. m* q1 Q) v
  37.         P3M0 = 0;
    $ H8 H- M5 ^: b* }# R5 W: ~
  38.         P3M1 = 0;, X5 x$ s/ ?  Y9 p* F
  39.         P3 = 0xFF;* O1 T# T$ N& z$ H4 r  G
  40.         // P5口设置为准双向,默认靠内部弱上拉输出高电平4 T3 [" W; c, f  D' y$ M, P; i
  41.         P5M0 = 0;3 J' J9 z1 H. P% L& M) G
  42.         P5M1 = 0;8 @7 ^1 L; }1 w; k; [# B; N7 @7 S' |
  43.         P5 = 0xFF;
    0 N' `0 |9 s( s, d( w
  44. }) {8 A, w8 g/ m# ?" u! w% _! {
  45. : b) |- i: K% P
  46. static void Timer0_Init(){! V/ [" ?5 ]0 U. g, Y4 l4 {& @7 @
  47.         // 16毫秒@6.000MHz5 o; y: Y- f. I
  48.         AUXR &= 0x7F;        // 定时器时钟12T模式
    * A# }  Q& {# g& Q7 H9 P: d; ~6 g! l
  49.         TMOD &= 0xF0;        // 设置定时器模式* e$ ]! i. b/ A7 G
  50.         TL0 = 0xC0;                // 设置定时初值7 x! k. @% G7 N$ G8 ?0 q$ }3 s
  51.         TH0 = 0xE0;                // 设置定时初值
    1 B# P' a& }, ]% D$ j$ n  p; j
  52.         TF0 = 0;                // 清除TF0标志9 q% K  d0 }  @' l5 @$ w: F6 Q! I5 d
  53.         TR0 = 1;                // 定时器0开始计时
    ) G" B$ x. w5 Y: E) l( r/ V
  54. }% @' n8 q# J5 X) M: Y

  55. " U; B/ U; ?8 V
  56. static void Interrupt_Init(){& F. g% X& X9 B6 m. t
  57.         // INT0中断触发类型为下降沿触发- j/ k3 _! s  T+ o* ^/ ?5 n" ]
  58.         IT0 = 1;5 E$ m3 h: C' k+ t7 d
  59.         // 允许INT0中断
    / k6 Z2 N0 w! k2 l
  60.         EX0 = 1;) V9 j* `1 K# G( C# v  T8 `
  61.         // INT1中断触发类型为下降沿触发
    4 m) v$ {) D+ x/ D1 q/ X
  62.         IT1 = 1;) Z0 e2 y; i+ s
  63.         // 允许INT1中断
    9 f; M% |- e" j5 _" `
  64.         EX1 = 1;
    . k9 }" W& N! A
  65.         // 允许定时器0中断
    # z0 Q* q8 O( t$ J/ [! v
  66.         ET0 = 1;' A( O* E: b7 T. ]5 N+ H0 e
  67.         // 允许全局中断- z4 _9 P% T/ H8 y4 E
  68.         EA = 1;
    ' y: P, Y9 }& j9 q5 M3 F1 s* ~
  69. }2 u1 Q. \' e7 w/ R0 v6 t& I" {5 g

  70. 3 `% i0 R: B& o4 ~
  71. static void INT0_Isr() interrupt 0{
    ! w5 m5 `4 j! J+ M7 W, f
  72.         // 矩形波次数累计归零
    9 U: m0 v# b% ?/ U
  73.         count = 0;
    / i( `! a" @( j" a' d0 f
  74.         // 重开定时器0中断' _+ Z4 M7 R/ p8 I. A4 j# ^$ A
  75.         ET0 = 1;
    , x+ _# F& Q; `9 k
  76. }( g3 I8 `8 u5 q
  77. + S6 ~) u- J# q- q# c
  78. static void Timer0_Isr() interrupt 1{
    . I& R1 }3 i; h  R6 q7 W  K
  79.         // 输出矩形波/ k+ a5 A+ W/ v9 p- r; `
  80.         OUT = ~OUT;
    & n# w* r! w4 S
  81.         // 累计矩形波次数3 R( t' j+ w2 ?
  82.         count++;9 b. X( u+ W! G. t8 B- i& H7 f
  83.         // 超过250个矩形波,准备停机8 k) t/ G% D9 m1 W2 w
  84.         if(count > 250){& w4 X0 ?2 X' m. J# @& T& h
  85.                 count = 0;' ], S* W9 j) U2 v' b1 D
  86.                 isReadyToHalt = 1;* s; u5 a1 t% r* \6 z
  87.         }" L' k0 \- p1 j6 y8 q) _
  88. }
    ! }; j3 V2 J5 t8 K! L1 ?) l; i

  89. 7 K' A/ _" x2 y" v8 Q7 G6 \
  90. static void INT1_Isr() interrupt 2{8 }2 t7 Z7 \% I( k3 @- M3 s
  91.         // 矩形波次数累计归零
    6 N2 ]3 g9 a# ^# W: X* y
  92.         count = 0;
    - p- [1 j8 K9 n) a6 l& D
  93.         // 重开定时器0中断9 i4 i- S8 \5 [  u& `
  94.         ET0 = 1;
    # ~* E  O3 I2 N: `# Y3 w8 r+ U! G. X
  95. }# S7 j6 _/ c7 \

  96. $ R; W* w0 K5 P; s

  97. " [7 |# g3 a- V0 ^# J
  98. void main(){
    - M, ^1 z3 e- t! f
  99.         // 初始化P3和P5口
      L  j- J& I7 c/ @
  100.         GPIO_Init();8 s! x! }4 |6 |* h& b
  101.         // 初始化定时器0% y! T3 t$ A1 p6 c- [/ |
  102.         Timer0_Init();
    , O( ~: p- v' F+ t. b1 F
  103.         // 初始化中断3 |" e- v2 t% Z. ?9 z0 {
  104.         Interrupt_Init();
    4 ?# U1 |: m- `& z
  105.        
    4 p: F7 l4 O! m; M' m
  106.         while(1){4 ]; Q1 t0 U' z* y6 f0 T5 n8 ~
  107.                 // 检测电量
    " Z' u- I& l0 p$ S
  108.                 if(PCON & (1 << 5)){
    4 H0 B% F2 i- f
  109.                         // 如果电量低,低压指示灯亮/ q$ o% M% K( K6 y* R+ }
  110.                         LED = 0;- `5 O( B1 H) J5 S/ [3 ?( R% ?
  111.                         // 清电量检测硬件标志位* X) b' j) @, H4 X4 |% V
  112.                         PCON &= ~(1 << 5);) r& y1 F. `) K' v
  113.                 }else{
    : E$ C$ Q6 Q& m& D- |
  114.                         // 电量正常,低压指示灯灭& J" T! {, g& u! o# }, y( T! R
  115.                         LED = 1;
    ( U! e& @+ E; n4 M4 r0 u$ G
  116.                 }% `6 M0 C6 q5 ^. X3 S; p5 m; k

  117. * l; J8 @- V- Y% d/ a# h/ a5 b& {
  118.                 // 检测到停机标志6 b. \* s4 G* A: O( W7 e
  119.                 if(isReadyToHalt == 1){
    $ Z' n) ?8 G. A
  120.                         // 暂时关闭定时器0中断
    , z& b5 d( b+ ], ~7 z
  121.                         ET0 = 0;
    / ~, Q; e4 E5 z
  122.                         // 停机之前先把矩形波输出脚置低电平,以方便INT0和INT1唤醒CPU4 ?; D6 M: T" S6 {1 v9 }6 P3 k; t( u
  123.                         OUT = 0;
    & h9 k0 e$ p  P) e7 W
  124.                         // 停机之前先把低压指示灯灭掉,以省电
    4 \. h. l2 O6 Z  K  h7 o' O
  125.                         LED = 1;
    7 l! E$ A1 y' P+ y( g$ W  v
  126.                         // 进入停机模式! N1 L( y0 l& U" [' ]8 n
  127.                         PCON |= 0x02;
    % l  w% |; H" A" q6 O6 k1 H
  128.                         _nop_();
    . S, ^  O" o" {9 @
  129.                         _nop_();
    4 r. f( c8 j( Z2 G9 X" n
  130.                         _nop_();
    , x# d7 \; G0 p3 L8 |
  131.                         _nop_();
    1 f5 A) E5 \& }; _
  132.                         // 唤醒,清标志位+ z' `# ^0 D9 {! z5 V' e" c+ t  `/ F
  133.                         isReadyToHalt = 0;6 Z$ \; W( M/ p+ P
  134.                         // 重开定时器0中断
    ! ^! Z& J! k3 I% b4 l
  135.                         ET0 = 1;7 E! G; K" [* q; y) R9 _" \
  136.                 }
    3 M7 F  S* n7 T4 V/ u0 _( b0 M
  137.         }
    & |* i" F0 F  R1 J
  138. }9 Z* t& v) t% J) K% b% s$ ~
复制代码
6 Z; r! n. d  x- L: x' i
硬件参数配置:
5 b' e2 K5 S2 B' C% r& S6 D- E- v9 w5 b' }, @2 p! i# N
  T- _* A4 v. Q& @  E( k& h
接收端:
" Y; k( j' ^; {& ~5 q! @
  1. #include <INTRINS.H>4 h. t9 d4 W' j; ?- r
  2. #include "STC15W.h": _3 j( a, G+ e! w' Q

  3. . P" S! E( M# a

  4. * j+ Q$ d! R  G+ T- q
  5. /*, e7 c3 X  b: i$ U# O6 P

  6. . Y" T( Y' @3 K7 j
  7. *---------------------------*4 d4 P1 Q: z  m
  8. |1 (GPIO2)         \__/  (GPIO1)16|9 r8 X6 L- z( A$ b( m" _( p
  9. |                                                        |
    5 l$ v/ h: P0 c! W+ b5 c$ \
  10. |2 (GPIO3)                   (GPIO0)15|+ d, `; i3 D& U) T9 C+ x
  11. |                                                        |' R( p% \: d; H: M6 ?; J
  12. |3 (GPIO4)                                  14|- T5 Q- X: Y6 C( e& @
  13. |                                                        |
    % y$ @; k8 A5 h" ^  z8 s; Y- M
  14. |4 (GPIO5)                        (DATA)13|" f0 H+ ]( W. y
  15. |                  STC15W204S                |
    1 j$ m/ i: Q& ], {& _* e: e
  16. |5 (GPIO6)                   (LATCH)12|
    0 \, k( T8 m8 M& p  s
  17. |                                                        |
    , s5 w3 o: X; S/ o( f
  18. |6 (VCC)                         (CLK)11|
    ) R- D+ Z9 m) Y# S# Q. Q
  19. |                                                          |
    7 r& l' \* i/ K! w
  20. |7 (GPIO7)                         (TXD)10|
    6 D* t4 ?3 p! `* E! O
  21. |                                                        |9 j4 {5 \/ r8 h
  22. |8 (GND)                         (RXD) 9|
    - R& ]- D' c* L7 s- ]; ~: x
  23. *---------------------------*& {$ J# @% p) _
  24. Fosc = 12MHz2 |9 ^9 N. T- t6 c8 t! A

  25. ( i8 {, M1 u; s
  26. P1.0 -> 上
    5 \. v8 q7 u' K: B' E9 R
  27. P1.1 -> 左# ^, V" R, ]2 _9 g' F4 E: I( H) U, I
  28. P1.2 -> 下) L( |  u* T; w# v: U3 p# D
  29. P1.3 -> 右
    . s. Q$ y/ N1 ~; z+ S: P
  30. P1.4 -> SEL
    6 w0 o4 ^2 P& ?4 [& E
  31. P1.5 -> STA
    * G* r2 E" k$ m. I
  32. P5.4 -> B( S5 r( u$ r  N% ^
  33. P5.5 -> A3 _( ^1 H5 o' `* L2 E) J

  34. 0 H* b# M2 _; e% O! [4 D
  35. */+ v+ S, c2 D3 F

  36. 5 K7 m# ]2 p& P1 }8 f

  37. ' T( x( m9 |, `: f
  38. sbit CLK        = P3^2;2 D: o  j" @. D5 u6 ?( T
  39. sbit LATCH        = P3^3;! b3 R+ Q5 |& b
  40. sbit DATA        = P3^6;2 o. g/ T' K# g+ e
  41. ! Q" g% T( U0 Q& m
  42. bit isReady = 0;
      d( j8 J" X2 @
  43. static unsigned char key = 0;
    $ Y1 t: Z8 |$ N  }) f7 Q3 K) c
  44. static unsigned char buf = 0;        // 双缓冲。这个缓冲区保存从P1和P5组合而来的键值0 T: u6 {+ q7 Y3 v
  45. static unsigned char bufReady = 0;        // 双缓冲。这个缓冲区保存上面那个缓冲区的备份. B, P, L/ N6 _
  46. static const unsigned char data mask[] = {0x80, 0x40, 0x10, 0x20, 0x01, 0x04, 0x02, 0x08};        // A B SELECT START UP DOWN LEFT RIGHT。为提升速度,这个表放到RAM中, C1 r- @! Q4 z* `5 [1 N
  47. static unsigned char idx = 0;* A& v, M3 d- w

  48. * X' X$ o6 A; |2 |6 [  J/ d  ~7 G
  49. ' I. x- M* G: f2 [
  50. static void GPIO_Init(){. S2 I5 I3 K: _. c8 s
  51.         // P1口和P5口用于接收并行信号,全部初始化为准双向,依靠内部弱上拉输出高电平
    ' K+ n; c, @/ L$ @8 N5 N: f* L9 q# d
  52.         P1M0 = 0;
    ' q: H3 Z8 _7 q- S  b! k/ x3 z
  53.         P1M1 = 0;
    0 w" y3 t3 U: _) U" W( A8 N
  54.         P1= 0xFF;4 Z+ ]9 T. T5 P( Z
  55.         P5M0 = 0;
    $ @8 W* E4 M" [" p# N/ {+ Y/ F
  56.         P5M1 = 0;
    - E$ h8 m/ M1 w- x, V6 ^8 q: }
  57.         P5= 0xFF;
    ! m4 z6 s& z6 \4 W- U: m1 |
  58.         // P3口初始化为准双向
    0 _' b$ ?" e1 F& l* W
  59.         P3M0 = 0;
    7 ^5 u: t5 S1 r$ j7 ]$ f* Y
  60.         P3M1 = 0;$ I- h4 a0 P( E5 o" I
  61.         P3 = 0xFF;4 S! ]& y+ {3 T" J2 o
  62. }. K% w- B* k3 L
  63. - Z/ O- q/ |, @) c2 y' E
  64. static void Interrupt_Init(){. E5 n2 x  b: ]
  65.         // INT0中断(CLK)触发类型为上升沿+下降沿* n) A+ A) ?" R, k$ G) M! M2 g" f
  66.         IT0 = 0;' u' L& w+ {4 {2 l3 w1 Y3 F$ u
  67.         // 允许INT0中断
    * J. I) n2 S4 ~+ U
  68.         EX0 = 1;5 S7 J5 d5 S- m! V1 ]
  69.         // INT1中断(LATCH)触发类型为上升沿+下降沿
    + I8 q" W; F$ }; F0 e& h) P
  70.         IT1 = 0;  @, b( J: y' f5 N: V. x8 y0 j- m
  71.         // 允许INT1中断
    7 o6 s+ q0 F  a% e6 d+ G
  72.         EX1 = 1;
    * t; {! w: z" D7 T  X- |
  73.         // 开启全局中断
    ; }# E/ J! @9 P8 T0 p  O! m+ p4 G  U
  74.         EA = 1;4 R" d( t2 S) V/ [1 o: n' c( ?/ F! Q
  75. }
    * t- }$ i  O( }3 V! W
  76. , o" |' b$ b4 t3 n
  77. static void INT0_Isr() interrupt 0{
    & G! I( U& Z3 k: \$ U  M0 `
  78.         // 只有已经成功锁存才允许CLK移位) B# x, Z6 }/ D& G' z  s
  79.         if(isReady == 0)
    , f6 Z0 a3 \, t9 b
  80.                 return;
    & f7 O! u" O+ y" ?0 |0 i- v$ v: e
  81.         // 读当前引脚电平,如果是低电平则说明是下降沿,此时直接忽略该中断1 b; B. z  Z0 m
  82.         if(CLK == 0)
    ) M0 C3 j  S/ U  i1 H' `" t( W( U
  83.                 return;8 x+ y! z8 i% g6 @* ]0 {& c
  84.         // CLK上升沿到来的时候,取锁存值的下一位输出
    6 `9 K0 H- r0 N" y. s/ D! U6 u
  85.         idx++;
    * b. Z3 a! T8 a  b5 N; \8 |
  86.         DATA = key & mask[idx];/ d, _1 u8 _' C; E, M' @4 }
  87.         // 如果已经完成7次移位,则一轮读取完成- S! Z) q9 V+ s# D( P
  88.         if(idx >= 7)
    6 `, ^6 x3 [( a1 ^4 J3 O
  89.                 isReady = 0;# S' I3 ?- c4 g/ V
  90. }% y1 o. F; _. @( B/ q- P! p
  91. & ?( i/ G( a( Y9 _0 K1 y
  92. static void INT1_Isr() interrupt 2{
    ' l" V2 L  o+ q% b
  93.         // 读当前引脚电平,如果是低电平则说明是下降沿,此时直接忽略该中断) z( ~+ H( O  M4 Y
  94.         if(LATCH == 0)
    ! k5 G8 o6 l+ ~+ |7 J9 f: J+ N
  95.                 return;% W# R/ m  W- [
  96.         // 当LATCH上升沿到来的时候,锁存所有按键状态,同时把键值A输出到DATA  C7 Q* A+ \9 |, t; J. I
  97.         key = bufReady;
    ' r/ I% P( ^" f% V
  98.         DATA = key & 0x80;//mask[0];        // 为了加速运算,直接取表中的值而不是读表
    1 @  F& w& d2 z1 j" Z/ x$ L: z
  99.         idx = 0;8 U. I6 o  `; b
  100.         // 允许CLK进行移位; y0 B( D4 b7 C1 y1 f3 _" V
  101.         isReady = 1;
    2 @' N, x; ~/ L7 C
  102. }7 I& ~3 S6 V; g( G
  103. 2 m# s3 ]6 @& T, O9 g+ N" w
  104. void main(){
    $ }' H- m3 Q' T, g4 g
  105.         GPIO_Init();- H" z1 a' t1 u" B1 R* u. b
  106.         Interrupt_Init();
    4 A: o; W/ o& W$ ^9 _
  107.         ! I7 B) ]' X3 w3 B5 p
  108.         while(1){
    1 a9 U: @& I9 J. W/ v3 X
  109.                 //PCON |= 0x01;        // 进入省电模式
    7 I0 h( _4 u. h# Q  r
  110.                 //_nop_();
    6 E; D) {2 [, c0 P$ F8 \- P& `4 a
  111.                 //_nop_();
    ; l$ M. `8 J+ v
  112.                 //_nop_();, d  }' A7 \2 G. o( h% d
  113.                 //_nop_();
      @) q4 c) p0 m1 C* ?: y
  114.                 buf = ~((P1 & 0x3F) | ((P5 << 2) & 0xC0));
    , t$ ?6 n, e0 O1 J( N. X
  115.                 bufReady = buf;
    2 F+ p: }5 ~5 y$ q- ^
  116.         }
    3 C! r- B  K1 I& S% |. Y4 s1 d
  117. }8 e/ D  c* k  s
复制代码

. R, Q% [4 }+ T0 q, _硬件参数配置无特殊要求,晶振频率选择12M即可。
) S; ]- k' p$ h1 ?- W$ s
! @5 C' G5 Z6 ?: |% @# G这是编译好的固件。

本帖子中包含更多资源

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

×

评分

参与人数 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) f4 Z4 B/ w! F  q; K/ }
不错的设计,想问一下楼主,FC的15针公头怎么解决?普通的公头太短了,插不进去FC的扩展接口。 ...
& B# |% B$ g) |9 }# H3 F0 B
坛友的改造方案
回复

使用道具 举报

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

使用道具 举报

发表于 2019-5-25 12:07:18 | 显示全部楼层
精彩,楼主动手强,也写得很详细。
9 C+ o1 v$ j! ]( l! j2.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
5 p1 c, ^9 [8 D精彩,楼主动手强,也写得很详细。! O7 o& A& ?# T. P1 I. w; S4 `
2.4G方案是目前无线的最低延迟吗?

5 w; e7 c9 j# R! W- \4 L我没用过其他无线手柄,所以实在不知道我自己做的这个手柄到底是不是最低延迟。9 m: [8 }/ t# \4 X: |% q' B6 S
不过根据网上的说法,延迟高低主要是由通信协议的复杂程度,以及数据传输速率决定的。这个模块虽然是2.4G无线模块,但由于协议很简单,所以延迟比较低。% N+ K3 D$ Z! a" W0 C0 ^: V, n( n
我用这个手柄玩一些ACT游戏,比如超级马里奥、忍者龙剑传、热血系列,完全感觉不到延迟,和游戏机自带的手柄没有任何区别。唯一的区别就是这个手柄是用火花山寨手柄改造的,外壳是垃圾回收塑料,粗糙+脆弱,导电橡胶弹性不佳,手感不是一般的差。) R- C2 p& k0 q3 G
我手里还有十几张板子,等我有空了我再做一套,到时候买一个好一点的手柄改造。
回复

使用道具 举报

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

使用道具 举报

 楼主| 发表于 2019-5-29 17:00:34 | 显示全部楼层
孙大师 发表于 2019-5-28 18:55/ C: u0 g+ V' w: @, l
非常好,楼主是技术帝,到目前我都还没开发fc的无线套件,等空了,开发一套套件,等玩家自己组装。 ...
" ?3 E+ Z% B& W- H9 W8 P5 w, Z
能得到孙大师的赞誉,不胜荣幸!: r" c* m; y7 ]+ J, @
不如开发一个多功能手柄,比如用SFC手柄改造,L/R键配合其他组合键可以用来切换2P~4P、调节连发速度、软重启等各种功能。接收端插到15PIN扩展口。
回复

使用道具 举报

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

本版积分规则

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

GMT+8, 2026-3-22 16:14 , Processed in 0.103429 second(s), 15 queries .

Powered by Discuz! X3.5

© 2001-2025 Discuz! Team.

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