找回密码
 注册

QQ登录

只需一步,快速开始

查看: 26095|回复: 32

自制FC无线手柄

  [复制链接]
发表于 2019-5-22 14:16:45 | 显示全部楼层 |阅读模式
本帖最后由 雷精灵2046 于 2019-6-14 09:28 编辑 3 m3 a! Y7 u. s  V/ `: X

) s; L( W. o; x* k  z! }没有用复杂的分立元件搭建发射接收电路,直接用的现成的2.4G无线模块jdy-40。. O9 Z( C' G) h5 J% `

. n: ?6 L! `& a6 O& r4 F5 c
$ o) c+ C9 f" ]" S发射端靠3.7V锂电池供电,用了一片SOP8封装的STC单片机,负责产生连发脉冲,同时负责检测电池电量,电压低于3V左右的时候触发低压中断,低压指示LED就会亮起来告知该充电了。平时发射模块和单片机均处于睡眠状态,有按键按下才会唤醒,从而实现省电。实测睡眠状态下整机电流约1~2uA。板子洗了一下稍微干净了一点。因为对于微功耗设备来说,焊接残余的助焊剂可能会增加漏电流。: P! e7 Q9 p: j, V4 b0 [6 L

% l" @5 Y8 Q# `* d买了一个火花的FC山寨手柄,去掉里面的牛屎板子,并修正一下塑料挡板,把锂电池和充电模块装进去。/ q. h7 {. X" \6 T
为了减少体积,充电模块裁剪得十分小,并且更换了充电电阻使之适应这个小小的锂电池。这么小容量的电池,也不需要多么大的充电电流是吧?
4 I$ c+ _- a: M. z8 L' M# g然后统统用热熔胶粘上。充电电流比较小,所以发热很少,不会熔化热熔胶。  o" i+ Z3 }4 f) K  Q: e. |; I4 `
( V/ [2 I2 X  v! \) c0 n
: a2 z. J6 H  m5 E" Z0 @: Y, A
) z7 Z% N5 g4 b' x; [1 t0 S$ S
最后把按键、导电橡胶和电路板装上去。2 }8 j. J7 [" o. |5 U
精心裁剪了电路板,正好扣上,不会阻碍其他元件,也不会影响后盖和拧螺丝。% w$ t2 X, O1 C

* e/ `% R! b* T2 v5 P) M+ Z; x' m' i
完工!" c# \. e9 J6 O: K, c1 v! J6 T+ q
- F8 ^8 S, ~$ p, `# ]* \- x

; w5 O9 E3 ]4 _这是充电的MicroUSB插座。旁边的小孔用于透出低压报警LED的光线。' w$ a: C$ X8 s

/ O/ T+ Y) Z; J5 f+ [
0 Z7 j- Z+ Y' B( w1 K接收端用一片DIP16封装的STC单片机模拟CD4021。为啥要用单片机模拟而不是直接用CD4021?因为jdy-40模块接收端在有按键按下的时候输出高电平,无按键按下输出低电平,和普通手柄正好相反。当然我也可以用两片74HC00或者74HC04之类的逻辑门进行反相,但那就增加了芯片的数量。对于FC手柄这种工作频率并不高的设备来说,STC单片机完全可以胜任模拟工作。5 v2 j. ]1 ~# T# F

  i4 d$ M- t/ n& E2 m& ^; x% x  \- |5 S( C4 f

) c+ W9 M1 r! v9 Y/ S电路设计有点小小的错误,所以有几根飞线。原本设计使用低压差LDO是XC6206,结果在做这个接收模块的时候,买的LDO居然找不到了!无奈只好用了AMS1117。幸好对于接收模块来说是5V降到3.3V,1117可以胜任。要是发射端手柄的话,3.7V降到3.3V,那就非得用6206不可了。
3 I5 |- D: j7 j9 z5 K5 E  p+ [! o
2 k; K) }: X6 T' e! i实测十分灵敏,延迟极小几乎感觉不出来。可惜这山寨手柄的手感并不佳,尤其是方向键,软塌塌的。看来我得买个剪线手柄改装。
$ E# n2 I" c3 q; {, W  K9 v' a) A8 Z
这是电路图,有兴趣的朋友可以参考。
% e/ r2 ]/ f$ Z2 g: v
6 X( S* v2 L# Z( K' D8 T5 e& ]+ i# \4 V, u- S% D! I: V
我信奉开源主义,十分痛恨把技术藏着掖着。好东西大家分享嘛!所以两个单片机的源代码大公开!
: p2 d- X$ `. W/ c编译器:Keil 51。
, l4 W0 M, E8 I5 X7 O# N/ h, F+ e3 z( q4 ^/ C
发射端:& f6 @% M! E: E0 f; J6 B  a2 s
  1. #include <INTRINS.H>
    1 C8 j" z# X4 R) F- }3 {
  2. #include "STC15W.h"$ s; N$ A9 ^1 D! b' }$ }% b
  3. 9 T& y0 ~( m/ o1 u! U
  4. 1 m1 ^  N; P, c. u& G$ _. f3 d# u+ w
  5. /*5 Q6 g, z$ u. O5 w/ J
  6. --------------------------. D5 q2 v: k- w% }( R* O1 ]
  7. |1 (OUT)        \__/   (INT1) 8|
    7 z6 Y# F. E; M  G, \
  8. |                                                   |9 k7 P5 x/ @! f
  9. |2 (VCC)                   (INT0) 7|" x  ^# a) ]4 h3 f, p: }' W
  10. |                 STC15W204S                   |
    1 D. Z2 r  f: o$ o
  11. |3 (LED)                         (TXD) 6|& N) h9 o6 l! D3 j" M, {9 o/ |
  12. |                                                   |
    8 G) V' P5 Z% W. ]* M) W& k
  13. |4 (GND)                         (RXD) 5|- ~1 f  E  Q" K" q$ c& P& o' U
  14. --------------------------
    8 `+ t( P* l' o4 F+ P  B$ _2 B6 B
  15. , D# t1 U$ e; E" ]  g( m: F( b
  16. LED ---|<|---[===]--- VCC% H5 x# c8 m6 U5 i
  17.            Red          330) K! G+ D6 U* p: b0 t- d
  18. / Z3 t7 i9 j) I) ^" I$ S3 i
  19. Fosc = 6MHz% e: _: N7 D/ ?
  20. */
    : ?6 E, u9 k% I" c) O6 [
  21. . H# X/ w( S$ E/ o) s3 I  g

  22. 5 k# c" c' x9 ?8 o& w9 s: }
  23. // 矩形波输出脚
    0 U( b9 h& e8 w$ C9 F* L4 b
  24. sbit OUT = P5^4;
    8 r7 q# Y7 ~+ T* q+ g8 t  N
  25. // 低压指示灯引脚
    % G5 \) c$ l4 T# Z' [+ X
  26. sbit LED = P5^5;$ I) X: S' [+ ]- Z* k1 q
  27. 0 y* W/ A. P# y
  28. // 停机标志位
    9 Y  t" C' J! o; I% F
  29. bit isReadyToHalt = 0;
    - |# Y+ Z& o* O. }

  30. 2 y/ [8 I7 F( X$ Q0 l5 S5 V  z/ b
  31. // 矩形波次数累计
    " ^1 e+ X* N7 V: ]
  32. static volatile unsigned char count = 0;. H/ V1 j% z' z- X" v  Q

  33. / w& L  g2 ~2 ~7 r* r) E

  34. 1 b, ?- E. l4 y# v
  35. static void GPIO_Init(){
    # h# ^$ n/ O% u% n
  36.         // P3口设置为准双向,默认靠内部弱上拉输出高电平: V5 D9 x$ p4 j7 S& B4 @  H
  37.         P3M0 = 0;+ j( `/ S3 b1 a1 k  D9 k2 T; S
  38.         P3M1 = 0;8 s) m1 P9 m& s# i# T% b  |) [; O3 |
  39.         P3 = 0xFF;
    ' c. ^# q6 K6 x) |
  40.         // P5口设置为准双向,默认靠内部弱上拉输出高电平2 t, \6 i* ^9 e+ \: L0 {  `7 G. J
  41.         P5M0 = 0;# T' Q0 E% h3 t
  42.         P5M1 = 0;
    % v. x; B  V7 s! s* w/ u! ^/ w* D0 ?
  43.         P5 = 0xFF;
    + q$ H4 d5 L$ o  c0 B% t; z) `) U6 p
  44. }& E1 A/ G1 p" C! ^) _

  45. ( x/ W! M7 X% q% ^3 Y) `  ?
  46. static void Timer0_Init(){
    ; Y5 s8 K, U# ~: _7 V9 y3 Z5 l) |
  47.         // 16毫秒@6.000MHz
    ; C; B9 h- ?8 W9 G( K. P' t- f
  48.         AUXR &= 0x7F;        // 定时器时钟12T模式
    1 r, R8 Z3 _( j5 S. ?3 \6 k
  49.         TMOD &= 0xF0;        // 设置定时器模式) X. H8 h) B2 \/ J' X' L& c$ |4 |
  50.         TL0 = 0xC0;                // 设置定时初值
    1 V! D( n0 F( M, b9 b
  51.         TH0 = 0xE0;                // 设置定时初值- f7 u8 n3 ?( g" \3 J  z
  52.         TF0 = 0;                // 清除TF0标志
    9 }! `: d* z- ^6 N
  53.         TR0 = 1;                // 定时器0开始计时- M+ G/ ~- Y; ~
  54. }
    - I# K$ M; g, |. h, w+ f4 K" ?
  55. : {0 F' ?/ O" U( v7 Q
  56. static void Interrupt_Init(){  V! t3 B% d3 \+ a# p& @8 @
  57.         // INT0中断触发类型为下降沿触发* w0 W! v0 Q( X2 c4 ~1 l' f
  58.         IT0 = 1;
    8 I" L' M. e0 W. }( ]8 G& }
  59.         // 允许INT0中断" `2 t. d6 P9 M  [' P! B
  60.         EX0 = 1;3 I0 l. o2 v6 \8 d
  61.         // INT1中断触发类型为下降沿触发
    0 E2 v# z  }7 `' i/ Y1 G  w* B
  62.         IT1 = 1;
    , X. C8 |+ Z/ }: N* T4 ]& O
  63.         // 允许INT1中断  X; x$ V# A* N
  64.         EX1 = 1;
    3 V: }7 ^$ l+ {# h+ ~; @
  65.         // 允许定时器0中断/ V5 Z' H+ ]' }
  66.         ET0 = 1;) C9 M& j+ y$ y9 ]2 Y4 d
  67.         // 允许全局中断' u% f2 u7 I! c5 e* x
  68.         EA = 1;
    + I) a( E: d4 Z5 F
  69. }
    . E/ p) |5 e  U5 M) z
  70. 4 W1 D, Z. v& r. s" x! y
  71. static void INT0_Isr() interrupt 0{1 S0 q# R: s8 `) I( Y4 k, f0 g# |
  72.         // 矩形波次数累计归零
    . Y) V4 k5 V* s
  73.         count = 0;' t. ?- p; D9 b3 y
  74.         // 重开定时器0中断
    7 ]# L% g7 u' o/ Y4 V( Q4 L3 T
  75.         ET0 = 1;$ J* f- l) S+ Z- _; f5 T
  76. }7 G1 [; t" s! S5 W
  77. 8 ~  a7 S7 C+ K5 T8 w9 b# z1 t1 Q, ], b
  78. static void Timer0_Isr() interrupt 1{9 P! d" X( a* m) [# F# w
  79.         // 输出矩形波
    8 B0 ~. K: {5 e0 L2 i+ A
  80.         OUT = ~OUT;% U+ P/ X0 K" `5 k$ @/ s( k
  81.         // 累计矩形波次数+ v2 Q- S3 P2 D* U& U) R
  82.         count++;; p5 }7 v" F5 n9 g
  83.         // 超过250个矩形波,准备停机) [1 r: I% A  k
  84.         if(count > 250){1 q- z4 m1 J, N7 w9 N
  85.                 count = 0;
    - [% c% c# S% g- c" T' W
  86.                 isReadyToHalt = 1;
    6 {! X3 z* B9 M3 a4 h+ n6 T* r7 c
  87.         }
    ' Q$ O5 T. `. |4 g  E+ l" k
  88. }
    5 I1 e5 k/ Q4 ~9 v
  89. " u, L) Y+ w0 p  W- c6 E
  90. static void INT1_Isr() interrupt 2{7 W( q0 `( x& f2 V
  91.         // 矩形波次数累计归零
    . a8 {# b' n) C5 h: W/ K- Y2 d
  92.         count = 0;
    * o3 T. C( ^( S/ A
  93.         // 重开定时器0中断9 n- h& d5 f1 ]
  94.         ET0 = 1;
    : }- A) B/ o# @9 P
  95. }, j) _3 v; L% S& d5 [
  96. , `" [3 ~; G1 k6 W. }4 l; {. k9 M+ b4 `
  97. - i9 f* X5 c, Y+ {% z4 I2 ]
  98. void main(){- ^* r0 Z, y& S6 h  O
  99.         // 初始化P3和P5口
    8 V- F: L  h  Y! K
  100.         GPIO_Init();
    5 G1 F9 x" d4 a. e
  101.         // 初始化定时器0
    " }: N) i% l- r
  102.         Timer0_Init();
    6 e& ^6 v. b- J
  103.         // 初始化中断
    + F7 ?, a4 H/ q0 O8 e$ g, L
  104.         Interrupt_Init();
    5 [) [% w" V% q# @. \! I
  105.         & ~( N! m; ^% a( G
  106.         while(1){
    3 y$ m  {) C3 f8 g
  107.                 // 检测电量
    . n1 g" e6 \1 K) x% D0 U
  108.                 if(PCON & (1 << 5)){
    ' g/ |$ u  E- X
  109.                         // 如果电量低,低压指示灯亮
    $ h3 P0 N3 M: K" z0 _2 n7 j2 V
  110.                         LED = 0;8 i- P: B! P' y8 c9 G
  111.                         // 清电量检测硬件标志位
    / q/ z$ {$ M  k, O: I  O/ C
  112.                         PCON &= ~(1 << 5);
    9 |1 H% g, [9 ~4 f( n7 D$ {/ p
  113.                 }else{% [3 c; c; m! L
  114.                         // 电量正常,低压指示灯灭
    " R9 T3 `* _, l) ^- U+ Q1 C" D3 K) C- {8 o
  115.                         LED = 1;
    0 g& L8 ~* v& Y$ R* P
  116.                 }6 \! d1 I/ H, e. `. u2 @7 n" J" d
  117. 6 h7 ~  W. e' K* U7 j1 j5 L, e" W
  118.                 // 检测到停机标志* ^' F. T+ L6 j" q: K* k
  119.                 if(isReadyToHalt == 1){
    ! J0 c" O: Q# e$ Q% y4 A; P
  120.                         // 暂时关闭定时器0中断% v7 m; v* M, z  Y- r+ R
  121.                         ET0 = 0;$ n% @4 J$ Y" W- n
  122.                         // 停机之前先把矩形波输出脚置低电平,以方便INT0和INT1唤醒CPU
    + i; Q/ b3 O7 j( i. g
  123.                         OUT = 0;
    1 p+ |" E0 B: Z8 Z8 n
  124.                         // 停机之前先把低压指示灯灭掉,以省电
    % j% r3 a( N; z* C2 U4 F
  125.                         LED = 1;
    3 o; ?$ [: J! ?7 _) m+ v0 A1 ?$ x
  126.                         // 进入停机模式. P& h% ~0 E8 |. I! \
  127.                         PCON |= 0x02;
    ; P. X) ?$ p( Q$ q! U
  128.                         _nop_();
    % a( a4 `/ ?" u7 P
  129.                         _nop_();
    $ C  f' q6 ^0 H4 K
  130.                         _nop_();- H& D  O/ G0 e$ t9 }; x+ Q
  131.                         _nop_();% a/ e0 N" T  W+ a& P7 z
  132.                         // 唤醒,清标志位
    + n. f$ u4 c! |+ L0 G
  133.                         isReadyToHalt = 0;! u! y# R3 V2 b4 ~" K  x, `
  134.                         // 重开定时器0中断. P1 m' K8 |* t5 Q+ r
  135.                         ET0 = 1;3 y7 Z3 g1 w+ N6 x! M
  136.                 }
    , t' \% Y. O  d8 @
  137.         }
    # m( G, ~. n" w
  138. }) y1 r3 i; R! Z( D: }8 |* D
复制代码

- I  ]9 W7 u3 O/ f# t5 e硬件参数配置:
+ T( J2 Q, A) z) _) `( Y& }9 _6 v0 U) c8 a  V
! T' M: Z7 J6 f/ s
接收端:
' @6 ^8 {% m- `
  1. #include <INTRINS.H>
    ( h1 P, v' R" R2 g$ @
  2. #include "STC15W.h") [* [" @, V  R  G; s& J% L0 {

  3. ! H% @6 [7 G6 v! Y" z0 D1 K! N% M
  4. 8 D2 n5 h% @8 ^, n) S+ G
  5. /** x# N! j6 Y( e# D0 m) z
  6. ' j' }4 ~- e" M0 K7 M" T
  7. *---------------------------*2 ^1 b; [7 z# T/ A
  8. |1 (GPIO2)         \__/  (GPIO1)16|$ g1 X4 d% y! ?
  9. |                                                        |
    ( H$ N1 T( w* t2 G3 V& P; T
  10. |2 (GPIO3)                   (GPIO0)15|! N' h3 ~6 A( ~$ g' j0 ?
  11. |                                                        |
    , R+ G+ ~$ h1 N" N
  12. |3 (GPIO4)                                  14|
    ! [+ D) r6 ^: M
  13. |                                                        |
    / b6 @: X) }, b; K  p
  14. |4 (GPIO5)                        (DATA)13|* w9 d8 W. q1 L1 I5 R
  15. |                  STC15W204S                |
    3 {" }/ B( }" D6 \
  16. |5 (GPIO6)                   (LATCH)12|
    : w; u8 b/ u$ {" |% Q% q$ t
  17. |                                                        |
    9 f0 \' l5 {) U: r# F5 m
  18. |6 (VCC)                         (CLK)11|
    . u2 F1 o; h1 q6 x( X  t3 B
  19. |                                                          |
    & G% x- `" }' @  P" W# j3 M' B  I
  20. |7 (GPIO7)                         (TXD)10|5 ]+ S. b% M$ g& |$ n
  21. |                                                        |9 f8 C" j# d* K6 H8 J
  22. |8 (GND)                         (RXD) 9|
    1 p! C0 p% x6 h
  23. *---------------------------*8 R$ v2 A; N# S- r+ l2 i
  24. Fosc = 12MHz
    2 }, ]- W7 }7 N

  25. 7 |$ A& q# S$ c2 X4 ^. K$ m
  26. P1.0 -> 上( R; Q* S( V  e1 [: }0 x0 h# l9 `
  27. P1.1 -> 左
    : o; U" k$ x3 O( k2 Q# |  @/ h
  28. P1.2 -> 下; z7 F- t3 {6 I
  29. P1.3 -> 右
    8 W8 z' Y  Q: f3 Q
  30. P1.4 -> SEL
    ! `1 m# f. z/ T# n! _0 O. m
  31. P1.5 -> STA
    ! t4 ]0 c5 w  ]% c
  32. P5.4 -> B
    & H& x7 p2 L6 V
  33. P5.5 -> A; A+ }% x4 l+ |/ M* u; f

  34.   @! X3 s% U/ a. u0 y
  35. */3 T- \6 y7 Q+ M( o1 v: T1 z3 `$ R- u0 I

  36. ' t# f1 J6 o- p+ J" Y$ w/ x
  37. 4 \) w% s, p6 D4 n" b0 p
  38. sbit CLK        = P3^2;
    2 I, i2 R/ d  y% [
  39. sbit LATCH        = P3^3;
    & S5 v, e3 @5 V
  40. sbit DATA        = P3^6;
    # T$ b# M! Z( M) b
  41. 4 A+ I. e& m1 C9 i  }& Z* m
  42. bit isReady = 0;/ j& j& N9 m) g. C" J" b- H+ U
  43. static unsigned char key = 0;
    5 l# @7 D1 b) K5 A. Z4 J5 E
  44. static unsigned char buf = 0;        // 双缓冲。这个缓冲区保存从P1和P5组合而来的键值
    ) K) I# u' M) v
  45. static unsigned char bufReady = 0;        // 双缓冲。这个缓冲区保存上面那个缓冲区的备份- m* }4 o/ P6 v0 ?, w3 g
  46. static const unsigned char data mask[] = {0x80, 0x40, 0x10, 0x20, 0x01, 0x04, 0x02, 0x08};        // A B SELECT START UP DOWN LEFT RIGHT。为提升速度,这个表放到RAM中. p* h+ S: I* U* a
  47. static unsigned char idx = 0;
    9 Y9 z/ n1 f6 |+ M0 W

  48. 2 R$ C3 X& v: i6 V; ?1 p; i# x8 H$ O
  49. - ~6 }/ m$ r( [0 A$ _% ~, {0 m
  50. static void GPIO_Init(){( w- }9 B- I/ F  w# m, k; P
  51.         // P1口和P5口用于接收并行信号,全部初始化为准双向,依靠内部弱上拉输出高电平
    0 C& ^6 u) k2 |( e; N: _$ J! _) U
  52.         P1M0 = 0;
    3 v  M! e% e; X  d4 f: U
  53.         P1M1 = 0;& ?# c, Q" `4 X1 l
  54.         P1= 0xFF;" S+ L, e' F: R9 f: n
  55.         P5M0 = 0;
    9 ~" S7 `2 D* F( j2 |
  56.         P5M1 = 0;0 d7 v" x4 X  |, G
  57.         P5= 0xFF;
    , d; t" b2 H3 {/ \4 x# {
  58.         // P3口初始化为准双向
    # y* E4 |" S$ s- y5 G% p
  59.         P3M0 = 0;
    3 S4 C  V" ^# l- y  q
  60.         P3M1 = 0;
    3 \, }. l& p- W2 d" z& A
  61.         P3 = 0xFF;
    : k+ O& m& b) D! @, O/ t
  62. }
    4 l/ b, g2 w5 ^# K

  63. ( J/ ?) h8 M. p1 N! d
  64. static void Interrupt_Init(){9 A4 z( e( m8 \# p  x2 R' z
  65.         // INT0中断(CLK)触发类型为上升沿+下降沿
    , B' A0 `$ j( d. j  k
  66.         IT0 = 0;
    . m4 @5 R2 Q6 p1 ^" u
  67.         // 允许INT0中断
      o* t$ `+ q/ }& @2 f" |
  68.         EX0 = 1;5 M6 c9 R2 v5 S/ F' u' v7 H7 {
  69.         // INT1中断(LATCH)触发类型为上升沿+下降沿
    9 Q0 ^3 k: p& A5 |$ L( J1 E
  70.         IT1 = 0;& r! o4 V; W, E0 M  R$ y, _
  71.         // 允许INT1中断
    # y$ M1 T4 z6 m0 _! q0 X) B
  72.         EX1 = 1;
    ( A: o" r% s+ k; g( S2 ~
  73.         // 开启全局中断
    5 O8 L, C) w7 f' \+ R. X! y0 r7 r" r, ^$ ?
  74.         EA = 1;& J% {% e6 _8 \2 ^
  75. }
    9 S' D2 }7 ?. b' p
  76. # B! K) M( [* q, G7 F- |
  77. static void INT0_Isr() interrupt 0{. b' ]: A) c' [; S* M
  78.         // 只有已经成功锁存才允许CLK移位& _, }: M( ~* q) `$ p3 d9 M
  79.         if(isReady == 0)9 ^+ D; ]1 H6 H0 u* m0 k
  80.                 return;
    & o  O$ f( @5 o2 N6 z
  81.         // 读当前引脚电平,如果是低电平则说明是下降沿,此时直接忽略该中断
    2 x) F' G% C+ a' |; I
  82.         if(CLK == 0)
    4 o3 i' x0 [, q0 Y1 q+ ]
  83.                 return;# a2 H+ F* ^, ]: ?4 g4 Q# ^: B
  84.         // CLK上升沿到来的时候,取锁存值的下一位输出
    / d( `  ?1 v, c% Y( O
  85.         idx++;
    3 ?3 \* u* ~: E0 ], [9 z3 h9 m7 w
  86.         DATA = key & mask[idx];
    + s( [: M+ e) u4 w/ H' |
  87.         // 如果已经完成7次移位,则一轮读取完成
      C- K' E% f, f2 K3 B2 `
  88.         if(idx >= 7)
    : L$ f0 o4 I( N8 \* b
  89.                 isReady = 0;# p5 P+ Y/ L$ O7 `  q$ Z; V
  90. }
    # b( l3 `1 j9 V, P* L
  91. " D% \& ?# b& n
  92. static void INT1_Isr() interrupt 2{
    ) `& Y/ o& g8 U+ D  `. o& W
  93.         // 读当前引脚电平,如果是低电平则说明是下降沿,此时直接忽略该中断
    ) \4 N' L4 {: l6 G( L  _
  94.         if(LATCH == 0)
    - k% ^* X* Y: m2 q/ x
  95.                 return;/ H: m+ L7 K- v3 N: \9 f$ U
  96.         // 当LATCH上升沿到来的时候,锁存所有按键状态,同时把键值A输出到DATA
    - Q: [' B6 W5 J* K( q" I
  97.         key = bufReady;
    & N0 \5 K$ x6 Q4 _7 B% o* y
  98.         DATA = key & 0x80;//mask[0];        // 为了加速运算,直接取表中的值而不是读表
    & M3 P  O( Y2 E- W" G- x* B2 e
  99.         idx = 0;0 m  a0 ^( w5 |- R0 K- K; [
  100.         // 允许CLK进行移位
    + ?) t8 E0 w# v2 I
  101.         isReady = 1;
    0 z, I! Y, B7 h+ T& C  Q
  102. }: d- T9 F: h$ y' w8 g. o- @0 d0 S
  103. + W5 u  ?% G+ d# r  C9 h
  104. void main(){
    3 D" y/ \% k7 W# J2 U% {1 z) l
  105.         GPIO_Init();6 r" g) [' z$ S7 C; G
  106.         Interrupt_Init();* o5 @0 u& c7 `  {, O
  107.        
    2 ~9 D+ z4 l5 n8 l: }
  108.         while(1){
    0 K& a" S' V5 V0 j2 B- r3 ], K
  109.                 //PCON |= 0x01;        // 进入省电模式! j( e1 W( T% x; ?5 g
  110.                 //_nop_();
    % @5 b, K" X* F; ?9 B
  111.                 //_nop_();* r' H- V- Q" J
  112.                 //_nop_();
    # ~6 _; ?5 X  E
  113.                 //_nop_();
    % P' n6 Z! F( c* s! O0 L
  114.                 buf = ~((P1 & 0x3F) | ((P5 << 2) & 0xC0));
    : ~( y* Q( Q7 u. e  O/ _' `
  115.                 bufReady = buf;1 O) Y+ v; b. T0 E+ O; u& ^$ k
  116.         }: E7 l2 ~5 R3 ]
  117. }
    ; T& U$ e1 O* s$ |; q/ f
复制代码

+ t0 a* r8 X& _+ O& d硬件参数配置无特殊要求,晶振频率选择12M即可。: p9 J) H" Q$ _+ ^6 _% M

: w0 Q+ G6 T. a  l$ m, E& K, W这是编译好的固件。

本帖子中包含更多资源

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

×

评分

参与人数 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/ W. y& d7 W% G) Z7 q  V# p! X, }( x
不错的设计,想问一下楼主,FC的15针公头怎么解决?普通的公头太短了,插不进去FC的扩展接口。 ...

/ v* H4 Q2 X- k1 w' t, h坛友的改造方案
回复

使用道具 举报

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

使用道具 举报

发表于 2019-5-25 12:07:18 | 显示全部楼层
精彩,楼主动手强,也写得很详细。
6 M+ h, Z, u1 m+ I5 m  b2.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
1 C( j- n+ t/ c精彩,楼主动手强,也写得很详细。/ C% V' h" \4 \
2.4G方案是目前无线的最低延迟吗?

: r' |9 ^3 m3 N, b9 T  @1 D我没用过其他无线手柄,所以实在不知道我自己做的这个手柄到底是不是最低延迟。
  n4 o& W" w- A5 f4 T# A9 j不过根据网上的说法,延迟高低主要是由通信协议的复杂程度,以及数据传输速率决定的。这个模块虽然是2.4G无线模块,但由于协议很简单,所以延迟比较低。
+ ^9 V1 d  P. P" Y7 N, k我用这个手柄玩一些ACT游戏,比如超级马里奥、忍者龙剑传、热血系列,完全感觉不到延迟,和游戏机自带的手柄没有任何区别。唯一的区别就是这个手柄是用火花山寨手柄改造的,外壳是垃圾回收塑料,粗糙+脆弱,导电橡胶弹性不佳,手感不是一般的差。
, q) U- b* @! Z, g! B我手里还有十几张板子,等我有空了我再做一套,到时候买一个好一点的手柄改造。
回复

使用道具 举报

 楼主| 发表于 2019-5-29 16:56:14 | 显示全部楼层
ppad 发表于 2019-5-28 17:27
: J+ G- Z" c9 v给技术帝赞一个,有半成品发布吗,自己焊接改造就可以,编程实在不会啊 ...
1 J7 z3 y/ _7 z* {1 b1 S
很可惜,我手里没有多余的单片机了,LDO也找不到了,锂电池以及充电模块更是没有了。反正就是该用到的元件基本都没了,所以没法发布半成品。4 T: L* i" R: \4 K( B' C/ d
两个板子倒是有十几张剩余。
5 @" G2 g" `2 l, X1 ^* }) U6 D. X你要是有USB转TTL串口板,完全可以自己买这两种单片机,然后我给你编译好的固件,你自己用串口板下载到单片机里面就行了。两个2.4G无线模块也得通过串口板用AT命令设置参数,不过好在我在设计电路的时候就已经预留好了串口,可以直接在线下载和在线设置参数。总的来说并不麻烦。
回复

使用道具 举报

 楼主| 发表于 2019-5-29 17:00:34 | 显示全部楼层
孙大师 发表于 2019-5-28 18:55
% Y8 l6 S: |) g# M, N5 e非常好,楼主是技术帝,到目前我都还没开发fc的无线套件,等空了,开发一套套件,等玩家自己组装。 ...

# `0 K. J" u' s/ @" m能得到孙大师的赞誉,不胜荣幸!
+ w" j- h' c' ~+ z- {( F; G) {2 u0 m不如开发一个多功能手柄,比如用SFC手柄改造,L/R键配合其他组合键可以用来切换2P~4P、调节连发速度、软重启等各种功能。接收端插到15PIN扩展口。
回复

使用道具 举报

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

本版积分规则

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

GMT+8, 2026-7-29 08:10 , Processed in 0.375814 second(s), 14 queries .

Powered by Discuz! X3.5

© 2001-2025 Discuz! Team.

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