找回密码
 注册

QQ登录

只需一步,快速开始

查看: 25494|回复: 32

自制FC无线手柄

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

& K! N8 w4 U! L+ R7 r$ R( \% W1 w0 v

9 g* j, O, V2 A4 N0 F最后把按键、导电橡胶和电路板装上去。0 _# ~, }3 ~- M* F3 v4 o* r
精心裁剪了电路板,正好扣上,不会阻碍其他元件,也不会影响后盖和拧螺丝。
$ l: T' L1 A6 X, ^& I
- l' Q& {0 Q" O' I- p8 Z  ^7 Q# y! ?/ W+ A. O! T
完工!& j- T4 n9 H1 L3 V& c. F

1 Y4 s" P$ |5 E* d3 j. `8 w& Q4 v
这是充电的MicroUSB插座。旁边的小孔用于透出低压报警LED的光线。
' z1 h, l. q( T- H6 M* b
7 f$ K- m: ~& d2 Y4 J3 l
: `* K2 d" N4 K; w接收端用一片DIP16封装的STC单片机模拟CD4021。为啥要用单片机模拟而不是直接用CD4021?因为jdy-40模块接收端在有按键按下的时候输出高电平,无按键按下输出低电平,和普通手柄正好相反。当然我也可以用两片74HC00或者74HC04之类的逻辑门进行反相,但那就增加了芯片的数量。对于FC手柄这种工作频率并不高的设备来说,STC单片机完全可以胜任模拟工作。2 N0 v+ @6 g) ^  j- D

5 ^! B* \" O+ f% x. f
+ b1 D7 K6 w: Q' ]6 `1 u6 _7 W4 m2 o
# T+ ]# ?" w4 |2 M1 M  J" l. b0 @0 ^电路设计有点小小的错误,所以有几根飞线。原本设计使用低压差LDO是XC6206,结果在做这个接收模块的时候,买的LDO居然找不到了!无奈只好用了AMS1117。幸好对于接收模块来说是5V降到3.3V,1117可以胜任。要是发射端手柄的话,3.7V降到3.3V,那就非得用6206不可了。( z+ M$ H5 z7 p, V* C8 ~. J

$ j7 k5 Q; s# T7 j5 }0 z: }  q8 G4 F实测十分灵敏,延迟极小几乎感觉不出来。可惜这山寨手柄的手感并不佳,尤其是方向键,软塌塌的。看来我得买个剪线手柄改装。. l7 ^2 \8 S) f" U0 S) T3 K) D" [

: X  u: |7 @$ K  x( E- {/ p这是电路图,有兴趣的朋友可以参考。
# R" t; V6 h* V) p7 ^% N! z8 X7 {) U! G/ V' v# S4 d

5 p. [4 i  F, e) H# a我信奉开源主义,十分痛恨把技术藏着掖着。好东西大家分享嘛!所以两个单片机的源代码大公开!
( _% o; L  [7 b! l, F+ p1 R: N编译器:Keil 51。
3 _; x6 Y3 S/ ~; V) }# G# a6 L3 W/ X
发射端:
  i4 @' A: k# m7 u2 k
  1. #include <INTRINS.H>
    0 h* g5 g* |+ r" B* W% u2 F
  2. #include "STC15W.h"
    % j; g) e" d9 I; @: f/ h) w+ X. V

  3. 5 x3 f) l1 U4 Y9 P
  4. 3 C+ H7 u) s# O9 Z, }1 q3 L
  5. /*
    # a2 e/ A% H5 [* Q( H
  6. --------------------------
    4 g8 E2 E. Z' v
  7. |1 (OUT)        \__/   (INT1) 8|) ]/ M5 _: t% G4 Q
  8. |                                                   |
    4 O' g9 j3 {! ^$ W* v
  9. |2 (VCC)                   (INT0) 7|
    - Y. V3 X+ [/ D6 g5 x- A% @+ A) ~
  10. |                 STC15W204S                   |; \5 K6 s& }* N/ F8 r4 L! K! H
  11. |3 (LED)                         (TXD) 6|
    * z( g% w, F& Q! \" W% U) V
  12. |                                                   |+ T& j+ j: ~% g( P* Z5 l' T) [
  13. |4 (GND)                         (RXD) 5|0 r( i, ]8 r8 ~: m6 b
  14. --------------------------
    , c% i1 J7 P5 L3 Y  U) X) M" ^

  15. + o; |% C7 G# r
  16. LED ---|<|---[===]--- VCC6 i( r; {; c6 j) F! t. v$ e
  17.            Red          330
    + n# `; c/ X; {

  18. 1 y% x8 N! b" `
  19. Fosc = 6MHz) _' e; t) [* @" n" F) ?0 K
  20. */
    / X2 p# @. W  F, m4 a1 q
  21. / z& f. i! ]3 A" K' p% j6 v1 _
  22. 3 k% r% H- J5 l7 T
  23. // 矩形波输出脚4 s* {! q! U' C1 G; S/ M! c
  24. sbit OUT = P5^4;& I/ T: a' w' z
  25. // 低压指示灯引脚1 D$ ^, y1 n1 A% L
  26. sbit LED = P5^5;! ^1 i) J; ^$ Z& h: k. Y( H* }) w

  27. 8 f7 ]* @. b% s( Z6 c
  28. // 停机标志位% R  k. |' U7 ~8 ~. y- J) P
  29. bit isReadyToHalt = 0;
    - Q4 Z2 S: T/ g& d2 p! l+ P: s' |3 u9 {
  30. , V+ f$ n3 L/ f9 c. L, u5 b5 f
  31. // 矩形波次数累计0 t/ H& t4 c; t- t$ z" V  R
  32. static volatile unsigned char count = 0;
    , v% n% u8 V& ?% ~2 O) ^# \
  33. ) E- Q7 m6 {# i; G# {8 I* l
  34. $ D5 k: G: L) Y/ x: @( e5 q, V0 E5 Y, m
  35. static void GPIO_Init(){
    8 @% {. }6 A2 h9 l" P& e
  36.         // P3口设置为准双向,默认靠内部弱上拉输出高电平
    9 ~$ L1 T! j' L. c
  37.         P3M0 = 0;9 z* V$ c7 [7 A7 Z1 m  s
  38.         P3M1 = 0;
      h4 L$ [6 M" ?/ Y+ W
  39.         P3 = 0xFF;- ], S% X+ T1 O# m: C
  40.         // P5口设置为准双向,默认靠内部弱上拉输出高电平; t# t3 S) I8 r  p& X
  41.         P5M0 = 0;
    5 Z0 |/ J$ B" F' r/ l0 y  b. y
  42.         P5M1 = 0;
    $ j& T6 f- a/ j- v" J/ _
  43.         P5 = 0xFF;; f  s( ]# Z6 T4 j: V) d7 N9 {
  44. }( D& W* f7 }' h! O" N; l6 x
  45. + m0 H! x/ N0 `% B1 ^% G! Y
  46. static void Timer0_Init(){
    + p. }8 w- Q& `+ H
  47.         // 16毫秒@6.000MHz8 @3 ~, y0 A" b& u$ y+ Q
  48.         AUXR &= 0x7F;        // 定时器时钟12T模式
    7 E. n" |6 p1 j. S$ X6 O
  49.         TMOD &= 0xF0;        // 设置定时器模式
    4 i1 u* t+ p3 Z6 q5 B
  50.         TL0 = 0xC0;                // 设置定时初值
    " ]) F4 Y) P  B. l
  51.         TH0 = 0xE0;                // 设置定时初值0 Y! {' i) G8 o- e
  52.         TF0 = 0;                // 清除TF0标志) Q3 V& W0 o2 R% H
  53.         TR0 = 1;                // 定时器0开始计时) O2 I$ _( t) T2 m
  54. }; O# K% j* _/ i

  55. 5 w. K; f; w7 B9 [
  56. static void Interrupt_Init(){
    - k4 }9 h- @3 Y( _
  57.         // INT0中断触发类型为下降沿触发
    ; S. s* C: L  ]
  58.         IT0 = 1;, ?1 m" d7 ^1 Q4 c9 e
  59.         // 允许INT0中断
    ) O; ?3 s' q; e0 t3 f; p
  60.         EX0 = 1;8 y: I; v! c/ ^# W+ R" F
  61.         // INT1中断触发类型为下降沿触发
    : k) E# H7 @4 M8 @% v
  62.         IT1 = 1;- i: _6 ~# [; y% O9 F7 C# k: K
  63.         // 允许INT1中断
      p3 j7 _3 R$ z; @% p! c7 E- a" Q) K
  64.         EX1 = 1;- `9 F7 [# P9 |
  65.         // 允许定时器0中断
    , C& T5 P' H/ T+ o% ~
  66.         ET0 = 1;
    / V) J# U) J* }
  67.         // 允许全局中断
    ; ~' V+ |( B8 L- Q0 ?2 ]
  68.         EA = 1;
    # X, ^# ]- j2 g) f: ^( @+ _: B: _
  69. }- w. n/ C# r) x. Q& ^

  70. $ P$ {7 N: z% c+ G* R2 f- s4 x7 }* L% M
  71. static void INT0_Isr() interrupt 0{
    ( J1 O, m/ q3 V
  72.         // 矩形波次数累计归零
    ) b9 F5 K( @+ G& w
  73.         count = 0;
    3 n# g% }. P* r
  74.         // 重开定时器0中断
    # q6 D9 Y! Y) C9 ~
  75.         ET0 = 1;
    ) I; R% M8 s1 q8 h& M
  76. }
    . i+ b$ I! W0 [# h5 {! [

  77. ) i# K+ n! h" w$ L7 y- a
  78. static void Timer0_Isr() interrupt 1{6 `8 }# l( N: u4 |3 Z0 N1 S% M
  79.         // 输出矩形波$ S) q3 L" v2 }4 {4 u! Y
  80.         OUT = ~OUT;
    % d% U: ~6 o: K, e2 J5 t& q" O
  81.         // 累计矩形波次数
    , b3 L& G% z2 ?( y) P6 A8 j
  82.         count++;$ X) H& e% H- w
  83.         // 超过250个矩形波,准备停机
    0 k) F# J" ]* R) q
  84.         if(count > 250){
    & |( a. |0 [- D
  85.                 count = 0;
    4 r0 q9 l( ~  @# W* Y  d% v: ?
  86.                 isReadyToHalt = 1;
    / B9 q, q( Y" H- r
  87.         }5 r6 ~1 ~, O/ V& x0 J$ I+ W
  88. }: ]: a: Y3 Y. r; v+ o
  89. : S3 e+ I6 H+ S. M: l
  90. static void INT1_Isr() interrupt 2{
    - J8 c0 k% c# S2 Y9 S) u  c
  91.         // 矩形波次数累计归零1 l' z8 o; y% R& I8 v7 f
  92.         count = 0;
    2 q# A2 T- |# |, \2 A4 t5 V
  93.         // 重开定时器0中断8 N# w- q5 g& J; ?' T; K
  94.         ET0 = 1;
    ; I8 k4 z$ t) Q: v
  95. }; E5 D! f. ?# b$ H8 z8 _* v

  96.   ^+ F9 r7 x5 [/ }0 M

  97. 8 a! J; g6 x9 K3 e9 a
  98. void main(){
    ! N- V* V9 {+ D. M4 q! G2 u
  99.         // 初始化P3和P5口
    1 r6 u# j2 N& P% A& |3 @( ~( I
  100.         GPIO_Init();
    / p/ h0 J8 n7 Q
  101.         // 初始化定时器0% o1 Y/ k; X+ I7 C
  102.         Timer0_Init();
    # X  m1 a( j* k0 h" n# j; T5 b
  103.         // 初始化中断' u& d. r3 [( x# t  R7 N
  104.         Interrupt_Init();
    8 D; V4 z. J7 F) s8 u7 q# N
  105.         ; B) z# a2 @$ y% n
  106.         while(1){6 a  z6 A$ ]  d
  107.                 // 检测电量
    # s9 |9 t5 }4 I2 c0 [/ Q
  108.                 if(PCON & (1 << 5)){0 H$ V! D) x$ ]0 N
  109.                         // 如果电量低,低压指示灯亮
    ' U5 d' r' @! {8 P
  110.                         LED = 0;
    0 P+ J, ~/ \7 `8 z9 x; [' T, P
  111.                         // 清电量检测硬件标志位$ y5 S6 C* p% \5 P. G
  112.                         PCON &= ~(1 << 5);( m+ x, s# V$ R6 X4 w, J/ r9 i2 z
  113.                 }else{2 S& N' c7 \# a* a0 a7 }
  114.                         // 电量正常,低压指示灯灭, y2 v: x) X0 ]4 r$ C
  115.                         LED = 1;" o# N' g, I. G9 o% _) h, ~
  116.                 }  h3 e" o9 S) \2 S! G6 n

  117. . G9 i  N6 [6 i
  118.                 // 检测到停机标志' K0 R$ H# ^6 U# C5 @
  119.                 if(isReadyToHalt == 1){
      a: E: y* }( j' _) D
  120.                         // 暂时关闭定时器0中断+ ?; j+ z  E4 w3 t$ w! g
  121.                         ET0 = 0;1 R* `+ J8 `7 O# r
  122.                         // 停机之前先把矩形波输出脚置低电平,以方便INT0和INT1唤醒CPU
    ; @% k/ O" c0 b0 c5 q# F6 o( F
  123.                         OUT = 0;- z$ E- U) f9 [% ?5 _* L. |. x
  124.                         // 停机之前先把低压指示灯灭掉,以省电: |' k$ y- K1 u7 R( y# p
  125.                         LED = 1;
      X/ x1 w* m* y$ o# X, w
  126.                         // 进入停机模式
    : Y1 s- K: I8 l1 @8 l1 [/ Z  e
  127.                         PCON |= 0x02;
    - Q" K  `0 R/ D. C5 n1 R9 |& ^- m
  128.                         _nop_();# [6 _% {$ M/ ^+ W9 ^$ `
  129.                         _nop_();' |8 j/ C' w/ v
  130.                         _nop_();$ D6 }7 J0 r2 b% }. k( C- c
  131.                         _nop_();
    7 ?8 ^9 p$ ]7 k4 F7 q% N0 Q  _
  132.                         // 唤醒,清标志位
    . ?+ |* @  f2 f, Z7 x4 ]& T& n
  133.                         isReadyToHalt = 0;
    ( d. X6 A- G' h) Y
  134.                         // 重开定时器0中断
    ! ]: C6 i% C7 e; B8 T2 @$ A
  135.                         ET0 = 1;1 d5 }" c0 m" W0 z1 @
  136.                 }( k! N* W1 v7 L. H/ v; V& ]
  137.         }  z: p) T" N8 P$ z: R
  138. }
    5 X3 x8 b" a% [) ?! C
复制代码

9 T4 F% C* ?6 H) a) M1 ?" b硬件参数配置:" e! v9 p2 J- C$ {1 s, b2 k* q

2 ]4 |, e7 `  P/ g2 d, ^% H& ^7 f+ {4 j& \$ a4 l% v+ P
接收端:4 z. J2 k% k/ F8 k1 a/ c6 N4 }
  1. #include <INTRINS.H>
    / _+ \# j$ u$ B% q; o5 L
  2. #include "STC15W.h"1 \" M' @: ^2 C# C. _
  3. # U/ P& y$ D' m' _

  4. ' k. ]& c, ?3 I2 P, `, e
  5. /*
    ) }# h/ Q& D/ w. l
  6. + g9 O6 g* [  M0 e' C* Q  x, y
  7. *---------------------------*! g8 {, g  v- h+ ]' O" r( `) j( F
  8. |1 (GPIO2)         \__/  (GPIO1)16|( N0 Q7 Q! c3 k$ f3 x# h
  9. |                                                        |! X9 Y+ h6 _* ]0 N
  10. |2 (GPIO3)                   (GPIO0)15|+ E9 L5 w& P8 L3 H$ c7 z$ `0 E' h
  11. |                                                        |# d3 C+ t. N* g# `6 l
  12. |3 (GPIO4)                                  14|7 b9 n3 x3 a3 d& }0 l" o
  13. |                                                        |
    : S1 D. Y! A' `) g  G! D0 J' g, Y* @
  14. |4 (GPIO5)                        (DATA)13|' @, q; l! K: w  M1 k0 G' O
  15. |                  STC15W204S                |
    + T$ U. X& g3 Z" N$ U/ |+ w! w
  16. |5 (GPIO6)                   (LATCH)12|
    $ `" a+ ~( Y) G) k- {$ B
  17. |                                                        |
    4 N! ]7 X( `3 ?2 ]# e5 V+ ~5 W$ C% i
  18. |6 (VCC)                         (CLK)11|
    + R! K- c5 W1 F
  19. |                                                          |  R2 k; e3 }2 a1 L
  20. |7 (GPIO7)                         (TXD)10|
    0 d& p5 d' A* N5 ^5 m9 X9 i- |
  21. |                                                        |
    ( H  n3 A/ m% |/ g* X( b, k: t
  22. |8 (GND)                         (RXD) 9|
    % H7 v( k1 t0 E/ L! w& T7 k; Q
  23. *---------------------------*
    + u$ J8 B- }; E
  24. Fosc = 12MHz
    5 d2 Q, Q1 Q: d" h
  25. ( k6 e4 b% e7 O: \( ?5 B0 O. r
  26. P1.0 -> 上
    % G& U; h7 y* S# B: J
  27. P1.1 -> 左9 }/ @' |: s  V0 M* D& `
  28. P1.2 -> 下
    , c! h! G- z# I* K
  29. P1.3 -> 右: Y6 W4 S/ f& ?$ j+ w8 W" v7 b; N
  30. P1.4 -> SEL& n% R& P# C/ W
  31. P1.5 -> STA
    $ o1 ^$ ~! E' v& w
  32. P5.4 -> B$ h9 W. z; E' j
  33. P5.5 -> A& Y( J4 X2 c+ ^* A0 v

  34. : M) t1 i* {1 R' j- _
  35. */+ W- I% l1 P6 Z6 Q" W+ H! H

  36. 2 k( {- }+ f9 H( \

  37. 2 ~$ A& B8 o+ l' Y- D, {
  38. sbit CLK        = P3^2;
    6 w, P- |& e2 V  U, O
  39. sbit LATCH        = P3^3;1 Y! J* e3 ?3 O8 c) B
  40. sbit DATA        = P3^6;
      T/ A( d& W/ T, E2 k

  41. ) f! Q8 u& u* T) K2 J( J; k3 W  N8 s
  42. bit isReady = 0;
    1 ]" K! `& P# H) m7 N: e) c3 ~# j" Y
  43. static unsigned char key = 0;$ A' }1 m, ^& y# a  B
  44. static unsigned char buf = 0;        // 双缓冲。这个缓冲区保存从P1和P5组合而来的键值0 m( ^  X0 N; M* b- V
  45. static unsigned char bufReady = 0;        // 双缓冲。这个缓冲区保存上面那个缓冲区的备份1 w9 d6 y& Q; ?) f) T" 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中
    7 G! L; x& G1 d) p; N  v' o$ l
  47. static unsigned char idx = 0;4 E( T9 ?6 B4 L4 J

  48. & C, Y% h1 g3 y# k- b$ E- {" Y6 Y

  49. : n; Y0 l5 R+ O* e7 C" c' o9 D0 o/ w
  50. static void GPIO_Init(){
    # i% _' j7 v7 m5 T2 U6 h+ T
  51.         // P1口和P5口用于接收并行信号,全部初始化为准双向,依靠内部弱上拉输出高电平
    7 T4 j% y! M6 P( g1 m! r$ e7 u
  52.         P1M0 = 0;2 C1 t8 l* n2 J, f, n0 c" Q' X
  53.         P1M1 = 0;$ D- {$ @2 F% K7 ~: O- B: I
  54.         P1= 0xFF;6 K  ~6 w! E7 C8 S2 ]+ v6 u
  55.         P5M0 = 0;  N1 p8 k6 S- C& q
  56.         P5M1 = 0;- R. ]" J: D7 I6 i
  57.         P5= 0xFF;  X2 C" R: }7 }# h# f% h
  58.         // P3口初始化为准双向7 r- R. M. q3 W% o$ _. e# F
  59.         P3M0 = 0;' w, u! j6 H! a% b4 Y) Y* u
  60.         P3M1 = 0;
    . t! I+ J% h) h' u
  61.         P3 = 0xFF;
    ; g, l; O' b# N$ y: \. S
  62. }1 ^" c; D! k7 d: C. `. ?. P

  63. 5 J0 k6 A8 Y5 p- G" t0 i' l0 Q
  64. static void Interrupt_Init(){
    1 F) M( i) Q( w& r% n+ U" R
  65.         // INT0中断(CLK)触发类型为上升沿+下降沿9 m9 ]4 S: o$ [2 S, ?
  66.         IT0 = 0;/ K  o" e, D: W3 A: O7 ~
  67.         // 允许INT0中断9 j$ |- D% A/ H- N8 b$ R8 N
  68.         EX0 = 1;
    0 y4 ~) g( b: ~" M
  69.         // INT1中断(LATCH)触发类型为上升沿+下降沿/ T3 a' S% X- @  E- h" b2 z+ I5 x7 u1 m
  70.         IT1 = 0;- N0 \% j4 g4 l3 X* u- q* O+ U
  71.         // 允许INT1中断
    " w' }, X6 ~/ ]
  72.         EX1 = 1;
    - e3 c  Y/ G0 N* o/ T% ]
  73.         // 开启全局中断0 y5 L2 e( d3 V4 Z# c( E, x
  74.         EA = 1;
    , U: m; H* e# R; k6 G3 P$ S
  75. }
    " j! i8 k3 A; ?  w6 `7 ?/ ^
  76. & j8 |6 G: w, E$ p6 b5 U: a* E
  77. static void INT0_Isr() interrupt 0{& n6 m) _: I# P* I  \4 E
  78.         // 只有已经成功锁存才允许CLK移位
    . t8 o% \- O7 Y% F
  79.         if(isReady == 0)
    , x0 ^1 Z/ x& N) Z0 G8 X: k# F" T
  80.                 return;
    / K3 S  F: `+ P9 h1 p. f
  81.         // 读当前引脚电平,如果是低电平则说明是下降沿,此时直接忽略该中断
    / c: |6 V. F, ?, L8 }8 a' A
  82.         if(CLK == 0)
    . ~% L) b4 o& p$ G9 r# L
  83.                 return;4 f3 s: E( ~& N& Z+ T+ O' ~
  84.         // CLK上升沿到来的时候,取锁存值的下一位输出
    . e0 Z1 S7 C( ]
  85.         idx++;5 d; t: o: p* _/ ^+ L, S
  86.         DATA = key & mask[idx];
    4 G' m( ^9 e* u4 o
  87.         // 如果已经完成7次移位,则一轮读取完成: h4 Y  j& H6 ?* |
  88.         if(idx >= 7)
    , T% f6 s0 g( [7 t
  89.                 isReady = 0;
    : N" W9 c7 G4 l% S7 E4 U3 F
  90. }
    + }1 T* g; d' \; U0 v. H/ \

  91. $ t0 X/ x5 ^! C8 ?6 u. |
  92. static void INT1_Isr() interrupt 2{3 z- x4 n' X" }8 b  b6 z
  93.         // 读当前引脚电平,如果是低电平则说明是下降沿,此时直接忽略该中断( c6 f7 N& S4 T8 u9 E
  94.         if(LATCH == 0)9 s9 s: Q( G! j/ r
  95.                 return;
    / }  l) H2 P9 C8 r# Z# t& H* |
  96.         // 当LATCH上升沿到来的时候,锁存所有按键状态,同时把键值A输出到DATA
    8 W( i; a1 |- b. v6 O% g
  97.         key = bufReady;
    7 B. d1 p# z8 N/ s$ O5 S
  98.         DATA = key & 0x80;//mask[0];        // 为了加速运算,直接取表中的值而不是读表5 ?5 k( Y5 Y6 w+ R
  99.         idx = 0;! x- w' g! }* t; y: ]1 x/ d
  100.         // 允许CLK进行移位2 a. `+ ^8 ?; n3 Y( ]( ^4 l
  101.         isReady = 1;: O$ M6 h/ p7 L8 B
  102. }$ N2 S. Q$ E+ N3 t3 F
  103. 2 R3 q$ |+ \' d& ?9 a5 e: s1 Q' C
  104. void main(){
    $ l" J% z" K8 ?$ R* k
  105.         GPIO_Init();
    / Y, B1 Q; O# B
  106.         Interrupt_Init();
    - y9 R) ]: l: s
  107.        
    6 V; k* n8 ?+ K) ~8 G
  108.         while(1){+ z* P) u7 j& c% s, a! d
  109.                 //PCON |= 0x01;        // 进入省电模式
    / s( o# c5 D5 z/ l) d" g
  110.                 //_nop_();
      s; M4 K4 y4 V- P1 Y4 C4 ^
  111.                 //_nop_();
    - @. W1 F$ s2 u; T7 o# I
  112.                 //_nop_();
    3 _  N- `9 U1 i
  113.                 //_nop_();+ ?; A/ _1 Y. w! j  ?7 h* t/ t) Z
  114.                 buf = ~((P1 & 0x3F) | ((P5 << 2) & 0xC0));
    ) P' R- g% R+ n& F4 o7 n! y
  115.                 bufReady = buf;
    . H0 ~4 L/ U: _+ i7 ?
  116.         }8 ?; q  m1 K  `5 {  |1 j
  117. }- r. p1 U% @# I. `, y4 ?
复制代码
" d. d. u, f; c% _
硬件参数配置无特殊要求,晶振频率选择12M即可。9 }1 q6 A* B$ Y; o

* J/ g& C2 a& l( b( y; a& Z这是编译好的固件。

本帖子中包含更多资源

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

×

评分

参与人数 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. {: C. O3 p" I
不错的设计,想问一下楼主,FC的15针公头怎么解决?普通的公头太短了,插不进去FC的扩展接口。 ...
- A3 t$ [) L4 f3 G6 Z% H# j3 q
坛友的改造方案
回复

使用道具 举报

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

使用道具 举报

发表于 2019-5-25 12:07:18 | 显示全部楼层
精彩,楼主动手强,也写得很详细。; [0 ?7 R* b; T% Q
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
$ q; Y$ {- F9 H/ P精彩,楼主动手强,也写得很详细。
/ ^$ s9 ?/ T$ r/ Q/ w9 C7 ~" U3 J2.4G方案是目前无线的最低延迟吗?
! ^8 l7 A" F* p) y9 q
我没用过其他无线手柄,所以实在不知道我自己做的这个手柄到底是不是最低延迟。
5 p# Q; Y# A2 r2 J不过根据网上的说法,延迟高低主要是由通信协议的复杂程度,以及数据传输速率决定的。这个模块虽然是2.4G无线模块,但由于协议很简单,所以延迟比较低。& R9 _7 P6 m! z4 M3 D. M( l/ [
我用这个手柄玩一些ACT游戏,比如超级马里奥、忍者龙剑传、热血系列,完全感觉不到延迟,和游戏机自带的手柄没有任何区别。唯一的区别就是这个手柄是用火花山寨手柄改造的,外壳是垃圾回收塑料,粗糙+脆弱,导电橡胶弹性不佳,手感不是一般的差。
9 {% j7 N) h, L% L我手里还有十几张板子,等我有空了我再做一套,到时候买一个好一点的手柄改造。
回复

使用道具 举报

 楼主| 发表于 2019-5-29 16:56:14 | 显示全部楼层
ppad 发表于 2019-5-28 17:27. l  \4 I8 m0 r5 |
给技术帝赞一个,有半成品发布吗,自己焊接改造就可以,编程实在不会啊 ...
0 E5 q, D) e7 j) i
很可惜,我手里没有多余的单片机了,LDO也找不到了,锂电池以及充电模块更是没有了。反正就是该用到的元件基本都没了,所以没法发布半成品。
6 D1 o6 A; X% y两个板子倒是有十几张剩余。. W! _, P6 U5 T; C
你要是有USB转TTL串口板,完全可以自己买这两种单片机,然后我给你编译好的固件,你自己用串口板下载到单片机里面就行了。两个2.4G无线模块也得通过串口板用AT命令设置参数,不过好在我在设计电路的时候就已经预留好了串口,可以直接在线下载和在线设置参数。总的来说并不麻烦。
回复

使用道具 举报

 楼主| 发表于 2019-5-29 17:00:34 | 显示全部楼层
孙大师 发表于 2019-5-28 18:55- P- a6 L- n0 n" i
非常好,楼主是技术帝,到目前我都还没开发fc的无线套件,等空了,开发一套套件,等玩家自己组装。 ...

; {1 H6 Q" z; B4 F" C6 y8 R* t能得到孙大师的赞誉,不胜荣幸!
6 x# O$ k2 b5 Q" S4 i不如开发一个多功能手柄,比如用SFC手柄改造,L/R键配合其他组合键可以用来切换2P~4P、调节连发速度、软重启等各种功能。接收端插到15PIN扩展口。
回复

使用道具 举报

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

本版积分规则

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

GMT+8, 2026-6-21 11:37 , Processed in 0.109183 second(s), 15 queries .

Powered by Discuz! X3.5

© 2001-2025 Discuz! Team.

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