找回密码
 注册

QQ登录

只需一步,快速开始

查看: 25499|回复: 32

自制FC无线手柄

  [复制链接]
发表于 2019-5-22 14:16:45 | 显示全部楼层 |阅读模式
本帖最后由 雷精灵2046 于 2019-6-14 09:28 编辑
6 s" x3 }6 [+ a9 [; f
4 `5 r: T; h# ~; g' I7 u1 Q没有用复杂的分立元件搭建发射接收电路,直接用的现成的2.4G无线模块jdy-40。
; e! ?& \& c1 g( }$ \1 b  G, v4 ]0 Z% Y

. S5 ?  r, X! h: C6 h0 {$ d发射端靠3.7V锂电池供电,用了一片SOP8封装的STC单片机,负责产生连发脉冲,同时负责检测电池电量,电压低于3V左右的时候触发低压中断,低压指示LED就会亮起来告知该充电了。平时发射模块和单片机均处于睡眠状态,有按键按下才会唤醒,从而实现省电。实测睡眠状态下整机电流约1~2uA。板子洗了一下稍微干净了一点。因为对于微功耗设备来说,焊接残余的助焊剂可能会增加漏电流。
- `8 ^7 Y( X6 C- O* I; s" G, i7 C; `
买了一个火花的FC山寨手柄,去掉里面的牛屎板子,并修正一下塑料挡板,把锂电池和充电模块装进去。
, g3 }9 i. ~$ b" I& K为了减少体积,充电模块裁剪得十分小,并且更换了充电电阻使之适应这个小小的锂电池。这么小容量的电池,也不需要多么大的充电电流是吧?8 l! ^4 K# }: S1 `
然后统统用热熔胶粘上。充电电流比较小,所以发热很少,不会熔化热熔胶。* V3 n8 F2 Z* i' s" ~

& [: ^" _; z9 f  E" J4 G- Z, B7 l* k/ G8 @( y6 u6 E( D
. }" T9 Z: }4 O. d
最后把按键、导电橡胶和电路板装上去。
$ {2 q7 v0 f& `! R# l) {! F7 d精心裁剪了电路板,正好扣上,不会阻碍其他元件,也不会影响后盖和拧螺丝。7 N# ~5 h" l4 e* ~5 o
% R7 J1 J2 \8 t; B( H' ?6 o6 R
/ |# j. N! k, @2 x
完工!- d8 M" R9 n; q# }( J

/ u& @8 i! F7 U5 L
2 }# g# B9 g. b9 k1 P这是充电的MicroUSB插座。旁边的小孔用于透出低压报警LED的光线。1 D$ |! z9 X0 H

. v, n8 N( r- ?6 l) N6 w0 T% j+ v1 c! u* a# E
接收端用一片DIP16封装的STC单片机模拟CD4021。为啥要用单片机模拟而不是直接用CD4021?因为jdy-40模块接收端在有按键按下的时候输出高电平,无按键按下输出低电平,和普通手柄正好相反。当然我也可以用两片74HC00或者74HC04之类的逻辑门进行反相,但那就增加了芯片的数量。对于FC手柄这种工作频率并不高的设备来说,STC单片机完全可以胜任模拟工作。( H; m! X1 c1 z" X$ x

  Y  Z. \3 W  ?7 C7 H- B/ r
; u; _8 ?, @0 p0 [8 ^8 ]; u( M  x: T1 [  i4 R4 U' K4 D
电路设计有点小小的错误,所以有几根飞线。原本设计使用低压差LDO是XC6206,结果在做这个接收模块的时候,买的LDO居然找不到了!无奈只好用了AMS1117。幸好对于接收模块来说是5V降到3.3V,1117可以胜任。要是发射端手柄的话,3.7V降到3.3V,那就非得用6206不可了。
3 Q: B* _, X+ _+ Y, E4 h0 H2 ^8 l
实测十分灵敏,延迟极小几乎感觉不出来。可惜这山寨手柄的手感并不佳,尤其是方向键,软塌塌的。看来我得买个剪线手柄改装。
; o8 e  w7 I  |2 C% T8 p" T
; g6 a8 Y4 q/ ^5 b+ b/ e( B8 U这是电路图,有兴趣的朋友可以参考。
' [, l( z, {" c2 ]8 C' q4 h/ \$ w1 s* n" h  ^5 x2 J  y

, L' d2 z9 O* T7 @我信奉开源主义,十分痛恨把技术藏着掖着。好东西大家分享嘛!所以两个单片机的源代码大公开!
8 T0 K/ L) H! |4 I编译器:Keil 51。7 B# _- X) V6 u1 T* U# W+ `
( i/ L9 u1 {/ q3 g; L
发射端:$ [; a$ a0 v; a/ d8 a
  1. #include <INTRINS.H>+ C4 \) x* E+ A' w5 t
  2. #include "STC15W.h"1 m3 q, I$ R; p" x) z5 S3 \
  3. / z9 n( b  d3 y) a

  4. 5 h. ~. k9 W* W. w0 r* ]& T
  5. /*
    2 R+ L% d) u  M; W& ^7 U' e  k# @; Q
  6. --------------------------8 b' }( f0 i- _. q! }+ V
  7. |1 (OUT)        \__/   (INT1) 8|
    ! M* H2 I, Z" E6 A  R6 M( N
  8. |                                                   |
    9 e; t5 U# U3 K6 {% w8 j% p
  9. |2 (VCC)                   (INT0) 7|
    ; r( w4 s' y1 P4 G
  10. |                 STC15W204S                   |
    ' @5 T9 F& h) d8 X% G
  11. |3 (LED)                         (TXD) 6|
    # e) m) p2 J" [; I6 F7 N
  12. |                                                   |# t6 L0 b- m3 h. Y: Q  ]) Q
  13. |4 (GND)                         (RXD) 5|
    ; Z0 W% d2 U4 n; D* G$ S, \
  14. --------------------------
      C  p& O# w- T. |/ P2 J, r
  15. $ C  l- ^) F/ T' z, Y/ h2 Y  }- c
  16. LED ---|<|---[===]--- VCC0 H- v% W  F' U: l/ `( D( K
  17.            Red          3300 Q2 L3 @' a* b4 f1 P# x
  18. 9 E# A% U! A' G. V( Y% l# w
  19. Fosc = 6MHz
    - h+ M7 S9 T7 S
  20. */0 G$ G' B5 b! A4 L/ b# X. U0 B
  21. 5 Q1 N4 f3 k8 k
  22. , \: J  S& K' ?3 y8 j, C1 _% I
  23. // 矩形波输出脚
    : [3 j' V8 t5 G7 Q$ t
  24. sbit OUT = P5^4;
    * c& \' u3 t: e" u3 A
  25. // 低压指示灯引脚
    ! y9 f% |/ J  x& k7 f  _
  26. sbit LED = P5^5;
    . z/ C8 y- H1 @. I& u$ @
  27. : L! x- ?& f6 j& ^2 D, Q  s
  28. // 停机标志位5 I$ T6 p- R$ e
  29. bit isReadyToHalt = 0;, e; _  u% ?* a/ j* p

  30. ; l4 s" _6 n3 i( G+ j; V) P( L' j
  31. // 矩形波次数累计
    ! }9 [3 }4 X8 a# m/ f: X: I7 P
  32. static volatile unsigned char count = 0;
    0 B5 Y8 u# {: R( H6 A
  33. 6 _$ }, ?, @: G8 g) j6 Z

  34. ! N. C$ `( z6 J+ Q
  35. static void GPIO_Init(){
    : N2 z/ X; \9 ^2 k: ^
  36.         // P3口设置为准双向,默认靠内部弱上拉输出高电平
    2 u0 O9 X. M9 D' A
  37.         P3M0 = 0;# Q- G% R0 n' V6 @1 C6 }
  38.         P3M1 = 0;0 `* |; ^7 u/ R
  39.         P3 = 0xFF;: P3 Z# t, N0 _' U5 x
  40.         // P5口设置为准双向,默认靠内部弱上拉输出高电平
    4 x  S6 A3 Z) c( n* b
  41.         P5M0 = 0;
    - C5 c0 c6 G) x$ m1 [0 b& B9 l* j
  42.         P5M1 = 0;" `% }( g8 }9 M; A6 ]
  43.         P5 = 0xFF;  t2 E* I, A4 Z  C) Q; @- A
  44. }" b, ~7 C% k( j
  45. ; L0 D7 Y9 m3 D" H% h
  46. static void Timer0_Init(){2 x: i; k: Z* `2 n# h3 z
  47.         // 16毫秒@6.000MHz
    6 V- I9 B3 w: z- f& ]+ `6 [# Z% Q
  48.         AUXR &= 0x7F;        // 定时器时钟12T模式& O; h  p6 y& v% T1 I% ^( v# z
  49.         TMOD &= 0xF0;        // 设置定时器模式
    * `$ u$ H: [' }% p7 Y, _
  50.         TL0 = 0xC0;                // 设置定时初值
    ) E0 X8 r7 C& Y* n( C
  51.         TH0 = 0xE0;                // 设置定时初值$ D- u3 J" }  }% q( ]8 z
  52.         TF0 = 0;                // 清除TF0标志. u  @8 {  k$ G2 F$ {0 K  R
  53.         TR0 = 1;                // 定时器0开始计时
    . V% {: X) b' x3 d/ L# F
  54. }
    + J9 R! d1 H8 O$ O! F4 }, V) D
  55. , P# N" K$ T# Z; G
  56. static void Interrupt_Init(){
    $ i7 H1 T  ~& I% f  I# W
  57.         // INT0中断触发类型为下降沿触发: `- I* |/ s7 K: R- j) {7 h
  58.         IT0 = 1;
    ( o0 u2 L: k& T6 ?( B8 s& C3 `3 ?
  59.         // 允许INT0中断! e, `0 b6 q* U/ s
  60.         EX0 = 1;
    7 s6 c/ T; l$ ^% c9 ^" s
  61.         // INT1中断触发类型为下降沿触发
    ! F+ @/ \; B3 B
  62.         IT1 = 1;
      t' o0 X5 z- M2 c" N
  63.         // 允许INT1中断
    6 z4 s$ T. {+ ^- m, w7 @+ O
  64.         EX1 = 1;2 z. S% {. M1 [# k! j
  65.         // 允许定时器0中断1 t/ o4 j1 v4 ?2 S" ]# a% P8 x9 R/ g
  66.         ET0 = 1;" j9 E! v8 Y8 Q- {: f
  67.         // 允许全局中断9 ?5 d* W* w5 i- b
  68.         EA = 1;
    ; g7 I% H- `4 e! V: G* q
  69. }
    / X6 ]2 f8 c' }; U0 B7 g4 X) q

  70. 1 e0 E/ r7 P1 {* _# [$ Z! D9 z
  71. static void INT0_Isr() interrupt 0{
    ( g' ]: A5 L% I5 a* f% y5 w
  72.         // 矩形波次数累计归零3 M( H% v  N9 T
  73.         count = 0;" a' ?9 _3 @+ v% C0 l, G! n% v& J7 K0 j
  74.         // 重开定时器0中断% a1 A4 {. K# |' `
  75.         ET0 = 1;
    3 d& ]) z5 x; }" ^3 K0 v! \! b8 U
  76. }
    7 d9 g: x. }- G% S6 e  [
  77. 9 {& A! z$ B* ?/ W8 Z. K
  78. static void Timer0_Isr() interrupt 1{, Y  ~( Q  a! r( j) A' N' p7 A
  79.         // 输出矩形波
    . C2 X3 E; A* E) t' R" }
  80.         OUT = ~OUT;- A( I% t0 r7 {3 F, o
  81.         // 累计矩形波次数
    % L/ @) Q9 f9 a: \6 V4 \
  82.         count++;4 C) R0 G, Y& A8 ~
  83.         // 超过250个矩形波,准备停机( @* G; K; J# M4 O' w4 _: `
  84.         if(count > 250){% c# ~1 `- o$ ^( N/ J3 k
  85.                 count = 0;
    " ?# \& U8 q+ [
  86.                 isReadyToHalt = 1;
    % b0 _* W9 q6 ]) `
  87.         }! l( w# [  N. }' r' j
  88. }
    1 F9 Q( M: @4 q7 V$ d
  89. $ Z! Y  W4 Z4 p: R2 t
  90. static void INT1_Isr() interrupt 2{; ], C! l8 {3 y% T2 z5 ~
  91.         // 矩形波次数累计归零
      E7 Z8 t) y6 X# H4 Y! r
  92.         count = 0;3 S, s% f: D4 ?! }
  93.         // 重开定时器0中断
    0 z0 Z8 J/ d& @6 a0 w5 t5 Q& b7 M* ]
  94.         ET0 = 1;
      k& D0 s4 f2 b; J; u4 I9 y
  95. }
    , Y4 L( w* R+ _7 ?0 ]

  96. * C, R! ]8 ]3 ~# l7 e/ Q

  97. : e% F( m' A7 K% x: Y3 q. A, i- s: n& ^
  98. void main(){' O4 J8 @9 z, {8 F0 C0 l/ W
  99.         // 初始化P3和P5口
    6 w9 ^: R9 x6 D' r3 x/ I4 {* B
  100.         GPIO_Init();
    9 d6 ]0 I. B7 ?1 `0 b
  101.         // 初始化定时器0& C& ~! L& I( Z2 r6 o+ X( h8 R$ U
  102.         Timer0_Init();4 J$ q% g- o# f& Z, |, Q+ Q- H
  103.         // 初始化中断
    8 R  v0 G4 Z% k# a$ Z0 s" ~+ W
  104.         Interrupt_Init();
    ; }& H% T+ G; R/ ]/ P& ^! \
  105.         ; y- S- m  _5 k/ y  ?8 }
  106.         while(1){2 `0 I8 [* z6 N% n; c( S
  107.                 // 检测电量
    2 p0 ~6 r  e  V
  108.                 if(PCON & (1 << 5)){+ D/ S9 Z4 V8 u
  109.                         // 如果电量低,低压指示灯亮
    0 i4 O0 ~  n) F6 J/ K0 D$ @/ U2 h
  110.                         LED = 0;: x# {2 i8 L! x8 H7 p) k
  111.                         // 清电量检测硬件标志位; V, \6 [' }& d  D' _
  112.                         PCON &= ~(1 << 5);
    " {6 z) _& _+ s2 {
  113.                 }else{2 }" ?2 f% I; N* M( y
  114.                         // 电量正常,低压指示灯灭( Z$ R' I) u( T* V& v6 ]5 Q) M
  115.                         LED = 1;% K3 o  s# |( r: @0 m
  116.                 }+ B! S  N; g1 l5 X! E
  117. . E' u+ `2 J9 C, k
  118.                 // 检测到停机标志# V. s2 Z3 L; l- E5 g9 u$ e; z
  119.                 if(isReadyToHalt == 1){
    & O6 x0 ]4 P& O2 h
  120.                         // 暂时关闭定时器0中断' i1 U  s5 g/ b* W" ^
  121.                         ET0 = 0;; |  F# z: ~8 @2 `* }* N
  122.                         // 停机之前先把矩形波输出脚置低电平,以方便INT0和INT1唤醒CPU, _3 Y6 H: \0 ^* n$ c2 D' f3 L
  123.                         OUT = 0;
    : |8 ^9 T; R, D0 n4 m6 `. [
  124.                         // 停机之前先把低压指示灯灭掉,以省电
    ! ]2 M3 s: d. u. j1 O
  125.                         LED = 1;3 w  `* v, V- G2 v. H6 Z. v% [
  126.                         // 进入停机模式2 _& {1 J% F' x8 M* f) z8 V& k
  127.                         PCON |= 0x02;( ?0 q  I9 a5 a6 v& @7 s: d
  128.                         _nop_();% }. `6 q6 [. n* P+ O: C( z* n
  129.                         _nop_();/ U: U3 x8 K, R( O8 o
  130.                         _nop_();4 y9 J+ L: ~4 }9 o; A5 B5 N; m
  131.                         _nop_();
    + K' i! W) R; v  N# |" F, ~
  132.                         // 唤醒,清标志位
    " t$ m4 `7 j& N5 n  f
  133.                         isReadyToHalt = 0;! C9 e$ }! b2 I- {- T+ n$ h) D
  134.                         // 重开定时器0中断6 U; ?/ R9 _, N' L  H
  135.                         ET0 = 1;
    5 u9 W9 q. e' K, v( U5 o8 f4 v
  136.                 }
      _% p  ]) G) \" r( u
  137.         }- l# [" e4 j9 z0 G1 o7 ~: `. F
  138. }$ M; ~' B( Y$ ]3 e8 K1 l2 X
复制代码

% {+ p, v' Y, j- k2 d# S硬件参数配置:
( d  Y9 D" [; f1 N0 t/ b. M- c: b( i1 t( _# f8 I+ p# {. Z2 _, \
( I( V6 F- m: a+ F1 k" `; Z6 w2 K
接收端:
! w; B$ }& t6 m- j2 O3 a
  1. #include <INTRINS.H>& X: i9 O0 ]5 d1 ^& C/ |  u9 o
  2. #include "STC15W.h"
    , Q  \( r$ ~. h

  3. ! S( f( T- y$ T5 j6 Q% w0 Q4 {

  4. / r  ]2 Z1 S: x) m8 g
  5. /*
    8 @$ p+ J& P% M8 _
  6. ' s4 W! e5 C% n! v
  7. *---------------------------*- ?' h) b5 h$ L
  8. |1 (GPIO2)         \__/  (GPIO1)16|
    / i/ f6 G- J# d; H2 E8 v' S$ T# Y
  9. |                                                        |
    # b* Y3 b/ s# R% r8 e; u7 t
  10. |2 (GPIO3)                   (GPIO0)15|
    / I: Y7 \! C! B+ ^
  11. |                                                        |* Z& e$ a! P' H2 x- M- L
  12. |3 (GPIO4)                                  14|
    + G( r4 S3 i! m5 ~  X! H
  13. |                                                        |
    5 Z+ E, O) b, R: f* \: E# b
  14. |4 (GPIO5)                        (DATA)13|! T( E# p1 r6 l
  15. |                  STC15W204S                |2 r; S1 e' ?3 X: p
  16. |5 (GPIO6)                   (LATCH)12|. g7 I: H. ?  p- S0 b2 t: G6 O
  17. |                                                        |
    1 p+ {7 F$ m% Y5 @8 N
  18. |6 (VCC)                         (CLK)11|
    + B! P5 P8 D! Y0 o/ X! e# Q
  19. |                                                          |
    : M3 p  L' d# F, X
  20. |7 (GPIO7)                         (TXD)10|% D# Q) i: N1 n2 g3 J4 r$ r
  21. |                                                        |
    + `: D$ E/ _8 d0 _
  22. |8 (GND)                         (RXD) 9|
    ( }. H2 M/ B# u5 f
  23. *---------------------------*% c% @( C+ U8 Y4 I% w* B0 P2 h9 k0 w
  24. Fosc = 12MHz
    $ V& G' k3 V. S0 C
  25. 1 {% e* U2 Z2 e4 u
  26. P1.0 -> 上+ q0 w' E- K! {
  27. P1.1 -> 左% h, r2 K& V/ S. V/ m
  28. P1.2 -> 下
    " \. g3 q2 k# X
  29. P1.3 -> 右
    ! V8 @8 b. O+ E+ l) U7 T! K
  30. P1.4 -> SEL
    # [* W7 C3 |. O- S
  31. P1.5 -> STA& `5 f" E8 S+ u( j% N' B* R
  32. P5.4 -> B, ]4 u* W( {2 |) R6 q% h0 l
  33. P5.5 -> A4 O9 V9 w; i" a5 y
  34. % x' b# p+ n$ c+ w8 q. j
  35. */
    " T* c+ o1 A" k+ `, B$ V

  36. ( @7 a  a( U8 T9 a- y: ~! ^
  37. + j" ?. a! P  h1 Q& q
  38. sbit CLK        = P3^2;
    + a3 J8 D# d& t% J
  39. sbit LATCH        = P3^3;
    ) i  i" Q7 M$ V! k, O% P0 ]; W
  40. sbit DATA        = P3^6;
    ) V% B8 r! r5 E# E
  41. " b# \/ W' N4 w
  42. bit isReady = 0;5 W8 B9 M6 ]! @& G
  43. static unsigned char key = 0;9 q) s8 b# L, @  a. n$ U4 b
  44. static unsigned char buf = 0;        // 双缓冲。这个缓冲区保存从P1和P5组合而来的键值
    3 F5 ]. ~' [& J2 f
  45. static unsigned char bufReady = 0;        // 双缓冲。这个缓冲区保存上面那个缓冲区的备份
    8 y) C* @& ?$ C# i
  46. static const unsigned char data mask[] = {0x80, 0x40, 0x10, 0x20, 0x01, 0x04, 0x02, 0x08};        // A B SELECT START UP DOWN LEFT RIGHT。为提升速度,这个表放到RAM中& H+ t7 B' G) Y- @4 M* {6 q/ o8 A
  47. static unsigned char idx = 0;. N1 b# R3 h; {4 @! [2 d) [) ?
  48. - Y" c' e2 m" o6 Q$ I8 v! L& w

  49. ; \- H1 _: B3 j+ _( e7 g5 e7 A
  50. static void GPIO_Init(){* P2 L' {0 L2 ^/ d' b, b4 K
  51.         // P1口和P5口用于接收并行信号,全部初始化为准双向,依靠内部弱上拉输出高电平7 z1 G/ ]6 T9 E; y
  52.         P1M0 = 0;. E7 q& b0 [! ^8 l, |8 ~$ y- `
  53.         P1M1 = 0;
    " l  f1 l2 h! K7 K9 b* C
  54.         P1= 0xFF;' E# ^, e, J. O3 x( b
  55.         P5M0 = 0;
    8 G3 X6 r2 p5 D. j) D7 r% E* T
  56.         P5M1 = 0;" \) b/ Z. D! Z6 o' q5 G
  57.         P5= 0xFF;
      }: v  t; [9 o6 R; N
  58.         // P3口初始化为准双向4 g# m' _0 G4 _* H0 |( m
  59.         P3M0 = 0;- e6 E% e- }3 b. Z! T5 c
  60.         P3M1 = 0;
    # {/ w3 H1 B% C6 Z( p
  61.         P3 = 0xFF;! O$ s0 h5 v% h4 Z
  62. }5 }2 M* N1 L4 T$ a3 D6 S8 s
  63. # N$ q2 n  j5 t; G6 B$ f7 @( ?4 p$ f: |
  64. static void Interrupt_Init(){7 T5 _9 O, Y& f! ~1 J
  65.         // INT0中断(CLK)触发类型为上升沿+下降沿
    2 ?3 n3 C2 p1 s
  66.         IT0 = 0;
    5 ^1 {. |( c4 d" P3 ~( S' u
  67.         // 允许INT0中断2 j0 ?+ V, c2 \& R1 p/ {) P
  68.         EX0 = 1;
    5 f/ y$ O! v& H8 V( s7 O
  69.         // INT1中断(LATCH)触发类型为上升沿+下降沿
    + S& W$ J) O3 h/ D- ^! b# Y- w
  70.         IT1 = 0;" F; r: d- g6 i1 s
  71.         // 允许INT1中断' f+ O; O3 R# w' P! N
  72.         EX1 = 1;: U2 R8 j9 O' J# _" [
  73.         // 开启全局中断* d6 L% E3 H8 R# R; u, t
  74.         EA = 1;+ C5 S* \5 Q: n2 h6 v+ n) m" |
  75. }
    5 K) U* t# w* W. N, q  x
  76. : L, h4 w6 {+ n% O/ _: |/ y8 L6 `6 [
  77. static void INT0_Isr() interrupt 0{
    / {. ^5 y5 y& P9 `5 y8 S
  78.         // 只有已经成功锁存才允许CLK移位
    ' ^& u- u& `. t, l: ^
  79.         if(isReady == 0): u, w9 Q0 f; p- [  A; ]
  80.                 return;9 ^. B: H- R5 u/ e/ b4 D
  81.         // 读当前引脚电平,如果是低电平则说明是下降沿,此时直接忽略该中断8 s8 `. W. ^% i1 l( P  e
  82.         if(CLK == 0)3 c0 h8 H6 ]( G1 e5 w
  83.                 return;% Q& Q( U, C" j9 g  u" G4 U
  84.         // CLK上升沿到来的时候,取锁存值的下一位输出, K- r3 R% w/ A2 k( e5 b9 s  l7 P- B, Y& {3 \
  85.         idx++;
    9 e, ?3 r5 s' R( x
  86.         DATA = key & mask[idx];5 N2 H: X3 x1 ~/ i) U
  87.         // 如果已经完成7次移位,则一轮读取完成
      C3 |4 @( {. Y7 g" ]- \& w% K/ p
  88.         if(idx >= 7)# s* M$ a% I' X
  89.                 isReady = 0;3 q/ z2 \2 g- V" l) a2 p
  90. }) ~" ^4 q. X0 k0 L! f* b; g

  91. * w  x1 Q0 f- T* A
  92. static void INT1_Isr() interrupt 2{: _0 Q1 f6 ]2 U1 {) Z8 s2 C& X% n
  93.         // 读当前引脚电平,如果是低电平则说明是下降沿,此时直接忽略该中断* ~( J+ ~. i' B3 I1 ^  r& Q9 M4 S% n
  94.         if(LATCH == 0)
      W8 \$ K- ^; m: H7 R
  95.                 return;! k1 |4 d$ v: e- x) [0 j
  96.         // 当LATCH上升沿到来的时候,锁存所有按键状态,同时把键值A输出到DATA
    9 ^. i( r9 Z) e; ]- e+ u" M
  97.         key = bufReady;
    1 O1 S% ~- F8 y" @9 ~' V
  98.         DATA = key & 0x80;//mask[0];        // 为了加速运算,直接取表中的值而不是读表
    $ `' V3 }: e: F
  99.         idx = 0;& X3 }( C8 X% K
  100.         // 允许CLK进行移位
    + d5 A' |+ U0 C
  101.         isReady = 1;$ K. J" \& Q% _( u8 @, l  ~* z' t
  102. }$ K: T1 s, b/ N9 ?! s
  103. 9 ~" J4 V; z  c2 G) ^( R
  104. void main(){
      y3 b' Q) }. Q+ Z- `
  105.         GPIO_Init();
    6 s$ [. a, k. k
  106.         Interrupt_Init();/ X2 i. l1 p2 D6 ?6 m
  107.         & |! l# C4 n7 E  D: D( x
  108.         while(1){$ h0 H' L' `$ P( _
  109.                 //PCON |= 0x01;        // 进入省电模式  I6 S! I1 i4 ]3 v* U
  110.                 //_nop_();$ `1 S# {. m7 [, G9 P  O
  111.                 //_nop_();
    ' W- U7 Z# z, @0 r1 ]! |2 {$ I* J
  112.                 //_nop_();9 l+ j" g: D& r
  113.                 //_nop_();$ s& b) ]+ a! X  e- i- O
  114.                 buf = ~((P1 & 0x3F) | ((P5 << 2) & 0xC0));( L  X. Y7 f/ F2 C0 _0 X5 E9 A
  115.                 bufReady = buf;" J4 X/ i4 g- k, I8 a
  116.         }: P0 ~) s) z) y& x
  117. }
    - x- I  n2 B% R! g% h
复制代码
- [+ C3 v3 x  {. e: e# b5 {- M
硬件参数配置无特殊要求,晶振频率选择12M即可。
. w1 Y7 r) Y5 {. E$ K* s( p% J$ i
; a! T3 g% Y# A8 W$ Y这是编译好的固件。

本帖子中包含更多资源

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

×

评分

参与人数 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
& ^/ h& C; G& s8 ^' v+ A( t不错的设计,想问一下楼主,FC的15针公头怎么解决?普通的公头太短了,插不进去FC的扩展接口。 ...
& G% r1 ~3 o& G# {4 o
坛友的改造方案
回复

使用道具 举报

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

使用道具 举报

发表于 2019-5-25 12:07:18 | 显示全部楼层
精彩,楼主动手强,也写得很详细。/ n! A" h* \# l  T/ J3 \0 r& {8 y6 X
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# t/ h) `( S- n5 N
精彩,楼主动手强,也写得很详细。
1 V7 B' f' W" A' ]' z2.4G方案是目前无线的最低延迟吗?

( H0 N9 }1 C* p( j. M" P* y我没用过其他无线手柄,所以实在不知道我自己做的这个手柄到底是不是最低延迟。$ w0 Y8 I# u( N1 f9 V" ~, `) |* a/ T
不过根据网上的说法,延迟高低主要是由通信协议的复杂程度,以及数据传输速率决定的。这个模块虽然是2.4G无线模块,但由于协议很简单,所以延迟比较低。6 A* H7 ]/ U, v! D, \
我用这个手柄玩一些ACT游戏,比如超级马里奥、忍者龙剑传、热血系列,完全感觉不到延迟,和游戏机自带的手柄没有任何区别。唯一的区别就是这个手柄是用火花山寨手柄改造的,外壳是垃圾回收塑料,粗糙+脆弱,导电橡胶弹性不佳,手感不是一般的差。
  A6 Y1 I  N) D; C我手里还有十几张板子,等我有空了我再做一套,到时候买一个好一点的手柄改造。
回复

使用道具 举报

 楼主| 发表于 2019-5-29 16:56:14 | 显示全部楼层
ppad 发表于 2019-5-28 17:27
* F9 ^$ E, @" }$ s- G( e给技术帝赞一个,有半成品发布吗,自己焊接改造就可以,编程实在不会啊 ...
& D/ s1 t! l/ G5 h% O
很可惜,我手里没有多余的单片机了,LDO也找不到了,锂电池以及充电模块更是没有了。反正就是该用到的元件基本都没了,所以没法发布半成品。8 J4 D" ]8 ^/ g( ~  F
两个板子倒是有十几张剩余。& R' m. g6 M. l- G, H% ]2 g8 N
你要是有USB转TTL串口板,完全可以自己买这两种单片机,然后我给你编译好的固件,你自己用串口板下载到单片机里面就行了。两个2.4G无线模块也得通过串口板用AT命令设置参数,不过好在我在设计电路的时候就已经预留好了串口,可以直接在线下载和在线设置参数。总的来说并不麻烦。
回复

使用道具 举报

 楼主| 发表于 2019-5-29 17:00:34 | 显示全部楼层
孙大师 发表于 2019-5-28 18:55
' j& i& J+ Q/ L* R3 k& |7 L非常好,楼主是技术帝,到目前我都还没开发fc的无线套件,等空了,开发一套套件,等玩家自己组装。 ...

1 O. ~# j# b- I9 E+ ?能得到孙大师的赞誉,不胜荣幸!$ ]; N/ S6 X! ^/ N
不如开发一个多功能手柄,比如用SFC手柄改造,L/R键配合其他组合键可以用来切换2P~4P、调节连发速度、软重启等各种功能。接收端插到15PIN扩展口。
回复

使用道具 举报

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

本版积分规则

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

GMT+8, 2026-6-21 13:20 , Processed in 0.106676 second(s), 15 queries .

Powered by Discuz! X3.5

© 2001-2025 Discuz! Team.

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