找回密码
 注册

QQ登录

只需一步,快速开始

查看: 24847|回复: 32

自制FC无线手柄

  [复制链接]
发表于 2019-5-22 14:16:45 | 显示全部楼层 |阅读模式
本帖最后由 雷精灵2046 于 2019-6-14 09:28 编辑
4 c% b7 R. M. D9 w8 i
+ _2 Y9 h" I3 w& Y2 N. w1 E7 L3 X" [没有用复杂的分立元件搭建发射接收电路,直接用的现成的2.4G无线模块jdy-40。
: f' x) ?- D9 E9 }0 ?% g# K1 J2 [0 D- B  C$ ^. _8 O5 P/ U
; S' u. ^% ~$ m% q
发射端靠3.7V锂电池供电,用了一片SOP8封装的STC单片机,负责产生连发脉冲,同时负责检测电池电量,电压低于3V左右的时候触发低压中断,低压指示LED就会亮起来告知该充电了。平时发射模块和单片机均处于睡眠状态,有按键按下才会唤醒,从而实现省电。实测睡眠状态下整机电流约1~2uA。板子洗了一下稍微干净了一点。因为对于微功耗设备来说,焊接残余的助焊剂可能会增加漏电流。
# A9 ?1 t, m* X  s$ {/ r: w2 _8 v% ]/ E- c
买了一个火花的FC山寨手柄,去掉里面的牛屎板子,并修正一下塑料挡板,把锂电池和充电模块装进去。
! F7 [4 u+ I, G" z0 k为了减少体积,充电模块裁剪得十分小,并且更换了充电电阻使之适应这个小小的锂电池。这么小容量的电池,也不需要多么大的充电电流是吧?
0 z$ Y' F3 I. |  _4 q8 D然后统统用热熔胶粘上。充电电流比较小,所以发热很少,不会熔化热熔胶。0 C# R  i, J8 m# q
7 l% K, [) L! q

: g' r# h  Z/ L& n5 r
# [1 q) I/ Y8 q! _6 Y- q最后把按键、导电橡胶和电路板装上去。& M, {  X+ y& \* L1 X- v: I- i
精心裁剪了电路板,正好扣上,不会阻碍其他元件,也不会影响后盖和拧螺丝。
- m. j1 X8 Y- ?1 I6 G! \
9 @; W/ j" [7 Q/ a4 U( o) d9 D* Z1 \+ c
完工!
7 r' w9 l1 l2 |* I0 @! M  T6 B5 K$ I3 ]
  a1 M! g. u& R* d. `: p- q
这是充电的MicroUSB插座。旁边的小孔用于透出低压报警LED的光线。
6 m+ S7 A& S0 q5 r" ]* J* ^+ T  O
6 l6 c# q! ^& S- C- o% ?4 c
接收端用一片DIP16封装的STC单片机模拟CD4021。为啥要用单片机模拟而不是直接用CD4021?因为jdy-40模块接收端在有按键按下的时候输出高电平,无按键按下输出低电平,和普通手柄正好相反。当然我也可以用两片74HC00或者74HC04之类的逻辑门进行反相,但那就增加了芯片的数量。对于FC手柄这种工作频率并不高的设备来说,STC单片机完全可以胜任模拟工作。
5 D# n  Z$ k' f1 U. e( w& U: h
, s4 f; U1 \7 t5 ~8 f1 ]4 s5 ~* e$ u* Z/ o& k( v
+ ^$ b5 N7 L* ^7 n& E0 h
电路设计有点小小的错误,所以有几根飞线。原本设计使用低压差LDO是XC6206,结果在做这个接收模块的时候,买的LDO居然找不到了!无奈只好用了AMS1117。幸好对于接收模块来说是5V降到3.3V,1117可以胜任。要是发射端手柄的话,3.7V降到3.3V,那就非得用6206不可了。
& r# S+ R6 |7 M- [1 A2 R9 I' _9 A
6 c; _1 [- X# h& q9 w7 J# m实测十分灵敏,延迟极小几乎感觉不出来。可惜这山寨手柄的手感并不佳,尤其是方向键,软塌塌的。看来我得买个剪线手柄改装。
! t) ?4 i( H! e, `# X8 n
/ B1 c. C, L& Z( |# @! E这是电路图,有兴趣的朋友可以参考。
. ?% O3 |9 Z. r/ V6 ~7 z) k- D1 r
4 }$ U& s4 F' [5 p5 }" r" g5 w% M1 s! V! `' Z3 A5 F
我信奉开源主义,十分痛恨把技术藏着掖着。好东西大家分享嘛!所以两个单片机的源代码大公开!
8 R% o) {- ~* x编译器:Keil 51。/ T# y! h# K! a/ e5 x7 q
& \, b, h, y" \" G8 E# t" I8 W
发射端:
" t# E5 I. N0 i" l' H2 j1 Z
  1. #include <INTRINS.H>
    ; V. r, O% @3 s( ?- R0 h% x- S
  2. #include "STC15W.h"" O- q) t9 J  T! X5 ]2 _
  3. $ H, B. A& {* n4 L+ P/ d

  4. ) s/ q* p8 B$ o8 ], R$ Y! x
  5. /*
    ! H# h+ c; h* d/ _* l9 U
  6. --------------------------) D  V+ z8 r2 S6 Y! R9 S
  7. |1 (OUT)        \__/   (INT1) 8|& w" ?. Q, p1 H3 O, i. S) e
  8. |                                                   |
    9 P$ \. K/ w3 E
  9. |2 (VCC)                   (INT0) 7|
    ; y" W0 d6 s: C& M2 \! G: h
  10. |                 STC15W204S                   |6 E9 s8 A* z% a% H: x- q
  11. |3 (LED)                         (TXD) 6|( H: Y) y  z/ y  n+ ^8 K8 k0 S
  12. |                                                   |9 H% u" O  z+ t4 C
  13. |4 (GND)                         (RXD) 5|
    " X! ?8 a: ]/ u( l8 o/ Y) N4 {
  14. --------------------------: C0 B" O4 c+ p/ y+ |8 k- W

  15. : @: n( v) D( ?, C
  16. LED ---|<|---[===]--- VCC. o3 V- N3 A- p) I; l* t: V
  17.            Red          330% }9 j: w) K/ s% O/ s9 H

  18. 8 e# V1 x, S% B0 k( e
  19. Fosc = 6MHz
    % Z0 C$ S6 C( R  D* j8 l' [
  20. */; U+ g( m" Q9 \' U, f) E
  21. & G* ~& k) u. _. @

  22. " o, M' [; d& y
  23. // 矩形波输出脚# Z' \/ R, q; C0 Q! ?6 r, @) |2 i
  24. sbit OUT = P5^4;
    ! o8 Y/ N: o: o% m% {
  25. // 低压指示灯引脚
    & [( |% @4 [# R3 q5 D4 q  u
  26. sbit LED = P5^5;0 [0 l& p- D/ `
  27. " \8 ?( h" K/ S/ T/ z, o
  28. // 停机标志位* G8 Z5 o7 n4 J) B* c
  29. bit isReadyToHalt = 0;
    5 N  J4 d: T( x1 j7 I/ c4 @
  30. & h3 x3 R9 F1 S+ L* L1 Q2 w. i# P6 ^
  31. // 矩形波次数累计
    + E( D8 g) f( |6 Z. s" i
  32. static volatile unsigned char count = 0;
    . [; ?7 m* B# e, ]- f

  33. % b- l4 |- h0 e
  34. " E: K9 B0 P# P8 [  [
  35. static void GPIO_Init(){
    % b- [( v1 j4 [* G
  36.         // P3口设置为准双向,默认靠内部弱上拉输出高电平9 i+ X; X5 V# a9 T6 [! I5 `- _
  37.         P3M0 = 0;( v% C) n1 k% x$ v, m
  38.         P3M1 = 0;2 [5 e2 b  t2 D! x% z* z9 t: V3 \
  39.         P3 = 0xFF;
    . x) g" y% v( S5 X
  40.         // P5口设置为准双向,默认靠内部弱上拉输出高电平0 N, j7 ~) H! G4 Z  e/ H
  41.         P5M0 = 0;
    " G, u3 ?4 m/ |2 Z0 Z! v$ m" Z
  42.         P5M1 = 0;
    4 d; y6 d* G4 @+ b
  43.         P5 = 0xFF;7 \- O9 t  O8 t/ s
  44. }
    ) N" K% J3 g0 b1 d3 p8 J$ h

  45. 2 S* |- Z: t+ [$ U
  46. static void Timer0_Init(){
    . P8 n! K+ Y* }2 u" z. l' p
  47.         // 16毫秒@6.000MHz
    5 D" E# A' l% t% G
  48.         AUXR &= 0x7F;        // 定时器时钟12T模式
    5 o6 L& Q+ l, }& L) j
  49.         TMOD &= 0xF0;        // 设置定时器模式
    ' C& M7 J  N6 m7 V9 Q8 K
  50.         TL0 = 0xC0;                // 设置定时初值2 s- P) Q  @0 Y$ h
  51.         TH0 = 0xE0;                // 设置定时初值8 t: m4 |: }  V8 ^) H5 r% J0 c
  52.         TF0 = 0;                // 清除TF0标志
    / b7 q+ w, B% y3 x" f
  53.         TR0 = 1;                // 定时器0开始计时
    , p0 g/ [5 t; W% K1 q8 w
  54. }* Q* K* T$ K6 y- V7 D8 a' X( B# N
  55. - E( s2 g- A0 e" i& e5 X" d
  56. static void Interrupt_Init(){
    $ E2 C( T+ C" W5 z  }! F5 f0 {
  57.         // INT0中断触发类型为下降沿触发
    : H4 ~4 `6 {2 a
  58.         IT0 = 1;
    , ]# M5 n4 ]0 i- T
  59.         // 允许INT0中断2 R$ k& |7 K$ D& F% I/ M4 A3 n
  60.         EX0 = 1;
    6 m+ h* f0 B; b5 b, P* n0 a7 k
  61.         // INT1中断触发类型为下降沿触发
    5 c$ c6 Y3 j6 ?" q& A
  62.         IT1 = 1;
    - L- S, `) r, Z- C) W  `( z
  63.         // 允许INT1中断
    . c4 K. x$ A: v4 V" [
  64.         EX1 = 1;0 ?( Y: e# o# t
  65.         // 允许定时器0中断5 \9 I4 `9 C3 N' n% ~8 \
  66.         ET0 = 1;
    7 e& s8 x. m9 X: N
  67.         // 允许全局中断8 A/ ?  g1 o/ |" ~
  68.         EA = 1;
      z1 B" Y0 h8 C/ [3 Z4 Y
  69. }( u  P: [* {$ Z: T' {0 V

  70. + W" W6 E0 E; X' o
  71. static void INT0_Isr() interrupt 0{! O; G- O3 Q  H( ^/ @- u
  72.         // 矩形波次数累计归零
    ) Q1 j9 e7 I0 ^6 z8 {+ p; @# {3 _- H( x
  73.         count = 0;- M7 K5 P1 m! o3 Z: e
  74.         // 重开定时器0中断8 S: f" s! |$ N7 g! c: R/ d
  75.         ET0 = 1;- g; m0 `! j$ }' U# Y
  76. }
    ) [9 k. _$ o( x  o/ b, R

  77. 3 |  V+ @. B* Y8 X9 R5 U4 e+ D
  78. static void Timer0_Isr() interrupt 1{7 q! `& V# t4 `$ ~# S
  79.         // 输出矩形波: c9 A6 P/ f) }& @2 h7 [/ l
  80.         OUT = ~OUT;$ L/ W" @( y1 k9 {! i. [
  81.         // 累计矩形波次数
    ' K% k0 P# A3 h) G6 h% ]
  82.         count++;
    6 j/ ~3 i) Y/ [& t2 x0 B
  83.         // 超过250个矩形波,准备停机
    . q! G+ y- m, u. [2 T. ]+ c
  84.         if(count > 250){7 X' S3 d5 S+ E6 n$ ]6 I
  85.                 count = 0;
    2 [/ w& J) t# m4 i7 r  b. f
  86.                 isReadyToHalt = 1;
    % g/ Q% ?' ^. O; H! \2 N
  87.         }
    9 W2 ?7 d! \* k: B
  88. }: _; a$ [  Y% m4 k- M' B- n, O
  89. 0 R  c, B+ Y; n' Q& e2 v# ?/ j4 e
  90. static void INT1_Isr() interrupt 2{
    / H9 _& V+ T, Z. t! C& r( X: e
  91.         // 矩形波次数累计归零
    # A$ R5 w% S, h& B# ?
  92.         count = 0;7 F( i: O' {* x) }/ A% ]6 H
  93.         // 重开定时器0中断
    ! c8 s, p& F) P% l6 o" V
  94.         ET0 = 1;
    8 f/ G7 \! x9 ~1 E: `
  95. }- ^0 U% ]5 k1 w$ v4 ?( @

  96. 3 W4 y; f+ p0 j7 J% K+ ^! j
  97. ' ]" |# j  G$ j" w
  98. void main(){( l5 B* V" P/ \" w2 @$ L3 M/ K' y  ~
  99.         // 初始化P3和P5口
    . X% ?" S! P  k- k/ |* e
  100.         GPIO_Init();4 A' P$ v. D" E+ B9 p+ `; V7 [
  101.         // 初始化定时器0
    # X8 _3 p5 v: b  ^/ P" ^3 {
  102.         Timer0_Init();
    # z7 Z% {. _' Z8 u
  103.         // 初始化中断
    : S: d- ^5 e; y  ^; P
  104.         Interrupt_Init();) f! m$ G& a- X7 Z
  105.         4 }9 H: C8 `' r4 N6 l
  106.         while(1){9 ]* s+ X! N% ~' T7 r% B
  107.                 // 检测电量* c* z& S0 w* K( @  G  \* F  l
  108.                 if(PCON & (1 << 5)){
    + E. H6 j! `+ {
  109.                         // 如果电量低,低压指示灯亮
    " C1 I1 h4 ]5 Q* q
  110.                         LED = 0;
    $ K5 l) \0 X- m- Y, S, V0 o
  111.                         // 清电量检测硬件标志位
    : o$ _' Q% V2 w6 y3 }& v
  112.                         PCON &= ~(1 << 5);
    7 b* i: J# D- X5 Z" {0 c
  113.                 }else{/ J4 C7 K# G+ K4 C
  114.                         // 电量正常,低压指示灯灭
    % L# d4 l/ C5 R4 P
  115.                         LED = 1;
    0 p3 f. j; E/ \+ a
  116.                 }4 W+ E$ m- ?3 X6 x  O+ Z# @
  117. & y$ K: Q6 K: x3 k4 |# a) h( P2 a
  118.                 // 检测到停机标志
    " n0 V5 `3 H: J* \* H
  119.                 if(isReadyToHalt == 1){
    ! {) g) x9 g7 w, b' ~) {
  120.                         // 暂时关闭定时器0中断
    5 Q9 M* o9 ~+ H
  121.                         ET0 = 0;" C0 o1 F' D0 h# w
  122.                         // 停机之前先把矩形波输出脚置低电平,以方便INT0和INT1唤醒CPU
    # w! P( M& L6 L5 Z6 i
  123.                         OUT = 0;
    8 t+ Z0 K. @6 k# E
  124.                         // 停机之前先把低压指示灯灭掉,以省电+ v+ J* |) ~& K) r1 ^3 Z6 K
  125.                         LED = 1;* S! Q- W4 g1 _: W# E- j! I
  126.                         // 进入停机模式2 Q/ R* ~6 j) X2 X  ]
  127.                         PCON |= 0x02;
    8 q$ R& |2 P/ `+ h
  128.                         _nop_();& v/ u$ @$ W$ _$ ?
  129.                         _nop_();
    ' E$ @. P5 t! U/ q$ B$ ]
  130.                         _nop_();
    7 l/ }% N3 N( m4 y! y: [* [! |( S
  131.                         _nop_();4 W1 t4 m/ [7 d, J- o" E
  132.                         // 唤醒,清标志位) k! V7 F3 S9 J6 j2 X* @9 S1 _
  133.                         isReadyToHalt = 0;2 ^1 g4 t" U8 K
  134.                         // 重开定时器0中断
    2 y/ {4 S" r0 l2 a
  135.                         ET0 = 1;0 }' _. j* o$ r6 C( g4 y8 E
  136.                 }& l/ b- Q% h* G0 M. M) u
  137.         }
    . |; m: c4 w' g+ U& f7 H, }
  138. }
    & _7 P5 S$ g0 P: ]. X7 j7 R
复制代码

' o6 G# Y4 ?' Z& o硬件参数配置:
4 Q7 n" R! y6 Y) X3 I8 c' w+ }; ~, I( r0 S5 m4 p. F0 I$ {

; D6 R' {! U( D  `; s" E3 e接收端:6 d) F0 J6 D/ F' x/ C  Y, q: X0 n' t
  1. #include <INTRINS.H>+ h' Z/ L, v( q7 b; ~
  2. #include "STC15W.h"
    " u( I8 m' E( w  g$ Z
  3. " c- X& v: n8 N% A3 N
  4. ' w- @* o) P/ v" u8 G( O0 O7 f) O# O$ l
  5. /*
      D7 u" Q6 q5 j; H

  6. 7 ^6 g( Q9 k) W& v* e
  7. *---------------------------*
    3 |( z' B) [: f$ O' l. b
  8. |1 (GPIO2)         \__/  (GPIO1)16|
    8 X/ Y/ E/ g8 B* H
  9. |                                                        |/ s  ]. c3 u4 |3 D2 _
  10. |2 (GPIO3)                   (GPIO0)15|
    + U" b9 [; A0 Z9 c5 b% t
  11. |                                                        |
    8 ]8 G/ J4 B( [6 I7 O# R% A; B0 G
  12. |3 (GPIO4)                                  14|3 B# m+ V; ]3 ]4 G
  13. |                                                        |
    6 R' ]6 W& ^& i5 d/ `8 v
  14. |4 (GPIO5)                        (DATA)13|
    / c' [8 R; I- [& ]6 v3 {0 l
  15. |                  STC15W204S                |
    - L' h, R: V3 s4 A- ^
  16. |5 (GPIO6)                   (LATCH)12|
    # R( v7 T$ `! Z' \0 O+ ^
  17. |                                                        |
    8 P+ x- Q6 A/ M9 c. q
  18. |6 (VCC)                         (CLK)11|
    ! s" R  a% b2 @$ m
  19. |                                                          |
    4 N3 x; d5 |2 @5 t/ }
  20. |7 (GPIO7)                         (TXD)10|2 e# ]7 s$ x- P* b" }) J6 r" R
  21. |                                                        |/ @; e  q% U: o- C$ \2 h: o) k+ n
  22. |8 (GND)                         (RXD) 9|- T8 i) D: C/ c- U! r
  23. *---------------------------*7 J* o/ ]% W) Y; u% _
  24. Fosc = 12MHz
    ) b$ W: e% e* |2 v; |1 [1 y* ]! g

  25. ! i2 y" i% `2 C, R0 J7 y
  26. P1.0 -> 上
    7 z3 S% M3 ~9 Q. E1 C
  27. P1.1 -> 左
    2 ?' g" m6 s" Q' S4 a# Z5 W7 Y* g
  28. P1.2 -> 下9 s& g, Z" ~# e! H/ b- Q$ r6 T( d
  29. P1.3 -> 右8 e- o: B* j/ @
  30. P1.4 -> SEL+ D- i8 z0 k) o
  31. P1.5 -> STA, d& @/ p3 ~. s! n: d
  32. P5.4 -> B% l" d- i% Q  e
  33. P5.5 -> A
    5 z( M/ t0 t( e6 F9 X4 Y, h( F& w# I2 u
  34. : X0 Z& |$ ]8 h) l  o4 ]$ R
  35. *// ?8 H, }, s/ O2 n! {! y* g# x

  36. 1 E$ k  W0 Y8 \7 u3 Q
  37. 1 B9 o% @) {; e, c: J8 t  k9 c
  38. sbit CLK        = P3^2;0 X, Z9 Q6 D$ a3 e
  39. sbit LATCH        = P3^3;
    # y5 B" q3 n0 J
  40. sbit DATA        = P3^6;
    / p6 ]1 R# w$ o- O: e! C
  41. + z% t. `& f% {, h5 p$ @+ }
  42. bit isReady = 0;3 _4 i+ `# L8 ?* E( T9 K* X* Y" d
  43. static unsigned char key = 0;& P8 Q3 C( W. y! Q" i& ]
  44. static unsigned char buf = 0;        // 双缓冲。这个缓冲区保存从P1和P5组合而来的键值& q* x* \5 R! O
  45. static unsigned char bufReady = 0;        // 双缓冲。这个缓冲区保存上面那个缓冲区的备份
    : O9 Q/ B* [  B" h; }7 @; S% 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中
    7 s3 |, _8 O% G3 k
  47. static unsigned char idx = 0;
    / i4 d, S4 k; L; ~, N
  48. / [- A) D6 j# C4 ]/ F6 Y5 B
  49. - l  N8 a( d' N8 D; n) h. k
  50. static void GPIO_Init(){
    : ?* J: {3 Q% R) Y, F0 N+ ]
  51.         // P1口和P5口用于接收并行信号,全部初始化为准双向,依靠内部弱上拉输出高电平
    ) i; }  N9 y) ^
  52.         P1M0 = 0;& x) \' R8 a+ X  x
  53.         P1M1 = 0;
    2 k& e4 F& D0 _$ S" L' t9 y
  54.         P1= 0xFF;
      I) o# ^4 y# m% Y7 s+ H. c6 ]
  55.         P5M0 = 0;) S  [0 D+ C* M, F2 d+ u
  56.         P5M1 = 0;
    + A+ _% t8 x' o3 ^+ b
  57.         P5= 0xFF;9 M& U( w2 g3 Y% d0 Y- |
  58.         // P3口初始化为准双向
    2 u6 G" u& N( S- L1 _0 _9 a- n2 c
  59.         P3M0 = 0;
    3 p: ~; t7 e' F7 ?1 h
  60.         P3M1 = 0;
    ; J( I: @/ X9 z1 K; l' ~  j
  61.         P3 = 0xFF;
    ' [) i# j/ r5 c: p+ [5 ~
  62. }. a8 M# U1 }4 u$ Y2 y8 q
  63. " Z" e; P. ?. A/ m& t
  64. static void Interrupt_Init(){5 A* Y' b+ U# L/ ]
  65.         // INT0中断(CLK)触发类型为上升沿+下降沿
    " F6 `: Q% J- k- O* D% k2 S* W. V
  66.         IT0 = 0;+ C$ p9 j% C& g% p( t, \' t2 D
  67.         // 允许INT0中断
    9 h( E: I. W% E" e  ^! s
  68.         EX0 = 1;
    0 ?6 y) `/ k; h+ k3 ?
  69.         // INT1中断(LATCH)触发类型为上升沿+下降沿
    " h$ n/ J8 G* U" ~& q5 w& b
  70.         IT1 = 0;
    7 ?( M' r4 p2 R3 `5 M
  71.         // 允许INT1中断
    ( k& [# @( ]1 u) I; ?: A
  72.         EX1 = 1;4 D  `" t7 y6 a, W( d3 ^. k/ o
  73.         // 开启全局中断
    1 _, o* u  ~) R8 D0 a2 a/ s; v
  74.         EA = 1;
    8 m+ K4 j/ P4 o) ]6 n4 Q) S8 y
  75. }# {- R$ L0 c: G; K/ n& M3 l8 ~# z6 ?
  76. 9 Q- P& c% I2 T) R2 Q
  77. static void INT0_Isr() interrupt 0{  V( x6 H' V) r3 z9 P" m  ?
  78.         // 只有已经成功锁存才允许CLK移位
    + f7 [0 m+ F9 i: i* H3 h
  79.         if(isReady == 0)
    6 e9 B" [% s3 A
  80.                 return;
    - `- y) `: X' z  X% I" ^, S) e) N- q
  81.         // 读当前引脚电平,如果是低电平则说明是下降沿,此时直接忽略该中断
    ! z8 ^, F; ?: y; t/ d. F( E! L1 ]
  82.         if(CLK == 0)
    + F: V9 ~+ J; w! g+ ^
  83.                 return;
    + ~, Y3 z6 ]; j$ S1 O
  84.         // CLK上升沿到来的时候,取锁存值的下一位输出
    . F. _# i) [( ]7 W& Q9 ^% b
  85.         idx++;
    : f4 Z! [4 N% @$ s' U
  86.         DATA = key & mask[idx];
    2 _* o9 Y) k# w: P
  87.         // 如果已经完成7次移位,则一轮读取完成
    1 I( P5 z) [# H/ F# ?2 v
  88.         if(idx >= 7)
    . Y/ C- Z3 a1 q) v. C$ M( T0 s8 I5 H
  89.                 isReady = 0;
    - S5 p5 N4 X: ~( x
  90. }" E4 A" R5 U. t7 ^6 `" a) Y
  91. 4 w5 ^5 K) w2 _4 ?6 N( J8 o
  92. static void INT1_Isr() interrupt 2{
    # m) _" B* y3 |; g4 n
  93.         // 读当前引脚电平,如果是低电平则说明是下降沿,此时直接忽略该中断
    ( C/ f/ x$ ^. I7 S( r& Y% B
  94.         if(LATCH == 0)
    9 l! ~6 j- V/ A6 v
  95.                 return;9 c) Q( D. t* @2 p- m- ?. m
  96.         // 当LATCH上升沿到来的时候,锁存所有按键状态,同时把键值A输出到DATA
      x4 R, Y' i/ ~; {  @
  97.         key = bufReady;
    2 |7 b& h; E. U& E
  98.         DATA = key & 0x80;//mask[0];        // 为了加速运算,直接取表中的值而不是读表' W2 q5 m1 ~( u8 I1 [
  99.         idx = 0;
    1 g* X, X2 c2 Q8 j, ^
  100.         // 允许CLK进行移位
    ) \* W! V; s1 t7 q3 _9 m
  101.         isReady = 1;
    6 G  q+ o; q7 `7 S  i3 }. W
  102. }
    * _  k+ j4 J2 e

  103. 1 S6 R* ^& a9 q3 @; Z) j6 Z" A) D
  104. void main(){
    ! d3 P# y% j. d, S/ ?
  105.         GPIO_Init();: t1 t8 v9 d; e# k6 r* E8 f
  106.         Interrupt_Init();
    ; R  R7 K$ o9 ]$ a$ _
  107.         * s# u* s7 Z/ W2 L! V+ L
  108.         while(1){5 x1 Q& `& R9 N
  109.                 //PCON |= 0x01;        // 进入省电模式9 L  z2 @' W$ q# Y3 N- V
  110.                 //_nop_();
    8 U7 W5 e# L# D( o; e
  111.                 //_nop_();
    3 F6 o; C5 m- R5 Z8 v' F- ~
  112.                 //_nop_();
    * \; A5 @; v( \+ C
  113.                 //_nop_();* `0 ?2 Z2 n7 f/ S1 N) y  w) E
  114.                 buf = ~((P1 & 0x3F) | ((P5 << 2) & 0xC0));, ]3 S3 c2 m$ }# y
  115.                 bufReady = buf;0 t9 q) f1 p! l# S# h- {
  116.         }. s8 t# @6 ^3 _, j# Y/ s, X
  117. }% n3 \9 ~) x( R  {& Y0 z
复制代码

" Y% r+ ^  d# q) I1 v8 H8 `" i硬件参数配置无特殊要求,晶振频率选择12M即可。
; I0 E% P3 ]8 v5 a6 Z  T- A6 v# C! ^  n, e  \
这是编译好的固件。

本帖子中包含更多资源

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

×

评分

参与人数 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
/ @, O( I( E/ n2 q不错的设计,想问一下楼主,FC的15针公头怎么解决?普通的公头太短了,插不进去FC的扩展接口。 ...

) ^$ O* h" i/ r% z7 J9 D坛友的改造方案
回复

使用道具 举报

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

使用道具 举报

发表于 2019-5-25 12:07:18 | 显示全部楼层
精彩,楼主动手强,也写得很详细。9 o& o4 k1 Z" o# z6 Z" y; 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
9 z, i+ s9 J/ t, i5 C" \精彩,楼主动手强,也写得很详细。' R2 ?0 E8 h* J8 j% ~
2.4G方案是目前无线的最低延迟吗?

7 l" S! O1 ?' j- k$ {8 Q我没用过其他无线手柄,所以实在不知道我自己做的这个手柄到底是不是最低延迟。. [% b6 Y' h- b8 K
不过根据网上的说法,延迟高低主要是由通信协议的复杂程度,以及数据传输速率决定的。这个模块虽然是2.4G无线模块,但由于协议很简单,所以延迟比较低。
  j. a9 w( k) }( U* D  |/ p我用这个手柄玩一些ACT游戏,比如超级马里奥、忍者龙剑传、热血系列,完全感觉不到延迟,和游戏机自带的手柄没有任何区别。唯一的区别就是这个手柄是用火花山寨手柄改造的,外壳是垃圾回收塑料,粗糙+脆弱,导电橡胶弹性不佳,手感不是一般的差。! o& A5 j2 D8 X7 s! U
我手里还有十几张板子,等我有空了我再做一套,到时候买一个好一点的手柄改造。
回复

使用道具 举报

 楼主| 发表于 2019-5-29 16:56:14 | 显示全部楼层
ppad 发表于 2019-5-28 17:27
4 B  s; Z$ F* n: d1 n/ K( u给技术帝赞一个,有半成品发布吗,自己焊接改造就可以,编程实在不会啊 ...

! ^* w; w' W/ Q- n很可惜,我手里没有多余的单片机了,LDO也找不到了,锂电池以及充电模块更是没有了。反正就是该用到的元件基本都没了,所以没法发布半成品。' T$ k. f" m( z1 Q; O2 o
两个板子倒是有十几张剩余。
1 M2 N% i2 o- _; M你要是有USB转TTL串口板,完全可以自己买这两种单片机,然后我给你编译好的固件,你自己用串口板下载到单片机里面就行了。两个2.4G无线模块也得通过串口板用AT命令设置参数,不过好在我在设计电路的时候就已经预留好了串口,可以直接在线下载和在线设置参数。总的来说并不麻烦。
回复

使用道具 举报

 楼主| 发表于 2019-5-29 17:00:34 | 显示全部楼层
孙大师 发表于 2019-5-28 18:55) ^( V5 Z6 N) y% @" d
非常好,楼主是技术帝,到目前我都还没开发fc的无线套件,等空了,开发一套套件,等玩家自己组装。 ...
) R# x- V  S6 C3 y+ p6 R3 S
能得到孙大师的赞誉,不胜荣幸!
& j6 ]+ @" f# z不如开发一个多功能手柄,比如用SFC手柄改造,L/R键配合其他组合键可以用来切换2P~4P、调节连发速度、软重启等各种功能。接收端插到15PIN扩展口。
回复

使用道具 举报

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

本版积分规则

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

GMT+8, 2026-5-6 18:06 , Processed in 0.997218 second(s), 14 queries .

Powered by Discuz! X3.5

© 2001-2025 Discuz! Team.

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