找回密码
 注册

QQ登录

只需一步,快速开始

查看: 26169|回复: 32

自制FC无线手柄

  [复制链接]
发表于 2019-5-22 14:16:45 | 显示全部楼层 |阅读模式
本帖最后由 雷精灵2046 于 2019-6-14 09:28 编辑 * @6 }- W" V! k1 I

% q- k! O! t9 v* ?没有用复杂的分立元件搭建发射接收电路,直接用的现成的2.4G无线模块jdy-40。
3 e' |( j! x5 _, V6 Y0 O! U* j  C" E8 X& w

7 J. [/ Z: Y3 \3 c/ J7 q- i: f6 ^发射端靠3.7V锂电池供电,用了一片SOP8封装的STC单片机,负责产生连发脉冲,同时负责检测电池电量,电压低于3V左右的时候触发低压中断,低压指示LED就会亮起来告知该充电了。平时发射模块和单片机均处于睡眠状态,有按键按下才会唤醒,从而实现省电。实测睡眠状态下整机电流约1~2uA。板子洗了一下稍微干净了一点。因为对于微功耗设备来说,焊接残余的助焊剂可能会增加漏电流。6 x+ ^  R- W' o6 X" l  D1 ^
! o' w6 T- i! _6 X' u4 K
买了一个火花的FC山寨手柄,去掉里面的牛屎板子,并修正一下塑料挡板,把锂电池和充电模块装进去。
' o# F2 x4 g% ~为了减少体积,充电模块裁剪得十分小,并且更换了充电电阻使之适应这个小小的锂电池。这么小容量的电池,也不需要多么大的充电电流是吧?
( F$ \5 Z; _0 M0 s! B  ?然后统统用热熔胶粘上。充电电流比较小,所以发热很少,不会熔化热熔胶。
  f, U. O: C! i% `' x6 p+ E  ?
/ J  S# \7 N+ Y7 F; ?$ R
+ T3 U' c' D+ p6 U: W9 R% F* L! r' x# u& H# N
最后把按键、导电橡胶和电路板装上去。
* t' X& r! i7 N. V1 E精心裁剪了电路板,正好扣上,不会阻碍其他元件,也不会影响后盖和拧螺丝。
) C0 D9 W# {! U4 P8 Y/ \# x4 m' m1 ^  \3 Z+ d# S
" M) ^% s( @1 ]* D4 y/ k: H. U$ w0 ^
完工!
# c6 u7 q, F  r1 j6 d+ {9 c- b7 y* E$ @8 q/ k% C0 v; ~7 ]
3 Q; v% u3 u, a6 P/ N4 W- l- K
这是充电的MicroUSB插座。旁边的小孔用于透出低压报警LED的光线。- ]  ?/ m' n/ ^6 X& S* h( s

0 f7 E$ a7 C& O) z) D: S3 ]8 Q5 o9 t* N6 d  m" N
接收端用一片DIP16封装的STC单片机模拟CD4021。为啥要用单片机模拟而不是直接用CD4021?因为jdy-40模块接收端在有按键按下的时候输出高电平,无按键按下输出低电平,和普通手柄正好相反。当然我也可以用两片74HC00或者74HC04之类的逻辑门进行反相,但那就增加了芯片的数量。对于FC手柄这种工作频率并不高的设备来说,STC单片机完全可以胜任模拟工作。6 u' G4 ]/ [4 ?* V" F& M5 D

: n; ~6 ^9 n$ R/ k2 Z
6 }! h7 N! D  j: q: q$ t
$ f* `' M' J/ q+ |  D8 {3 d- C电路设计有点小小的错误,所以有几根飞线。原本设计使用低压差LDO是XC6206,结果在做这个接收模块的时候,买的LDO居然找不到了!无奈只好用了AMS1117。幸好对于接收模块来说是5V降到3.3V,1117可以胜任。要是发射端手柄的话,3.7V降到3.3V,那就非得用6206不可了。. H9 @9 w7 u0 b7 f

" T% A4 b- a4 O5 e, B$ T1 }实测十分灵敏,延迟极小几乎感觉不出来。可惜这山寨手柄的手感并不佳,尤其是方向键,软塌塌的。看来我得买个剪线手柄改装。% O2 a" V. x2 g6 d2 ^
1 ~7 {0 l2 h1 C+ M
这是电路图,有兴趣的朋友可以参考。* B" Y$ j$ X0 P1 u$ Q' n1 {4 c9 ^

4 K  Y7 u# p/ g. C. B: ]4 e5 O1 Q9 ?* j, X% h' v
我信奉开源主义,十分痛恨把技术藏着掖着。好东西大家分享嘛!所以两个单片机的源代码大公开!
+ _  c( b, k" V2 r, H. R$ Z编译器:Keil 51。9 u0 e- Q# Y" t7 t- m
; Y& b8 |- O: g2 G
发射端:0 ~% g; ~$ b2 {: e% e; E
  1. #include <INTRINS.H>" Z7 j. L& U4 B4 M; X$ J" \
  2. #include "STC15W.h"
    # @4 }, F- c6 U5 Q( [
  3. 8 N2 }# Y! y! j
  4. 0 T0 w8 x5 r4 M! ^! k( }1 w
  5. /*& `8 Q  ^8 ~! `; J
  6. --------------------------, I& D. g% J: L) ^8 L* Z4 R  x
  7. |1 (OUT)        \__/   (INT1) 8|
    : |3 l" }- a' F2 i8 }
  8. |                                                   |- x  ~* w% s1 \! i$ w* ?
  9. |2 (VCC)                   (INT0) 7|
    7 h  v0 `/ s( r6 N6 L. {3 D, A
  10. |                 STC15W204S                   |3 e+ |( ?/ }& n
  11. |3 (LED)                         (TXD) 6|0 x% Q! s4 S3 r4 N6 C& V8 {3 @* A
  12. |                                                   |! `1 n' Y. M) r7 ?" i
  13. |4 (GND)                         (RXD) 5|4 c5 D4 P, l, S% ^) s
  14. --------------------------( V' L- E# I0 g2 `9 }1 C
  15. 2 v3 p0 ~. n- i* Q5 }
  16. LED ---|<|---[===]--- VCC5 J5 x1 w( w" Z
  17.            Red          330
    1 W& t6 |: A4 s

  18. ( A3 q' _+ N8 f
  19. Fosc = 6MHz: Q, C( ~% M$ @0 l, v  p& {
  20. */' k% l. W" n' k* J5 E% w+ m& V

  21. 8 L7 a2 b' J& U& @

  22. . }) s) ]9 j/ u: L) h
  23. // 矩形波输出脚
    + i6 d3 ~+ G. e8 ^% u  s' V+ }
  24. sbit OUT = P5^4;
      C% @+ `$ U- ~% V9 V
  25. // 低压指示灯引脚5 S7 A: `1 I$ p- C" p. ^4 C9 j
  26. sbit LED = P5^5;! t6 R  o0 ~% O& Q" P6 t9 W8 z$ `

  27. - F/ S! E. K0 V5 N
  28. // 停机标志位9 N/ n; C) \- [, T! }* d# d
  29. bit isReadyToHalt = 0;
    ( b  z: I6 [0 z* ^' o% \

  30. 5 H6 `7 D. a4 j3 U: x! K% A! `
  31. // 矩形波次数累计$ V! M: V! L+ f& [; c
  32. static volatile unsigned char count = 0;3 u! Z! C# _- r! u$ O
  33. 7 ~2 q0 i) Q2 a2 g
  34.   h- S' y. c" [6 C
  35. static void GPIO_Init(){
    + K4 l. _' {/ H
  36.         // P3口设置为准双向,默认靠内部弱上拉输出高电平3 T9 u9 m% I* P+ E
  37.         P3M0 = 0;
    8 }) V$ z- A/ {
  38.         P3M1 = 0;% S# |/ `, @/ b2 a
  39.         P3 = 0xFF;
    $ R& _4 |6 l* f, }% C
  40.         // P5口设置为准双向,默认靠内部弱上拉输出高电平0 [0 G5 [4 r% y2 N- C0 l( ^0 {( p
  41.         P5M0 = 0;0 s9 O) J) ~) j1 H3 O+ h, W
  42.         P5M1 = 0;: k3 m% p- k* [2 f6 C+ d
  43.         P5 = 0xFF;
    ' `$ ?, M4 O7 _. q
  44. }
    / o$ A1 }% j# z. ?. y5 S

  45.   i, y, J+ W, c, g* ^
  46. static void Timer0_Init(){
    3 s& s2 O6 y1 O, P- b4 u% \
  47.         // 16毫秒@6.000MHz2 z  h5 U* V' O6 q! e1 ^/ \
  48.         AUXR &= 0x7F;        // 定时器时钟12T模式
    " t" W- ?3 g- H; I9 @& w0 N( i
  49.         TMOD &= 0xF0;        // 设置定时器模式( h; i+ w6 R$ s6 Y7 T. ?; e; s
  50.         TL0 = 0xC0;                // 设置定时初值
      q/ Z& M3 f1 u8 {. k' _
  51.         TH0 = 0xE0;                // 设置定时初值; G* x& _9 M3 {: H( J  k+ ?" W
  52.         TF0 = 0;                // 清除TF0标志( y  ~5 O, _8 J) }6 h
  53.         TR0 = 1;                // 定时器0开始计时2 p; r) E( c8 p  m5 i- [: }; d. y
  54. }
    : a5 l4 k( K' j: ^' F$ L7 U

  55. ! T; K7 s- [; z6 f; s$ j; y& m
  56. static void Interrupt_Init(){: `& F/ X7 S- B; P, T7 Z
  57.         // INT0中断触发类型为下降沿触发$ \, H, E4 L! C' h7 {+ g
  58.         IT0 = 1;
    : `1 F* z. \3 l: V7 u9 C
  59.         // 允许INT0中断8 z* m* |% i- I( ^3 k$ R& g0 p
  60.         EX0 = 1;
    , M, e1 }6 d+ i$ a& G
  61.         // INT1中断触发类型为下降沿触发: \. |- [# f# ]* }. X' s
  62.         IT1 = 1;
    $ a: V9 i5 L$ G8 B4 D' Q
  63.         // 允许INT1中断7 P. s% W) Q' D: H& L/ X8 Y4 K7 r
  64.         EX1 = 1;( Z( U1 @8 T9 h) Y/ U" K/ G
  65.         // 允许定时器0中断
    . |2 d% m) W6 J- n8 |7 F
  66.         ET0 = 1;9 _, i' j9 w/ k" s" P& F4 O7 N
  67.         // 允许全局中断  q; s1 Z) S4 d. X
  68.         EA = 1;
    $ R( z$ W7 \7 o
  69. }6 I. h5 G7 O- r  w& d) l+ W

  70. ! d( c( w! ?; \
  71. static void INT0_Isr() interrupt 0{" D  Z3 d$ c1 F
  72.         // 矩形波次数累计归零
    . {. |7 l3 d' {! R* ~) |
  73.         count = 0;& a1 T* C2 v# r7 A' w6 k, K
  74.         // 重开定时器0中断
    9 Y0 h6 U/ y) F1 z4 \# v
  75.         ET0 = 1;
    ) j9 D/ W' O  j, @( c
  76. }
    : X. a% i1 ~. o" U
  77. 8 d6 W0 \+ |) p4 H2 Y4 K3 _: L
  78. static void Timer0_Isr() interrupt 1{
    ' y* @. b- x- D8 k
  79.         // 输出矩形波
    & u$ n3 i5 q" u
  80.         OUT = ~OUT;+ I! G7 P& N1 A7 i4 Y
  81.         // 累计矩形波次数
    ) @. W% N3 h& O
  82.         count++;
    ; F- }; B) H9 R/ h9 X' S
  83.         // 超过250个矩形波,准备停机
    2 X( W7 |. U/ e  P7 D, W2 E) L$ t2 _
  84.         if(count > 250){
    " o, U+ J# r! L" y( i- g
  85.                 count = 0;6 X  [/ Q$ s: N  }8 D5 \' S7 @9 {
  86.                 isReadyToHalt = 1;. _- h6 ~- [( G$ m
  87.         }
    9 T+ o2 c* [+ d2 D% ~4 o* A( z
  88. }( k+ k) f& V( I: e: n5 ^( M# n% v7 ?
  89.   B4 I; B2 u$ c  z: f0 @# l
  90. static void INT1_Isr() interrupt 2{8 ~6 K0 s% |4 ]
  91.         // 矩形波次数累计归零
    6 G) O2 Y, @+ Y- \1 T
  92.         count = 0;
    $ T7 n: X( q; Z8 C
  93.         // 重开定时器0中断
    % k- ?7 i6 q  D/ y" s
  94.         ET0 = 1;
    * |3 @% ?7 |9 O0 V* O
  95. }* x, q4 w7 o* M, [: C

  96. 1 E6 O5 d6 b6 X2 \+ a! O
  97. % j$ N  h% L8 L/ d1 S
  98. void main(){
    4 t( h" c8 Q* g. }# g
  99.         // 初始化P3和P5口5 c3 f) y6 T8 D$ W, J; R
  100.         GPIO_Init();  y& r, [& S9 b6 s
  101.         // 初始化定时器0
    7 p4 J6 h5 [4 b5 X1 r
  102.         Timer0_Init();& ?* M9 ]" R4 y
  103.         // 初始化中断2 W+ k" P: ~' W  t. x8 Q- k' y
  104.         Interrupt_Init();
    " b! _1 G2 u, d5 ]7 h
  105.         + V  |" u: f8 y* F3 W7 t
  106.         while(1){
    ( D( R* Z# G& K2 @; g
  107.                 // 检测电量
    & x: P- F& z* o0 z
  108.                 if(PCON & (1 << 5)){
    + G, i  w' u% V# _0 c
  109.                         // 如果电量低,低压指示灯亮& a* E$ `8 R% G+ _3 v1 K0 y) D- M
  110.                         LED = 0;
    6 E( e4 G/ Z% Y
  111.                         // 清电量检测硬件标志位
    * h  i1 W; r& J  m' a6 P
  112.                         PCON &= ~(1 << 5);: w" r- s7 C) i! @2 W) v. T
  113.                 }else{0 v+ l# H. X9 U3 U3 o
  114.                         // 电量正常,低压指示灯灭( \0 A: q* V1 h" g6 j5 C
  115.                         LED = 1;
    " b, A# p) M( w5 L% @6 _9 m
  116.                 }
    3 Z3 h0 t; v9 g+ M

  117. 9 ~: [7 ?6 o/ q
  118.                 // 检测到停机标志
      z- a* J* T3 b6 D1 ^
  119.                 if(isReadyToHalt == 1){; `8 H. L- j3 k' b9 [$ w* z: d
  120.                         // 暂时关闭定时器0中断
    ( b2 c3 K: E/ y1 R" ?3 m. x
  121.                         ET0 = 0;" t; O. v9 W2 K: L/ K4 s- @" [
  122.                         // 停机之前先把矩形波输出脚置低电平,以方便INT0和INT1唤醒CPU9 x( v1 `: ^: j
  123.                         OUT = 0;
    ) Q% t; ~& X- U. Y( N' w7 d' u
  124.                         // 停机之前先把低压指示灯灭掉,以省电% K2 h+ p5 _# w, z$ u
  125.                         LED = 1;- Z; r6 f% b  n) Y0 \
  126.                         // 进入停机模式
    & _) l+ j: Q0 P0 J; f
  127.                         PCON |= 0x02;
    4 Y  `. b1 g% r9 I
  128.                         _nop_();1 ]9 g) u% U, t+ M0 W
  129.                         _nop_();
    ( g. X0 C# f; X3 `1 ^: y
  130.                         _nop_();1 \6 C* D& R, H# P  ~6 a
  131.                         _nop_();1 M+ w- y0 }: [6 A- e8 G- o
  132.                         // 唤醒,清标志位" T9 g) q! O) t+ a
  133.                         isReadyToHalt = 0;
    % [; o3 H, _8 T. j0 N
  134.                         // 重开定时器0中断
    ' L5 S( g1 v9 \% N3 u% s; w1 L
  135.                         ET0 = 1;
    2 W: C- k* P3 N  R* z
  136.                 }/ f2 ~5 M1 W/ l" g
  137.         }
    ) G7 n( a2 Q2 M0 q
  138. }
    ! a# k$ Y9 l' Q( g" m
复制代码

4 A8 O" T6 i7 Z硬件参数配置:% F8 R( n; o) C+ `  P5 V% n
! V8 [, c! f+ f- W) B! v1 @
3 Q9 h5 g6 `7 @+ _. U: E
接收端:
8 z; m2 ^- ^; F# z8 u  U& k$ ?
  1. #include <INTRINS.H>9 d  u* ~: V5 Z5 e1 _! X/ G
  2. #include "STC15W.h"0 {, d; Q+ ]/ b

  3. 3 e7 b9 u$ K2 t8 a- s4 u
  4. ( i! ?- z1 U# S$ A
  5. /*
    & u' ~  I! [5 \  G
  6. 8 U9 z- l, F5 o2 O
  7. *---------------------------*4 d  ?7 G: \5 F7 F6 F, J: [# D+ W; g! F
  8. |1 (GPIO2)         \__/  (GPIO1)16|( ~7 f9 J' T3 T+ I: g
  9. |                                                        |
    . X- v! W( \" O! _4 }
  10. |2 (GPIO3)                   (GPIO0)15|* O( w- J/ v! B" V
  11. |                                                        |
    : N; @& i. Q$ {9 ]/ O# I0 x
  12. |3 (GPIO4)                                  14|
    6 x7 L5 J; j& {/ }' p+ |
  13. |                                                        |- {: x- x) D' m1 W4 s8 z
  14. |4 (GPIO5)                        (DATA)13|
    ( `0 e$ ]$ |8 G0 i3 d% B/ a' |
  15. |                  STC15W204S                |$ e1 Z$ @9 Q/ P
  16. |5 (GPIO6)                   (LATCH)12|4 L/ O- x. H" J: a( j" c
  17. |                                                        |
    8 p' [! z! r1 x, ]# k! P
  18. |6 (VCC)                         (CLK)11|6 [8 |9 ?% H! E) h8 C; X, T8 k
  19. |                                                          |
      t6 [2 i4 Q$ U+ {
  20. |7 (GPIO7)                         (TXD)10|
    9 h7 n* y, y6 t4 K7 ^3 H: k# M7 b
  21. |                                                        |+ }& Q0 m  G  o- ]8 o2 S6 z8 q, w. N1 N
  22. |8 (GND)                         (RXD) 9|% r9 r" |7 z& X
  23. *---------------------------*5 ~& w+ z; E( I4 d, Z7 W3 h
  24. Fosc = 12MHz6 D1 C1 ~( A8 L  n& J( o9 q
  25. ; R7 d: B5 d+ `1 ?
  26. P1.0 -> 上
    6 X! C8 Y4 b- O+ V1 ~1 h
  27. P1.1 -> 左# U( X% m2 c) q" P' p9 c( h  \
  28. P1.2 -> 下3 M& z9 p6 r7 c8 \
  29. P1.3 -> 右
    / J; ?5 x- g4 B$ n9 }: N7 J# O  s
  30. P1.4 -> SEL
    / K: u' C' y0 C- y( K+ e
  31. P1.5 -> STA
    1 T0 Q1 G5 Q6 o' R0 D( z# A$ x3 F
  32. P5.4 -> B
    " ]( q) T/ ~0 h, N: ]
  33. P5.5 -> A  ^: Z5 j& c- w8 s
  34. 8 D& w% O) b+ S
  35. */2 M4 H8 P* b3 s) B

  36. ) l1 Z! J: s0 ?8 H% Z4 r, {9 {
  37. * H4 T: c" q) }* I7 ?
  38. sbit CLK        = P3^2;
    ' E7 \2 ]9 r& k  V& ~0 a" K
  39. sbit LATCH        = P3^3;
    1 K$ B& z% k4 B! @
  40. sbit DATA        = P3^6;) i. r$ X2 e6 w2 K# x' {
  41. 2 T8 b' [8 `! k" f
  42. bit isReady = 0;$ J0 {1 o' H* R2 q3 x& p: E% v
  43. static unsigned char key = 0;8 H. U) |5 x$ m, ~/ {4 }
  44. static unsigned char buf = 0;        // 双缓冲。这个缓冲区保存从P1和P5组合而来的键值9 X8 `% o( f* G2 y
  45. static unsigned char bufReady = 0;        // 双缓冲。这个缓冲区保存上面那个缓冲区的备份. ~% g2 T8 G# S+ e7 s; T  @. ^
  46. static const unsigned char data mask[] = {0x80, 0x40, 0x10, 0x20, 0x01, 0x04, 0x02, 0x08};        // A B SELECT START UP DOWN LEFT RIGHT。为提升速度,这个表放到RAM中9 t. q# Z* G- x. O  @/ c1 l; g
  47. static unsigned char idx = 0;
    / [6 _8 r6 m6 j; g1 r) Y
  48. 3 W3 g5 B6 S( ?3 D6 F6 f

  49. ' E' a6 n' y" c3 L, c
  50. static void GPIO_Init(){
    % l+ p( V1 D; I% {  w) p
  51.         // P1口和P5口用于接收并行信号,全部初始化为准双向,依靠内部弱上拉输出高电平
    : Y# r. n8 V/ D& ^" `9 b' [
  52.         P1M0 = 0;' }- f# w& C! I% L3 e1 D
  53.         P1M1 = 0;$ ]- m% O7 o; J/ U
  54.         P1= 0xFF;% E& H& H2 X$ ^, h# [: u( u; ~1 W4 s
  55.         P5M0 = 0;+ @( V: l9 z8 f' @
  56.         P5M1 = 0;2 X( ?8 J+ i4 n- G
  57.         P5= 0xFF;
    ( s3 `' s# S6 w% Q6 \
  58.         // P3口初始化为准双向
    - I. A  w, ?4 P" T( W
  59.         P3M0 = 0;; U/ y& ^* f' e5 X
  60.         P3M1 = 0;
    ' ?% y" n! u& D, |3 M" V5 d
  61.         P3 = 0xFF;6 s1 G0 ]$ N. h3 W' _/ z5 A9 y
  62. }
    * U! {  R/ R6 y7 H  X! C
  63. $ U$ S0 S8 |- ^1 ?. H1 S
  64. static void Interrupt_Init(){
      l/ o, l) q( h9 @1 X2 ~
  65.         // INT0中断(CLK)触发类型为上升沿+下降沿
    & e: m2 x. i+ Y$ d
  66.         IT0 = 0;
    0 R$ H1 P& _+ E# |- n% C
  67.         // 允许INT0中断: w) r. E  J. ?% L
  68.         EX0 = 1;
    0 J( q2 E) S- N" X, r
  69.         // INT1中断(LATCH)触发类型为上升沿+下降沿& W: }6 ~) m, ?! o3 x9 N
  70.         IT1 = 0;
    ( ~0 \. d: K! O! w! c! E9 O$ ?# N
  71.         // 允许INT1中断
      \" X0 I+ E+ Z7 D* }. P( @
  72.         EX1 = 1;
    . C6 j5 Z) k" j0 J/ N
  73.         // 开启全局中断
    2 F& C0 `" e. p  C7 n% V
  74.         EA = 1;$ ]! b% I! ?: y! n7 l0 o
  75. }0 t/ O, [& c2 T+ H2 m2 G$ C8 @

  76. 3 `6 w. D  e% V" Z6 w3 k
  77. static void INT0_Isr() interrupt 0{* W& i+ M4 l+ X- K% [* ?: G" q
  78.         // 只有已经成功锁存才允许CLK移位. a6 L  h$ p* \  w
  79.         if(isReady == 0)
    ! [& i# j# ~8 M6 ?% R+ T. N
  80.                 return;1 P) c  p* w& q) }: G' @/ h
  81.         // 读当前引脚电平,如果是低电平则说明是下降沿,此时直接忽略该中断' D# p+ h4 r% Q+ U: ?
  82.         if(CLK == 0)
    3 E$ a+ b! }# v$ R) V
  83.                 return;( T9 ~2 I, r1 H2 g% L/ b7 L
  84.         // CLK上升沿到来的时候,取锁存值的下一位输出% `' i& {" z. Y# e3 U# X9 k: {, _
  85.         idx++;
    $ ]; v1 G0 y  g$ T+ b3 O" J' z
  86.         DATA = key & mask[idx];
    ' O- ]8 j2 |  M0 e
  87.         // 如果已经完成7次移位,则一轮读取完成1 q; Q- F) P4 c5 @. u, Q# `
  88.         if(idx >= 7)% k' p* R1 r* d, v  X( J
  89.                 isReady = 0;
    . B! y/ p6 I' T0 n/ L$ Y
  90. }
    4 v6 e2 T) v& w8 d. {

  91. 2 L. q& h# e3 |9 k! O. Y, l% |, L- B
  92. static void INT1_Isr() interrupt 2{
    * x3 o; Y: e0 g% W
  93.         // 读当前引脚电平,如果是低电平则说明是下降沿,此时直接忽略该中断# O$ j- A$ m: Y+ _) `# k% @
  94.         if(LATCH == 0)
    6 O' \- D9 L8 P4 P) [( g
  95.                 return;0 _+ ^$ [- V( ~3 c% ?! y% ~
  96.         // 当LATCH上升沿到来的时候,锁存所有按键状态,同时把键值A输出到DATA
    " E  Z( n. j- P  |
  97.         key = bufReady;2 a& H; o  `9 D9 R: }
  98.         DATA = key & 0x80;//mask[0];        // 为了加速运算,直接取表中的值而不是读表. m  h3 a3 W( k, I3 u0 a/ u) W
  99.         idx = 0;' c6 }1 ?0 b0 c% f
  100.         // 允许CLK进行移位) m9 x: Q( K& V4 m7 I! T, ]1 \, N
  101.         isReady = 1;+ x/ ~! a7 I. n1 F1 Z% i
  102. }
    * j; V  ]0 J8 T& w
  103. : ]' U: @8 ]9 f, K
  104. void main(){
    1 f2 X# {/ T3 j( [# X0 r# r
  105.         GPIO_Init();
    " Q: k* g& _, k0 P$ m
  106.         Interrupt_Init();
    / r4 o$ F* ]/ M) [, u/ C# g
  107.         / d+ I+ ^) ]& j6 \9 A* @
  108.         while(1){
    # Z6 Y$ N) g9 }/ p, ~  h
  109.                 //PCON |= 0x01;        // 进入省电模式
    9 N) s7 b) ]% j' x0 F9 j8 Z7 F
  110.                 //_nop_();
    7 X0 l3 w: K2 M1 H$ C8 |( w
  111.                 //_nop_();
    3 R+ e0 X8 O. ]" n2 H. F$ h8 j+ A
  112.                 //_nop_();
    8 u4 M- t' ^6 h' R
  113.                 //_nop_();
      g' w7 a9 f) G0 c5 V7 `
  114.                 buf = ~((P1 & 0x3F) | ((P5 << 2) & 0xC0));* E5 b$ @0 j' n: u
  115.                 bufReady = buf;
      Z$ M0 I, w) N2 r
  116.         }
    + P1 B6 d9 Y: H8 |( e2 X/ t2 X
  117. }" L% j7 T  }$ I2 b& b' r- r
复制代码
/ ?4 D, L6 t2 ]$ X: m0 ?7 k
硬件参数配置无特殊要求,晶振频率选择12M即可。) {) q  _9 N4 N  b# [5 ?' k
, Q' z$ s) W7 c, P& l3 d
这是编译好的固件。

本帖子中包含更多资源

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

×

评分

参与人数 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:056 L% g( c( Q9 ^1 o# E8 s! A
不错的设计,想问一下楼主,FC的15针公头怎么解决?普通的公头太短了,插不进去FC的扩展接口。 ...
$ P3 s' p' ]; z
坛友的改造方案
回复

使用道具 举报

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

使用道具 举报

发表于 2019-5-25 12:07:18 | 显示全部楼层
精彩,楼主动手强,也写得很详细。7 }7 }5 U" N3 F
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* S- A  `1 W# r) m) y
精彩,楼主动手强,也写得很详细。
: [! H1 q0 S$ t9 p1 L5 A2.4G方案是目前无线的最低延迟吗?

# o( r9 O2 c( j" A9 M我没用过其他无线手柄,所以实在不知道我自己做的这个手柄到底是不是最低延迟。+ }% x1 j  ?1 p: O7 Y( M4 F
不过根据网上的说法,延迟高低主要是由通信协议的复杂程度,以及数据传输速率决定的。这个模块虽然是2.4G无线模块,但由于协议很简单,所以延迟比较低。* u1 M& n9 }% H1 ]2 [, A
我用这个手柄玩一些ACT游戏,比如超级马里奥、忍者龙剑传、热血系列,完全感觉不到延迟,和游戏机自带的手柄没有任何区别。唯一的区别就是这个手柄是用火花山寨手柄改造的,外壳是垃圾回收塑料,粗糙+脆弱,导电橡胶弹性不佳,手感不是一般的差。) G  U# S; k% x9 d  N
我手里还有十几张板子,等我有空了我再做一套,到时候买一个好一点的手柄改造。
回复

使用道具 举报

 楼主| 发表于 2019-5-29 16:56:14 | 显示全部楼层
ppad 发表于 2019-5-28 17:27
$ e7 l( I$ }" i7 t; D( K给技术帝赞一个,有半成品发布吗,自己焊接改造就可以,编程实在不会啊 ...

- q) r$ }* d& V3 D很可惜,我手里没有多余的单片机了,LDO也找不到了,锂电池以及充电模块更是没有了。反正就是该用到的元件基本都没了,所以没法发布半成品。3 x$ s0 |" B4 y7 y4 K
两个板子倒是有十几张剩余。
7 Z/ _7 _  g) I- o% E$ p你要是有USB转TTL串口板,完全可以自己买这两种单片机,然后我给你编译好的固件,你自己用串口板下载到单片机里面就行了。两个2.4G无线模块也得通过串口板用AT命令设置参数,不过好在我在设计电路的时候就已经预留好了串口,可以直接在线下载和在线设置参数。总的来说并不麻烦。
回复

使用道具 举报

 楼主| 发表于 2019-5-29 17:00:34 | 显示全部楼层
孙大师 发表于 2019-5-28 18:552 p: t% m; c! c7 F5 \
非常好,楼主是技术帝,到目前我都还没开发fc的无线套件,等空了,开发一套套件,等玩家自己组装。 ...
  h" H% B6 y/ V
能得到孙大师的赞誉,不胜荣幸!
- \" o* X2 F: v5 _不如开发一个多功能手柄,比如用SFC手柄改造,L/R键配合其他组合键可以用来切换2P~4P、调节连发速度、软重启等各种功能。接收端插到15PIN扩展口。
回复

使用道具 举报

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

本版积分规则

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

GMT+8, 2026-8-5 17:47 , Processed in 0.120290 second(s), 15 queries .

Powered by Discuz! X3.5

© 2001-2025 Discuz! Team.

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