找回密码
 注册

QQ登录

只需一步,快速开始

查看: 25588|回复: 32

自制FC无线手柄

  [复制链接]
发表于 2019-5-22 14:16:45 | 显示全部楼层 |阅读模式
本帖最后由 雷精灵2046 于 2019-6-14 09:28 编辑
& m; n8 Q- k4 M$ X9 X! x+ P+ v+ g; s- }7 L" n
没有用复杂的分立元件搭建发射接收电路,直接用的现成的2.4G无线模块jdy-40。6 W% k2 s" v6 l2 k0 q
9 g/ Z$ |: l$ k7 N
+ L! }( {1 A/ a: z0 u" n
发射端靠3.7V锂电池供电,用了一片SOP8封装的STC单片机,负责产生连发脉冲,同时负责检测电池电量,电压低于3V左右的时候触发低压中断,低压指示LED就会亮起来告知该充电了。平时发射模块和单片机均处于睡眠状态,有按键按下才会唤醒,从而实现省电。实测睡眠状态下整机电流约1~2uA。板子洗了一下稍微干净了一点。因为对于微功耗设备来说,焊接残余的助焊剂可能会增加漏电流。
% B/ e3 f4 T* c% G; Y. }" l1 y% n2 s2 Z6 X
买了一个火花的FC山寨手柄,去掉里面的牛屎板子,并修正一下塑料挡板,把锂电池和充电模块装进去。! ^4 _* v, z: h4 R& y7 g
为了减少体积,充电模块裁剪得十分小,并且更换了充电电阻使之适应这个小小的锂电池。这么小容量的电池,也不需要多么大的充电电流是吧?+ U/ }4 X0 w2 f3 s4 J
然后统统用热熔胶粘上。充电电流比较小,所以发热很少,不会熔化热熔胶。: B  F3 b) }$ u. \+ T6 F

- s# c- ~+ u. g  x. l+ A
6 Q/ V, V- ]) J  a! s3 C! e! `6 `6 |' U3 o
最后把按键、导电橡胶和电路板装上去。
2 ?: t: `$ U8 X" T2 b7 p精心裁剪了电路板,正好扣上,不会阻碍其他元件,也不会影响后盖和拧螺丝。
6 f' o' R0 W; E( @8 a, y6 h9 ^6 n7 H

/ F, W$ ^; O* I. `$ k) X完工!
# V4 l  i" K; f; i' `7 z
4 P; I7 w+ \+ J) L3 b# M+ |: W4 Y- a8 L: V  @& W/ G
这是充电的MicroUSB插座。旁边的小孔用于透出低压报警LED的光线。
/ T" B$ L+ n! _* f4 l
$ x' w3 m& c  s$ K2 U3 A
& z' I, F  F/ g8 ^& Y, K接收端用一片DIP16封装的STC单片机模拟CD4021。为啥要用单片机模拟而不是直接用CD4021?因为jdy-40模块接收端在有按键按下的时候输出高电平,无按键按下输出低电平,和普通手柄正好相反。当然我也可以用两片74HC00或者74HC04之类的逻辑门进行反相,但那就增加了芯片的数量。对于FC手柄这种工作频率并不高的设备来说,STC单片机完全可以胜任模拟工作。' R. R! c, l# J/ S- @

6 D" Y* Q1 r- n. K* f# [6 X' c( K; Y" C5 ?+ t

  F& j9 o: r2 O/ _% ~8 u电路设计有点小小的错误,所以有几根飞线。原本设计使用低压差LDO是XC6206,结果在做这个接收模块的时候,买的LDO居然找不到了!无奈只好用了AMS1117。幸好对于接收模块来说是5V降到3.3V,1117可以胜任。要是发射端手柄的话,3.7V降到3.3V,那就非得用6206不可了。" s1 i8 B. H$ s
, F7 A0 p5 N  o7 b& ?
实测十分灵敏,延迟极小几乎感觉不出来。可惜这山寨手柄的手感并不佳,尤其是方向键,软塌塌的。看来我得买个剪线手柄改装。, i; H9 v0 g" x  w
$ u4 [" I. M( }, k0 z% _
这是电路图,有兴趣的朋友可以参考。
  R2 l( e7 F6 ?( U; v, V/ U. E
2 g7 i0 K5 }4 k. s, W
1 S/ [9 V( P- f* C" `3 r我信奉开源主义,十分痛恨把技术藏着掖着。好东西大家分享嘛!所以两个单片机的源代码大公开!. h- f( x& W4 E% p, D
编译器:Keil 51。: J& g+ a, T2 @0 [1 r1 f8 S

" o% n& e8 n- M0 Z4 E$ C$ P发射端:# K, c0 o3 F! u9 A6 H; u$ R2 A: A
  1. #include <INTRINS.H>
    , G" @7 L! w! m' t: B$ b  o
  2. #include "STC15W.h"
    ) a  A$ _1 a0 r* o

  3. 7 W+ s5 b1 E# u( r

  4. + E( Z9 m) j  V8 d! q% s' N
  5. /*8 Z# W& v( N; V, R
  6. --------------------------9 h7 \/ _. K! Z1 o  r
  7. |1 (OUT)        \__/   (INT1) 8|
    3 h. L9 |" C+ k# S4 v
  8. |                                                   |
    ) Z) H9 H: L, N0 Z: Y1 G* n* v
  9. |2 (VCC)                   (INT0) 7|0 E* u8 g9 h# S( K3 T) h; h
  10. |                 STC15W204S                   |
    8 Y8 O& P( n* H; w
  11. |3 (LED)                         (TXD) 6|
    ; e0 d8 o/ a) T' g3 \# @
  12. |                                                   |
    8 I+ J5 s" ?4 T! p( ?; F0 f2 U
  13. |4 (GND)                         (RXD) 5|
    " @9 }5 H7 U- Y# I. w& y- y5 g7 {3 r$ \& k
  14. --------------------------1 n8 G3 o0 Q; T: T  b

  15. ; T+ P/ \) E- Z; W# x
  16. LED ---|<|---[===]--- VCC
    9 J+ g7 y/ S/ x- T
  17.            Red          3302 j6 a5 l- z. C
  18. 7 J4 L2 W4 e, y* u
  19. Fosc = 6MHz& D! O! t3 e: O& M& E
  20. */
    , H9 B3 p0 K5 V. i. u& O
  21. ; @) D! g6 r1 |" a% y: H) o* R
  22. ( h0 y( G1 T' A
  23. // 矩形波输出脚* c8 E0 H/ S" U8 X1 H
  24. sbit OUT = P5^4;
      q. b) W! w; o2 w
  25. // 低压指示灯引脚
      O  v' A! P* U+ p9 U/ t
  26. sbit LED = P5^5;! F) g- i9 D7 Y5 m5 i

  27. ! Q+ T9 G* {1 [! I9 ]
  28. // 停机标志位
    7 Q1 w5 ~& z+ D. e
  29. bit isReadyToHalt = 0;9 \* s7 w) X: R' t
  30. 1 A7 y8 K2 d# G- \8 I$ f- g
  31. // 矩形波次数累计
    . }% ~4 u0 z7 d+ ?- y
  32. static volatile unsigned char count = 0;, Y5 }' Q& T) O) R4 C; g
  33. ; ?0 z' t, R( b: A7 v
  34. $ G. L/ U; p; S  L  |
  35. static void GPIO_Init(){& {0 D/ d4 P; X( L8 e; |
  36.         // P3口设置为准双向,默认靠内部弱上拉输出高电平
    1 [  J! e0 I' m# E7 {( u
  37.         P3M0 = 0;& i$ |* E0 r) N; S5 \# c
  38.         P3M1 = 0;: t4 ~# k# \  v* I
  39.         P3 = 0xFF;
    4 E9 g) X; f5 @, Y
  40.         // P5口设置为准双向,默认靠内部弱上拉输出高电平' b4 t% E2 I& U9 P. u/ p6 _  @  D
  41.         P5M0 = 0;
    , J" H3 B  l- `, l( M
  42.         P5M1 = 0;2 {3 Z8 h& n* }# c# e$ n
  43.         P5 = 0xFF;
      n/ w" L6 L% O' B& ?
  44. }
    # G/ n3 D9 l! ?' P8 R3 H; {
  45. - k2 g/ J( Z0 t/ I' e( R/ P
  46. static void Timer0_Init(){' p$ Z! D# g9 d4 {& T. U3 j) V6 T
  47.         // 16毫秒@6.000MHz
    0 ^1 s* B9 K, r' j) X' \; {
  48.         AUXR &= 0x7F;        // 定时器时钟12T模式
    6 |) E6 y3 v; T$ f/ d4 h( ?
  49.         TMOD &= 0xF0;        // 设置定时器模式& a8 X  [( X$ E/ U
  50.         TL0 = 0xC0;                // 设置定时初值
    4 i8 `) Q) R# u7 ?
  51.         TH0 = 0xE0;                // 设置定时初值9 f$ A1 v0 p4 T; F# H
  52.         TF0 = 0;                // 清除TF0标志, {, |! _6 P6 a2 a) N
  53.         TR0 = 1;                // 定时器0开始计时
    : J4 U# r9 A  u* ]
  54. }
    2 M1 J8 d9 x1 Z5 y% k, w5 d4 p* n4 U
  55. ' Q' Q; e* F3 Q3 ?; B) ]% f9 s1 O/ R& y
  56. static void Interrupt_Init(){' ~  K% P$ ^" o. b6 C1 j) N
  57.         // INT0中断触发类型为下降沿触发
    % m. u! W! Z  B& `
  58.         IT0 = 1;; k& _: n# ~/ {5 r, e3 {9 `
  59.         // 允许INT0中断, e, C& M, }7 P8 |: I; O
  60.         EX0 = 1;0 [7 v7 y" |" Q9 P
  61.         // INT1中断触发类型为下降沿触发" J, J  b3 f& ^1 B% d* y& g
  62.         IT1 = 1;
    , A- c( W  t. M$ v( o% r
  63.         // 允许INT1中断
    / n: q" i0 f0 _2 Q
  64.         EX1 = 1;: N2 J; Z- n3 t3 l7 l. H9 s, S9 V
  65.         // 允许定时器0中断
    8 b& F+ `: W% @9 g: [7 K. l
  66.         ET0 = 1;( r6 ?2 q7 {! E! F% L
  67.         // 允许全局中断1 u7 w/ n2 r+ v2 ]* B
  68.         EA = 1;5 C4 E0 H; V( j. J
  69. }( b9 J# H/ b# M+ f" _4 }! G
  70. ' E4 B' T& q! q3 M( B+ F& b
  71. static void INT0_Isr() interrupt 0{3 |, R; D, z$ U# u1 S
  72.         // 矩形波次数累计归零2 C9 K; k1 f. }  |
  73.         count = 0;9 b' h: \9 D# R/ Q8 g3 u$ L  w
  74.         // 重开定时器0中断, k" C( t. ?4 B4 T
  75.         ET0 = 1;, U/ g# K2 s' x& V6 S% z
  76. }$ B& H- R: U* }9 \1 F

  77. 5 ^, U5 x" R# k; G1 f: t2 g0 ?5 B
  78. static void Timer0_Isr() interrupt 1{( R* g! u: ^: I
  79.         // 输出矩形波
    & r+ v" Y' Z9 _% A
  80.         OUT = ~OUT;! K2 ?5 A& h/ }5 v$ W( L
  81.         // 累计矩形波次数+ c! a- B" K# M/ h
  82.         count++;
    3 e. V" z  z- p9 L6 O& B
  83.         // 超过250个矩形波,准备停机
    + P8 E2 u5 Q% Z/ s0 q
  84.         if(count > 250){
    $ T* d* c0 w. k" b" _4 `1 |* B- o
  85.                 count = 0;
    3 ~& V! B- J9 p, Q: m1 g/ x4 d3 H
  86.                 isReadyToHalt = 1;
    : Y0 D) k9 E$ i+ g1 K1 i  W
  87.         }
    ! |6 L) t& m+ [( G" ?0 v3 a% N' |
  88. }% W; B4 F/ R( N% u+ e& o4 m
  89. 0 {) O7 ]: E9 N% c5 a1 w1 W1 p- B
  90. static void INT1_Isr() interrupt 2{
    $ M& M' G% ]% b' M
  91.         // 矩形波次数累计归零. B+ ^4 p- X3 g# m6 b+ I) y& }1 X4 a! F
  92.         count = 0;
    # v" a; w. W8 w9 s
  93.         // 重开定时器0中断, D$ k" m# Q, K$ |& w" W- t3 H. m$ ?
  94.         ET0 = 1;5 A4 W1 \! f- d& q/ D/ I7 T
  95. }
    " _5 l, g6 ?" J2 `; [& B1 i. e
  96. % W0 t8 q: g# M0 y

  97. ; G  ?* e9 I' m
  98. void main(){
    5 ]5 S' G, {3 L3 \/ _0 j1 S
  99.         // 初始化P3和P5口3 t% Y  s" g- t. s' L
  100.         GPIO_Init();
    : s6 |% J1 l' t" `  J& o: q
  101.         // 初始化定时器0' A3 [6 H; t3 b7 k) I
  102.         Timer0_Init();, \# E. a; x9 @( r
  103.         // 初始化中断
    $ I8 p. ?$ A! g' b: F- @. X
  104.         Interrupt_Init();3 H; {2 y/ c- z) S2 u' G6 b% X+ X3 I
  105.        
    3 J1 z, K4 f+ C( m# H5 Y" N' v
  106.         while(1){: J3 R" r! O/ ]' B6 t
  107.                 // 检测电量% U+ _8 X/ [3 d5 S
  108.                 if(PCON & (1 << 5)){8 G' ~& c# W' ~* G: F0 _$ r
  109.                         // 如果电量低,低压指示灯亮
    * b( H4 w- V" o- M: R/ @7 l
  110.                         LED = 0;
    : d/ q6 m7 b9 {7 z! B( q
  111.                         // 清电量检测硬件标志位& g) g  J; J+ k
  112.                         PCON &= ~(1 << 5);% E6 W0 |, L0 J2 t) m" _4 r
  113.                 }else{6 G) Y- z- a7 J, Y0 F: I4 `
  114.                         // 电量正常,低压指示灯灭  T% ~9 x1 e. B& k% r
  115.                         LED = 1;
    5 g% G- \. m# `% U" P
  116.                 }+ G' W7 d# R: O' b- s: q  @9 T
  117.   |. X2 q; k7 _( P7 d! _" Z
  118.                 // 检测到停机标志
    # x8 V0 N6 N! A. i7 J* P# `
  119.                 if(isReadyToHalt == 1){+ j0 o0 y. B9 a6 ^
  120.                         // 暂时关闭定时器0中断
    8 c2 T7 d4 j: ]: p$ D7 U
  121.                         ET0 = 0;0 f% _2 U4 Y( P0 M: K
  122.                         // 停机之前先把矩形波输出脚置低电平,以方便INT0和INT1唤醒CPU
    3 _' V) C# c' X" i+ u( e
  123.                         OUT = 0;# i  b( k# e0 g# ]" B
  124.                         // 停机之前先把低压指示灯灭掉,以省电3 n5 I! h* S2 @+ Z! s8 a
  125.                         LED = 1;
    " v) O5 R* ~  W# b4 l7 a
  126.                         // 进入停机模式
    " z% W5 H. V9 \( _- d8 W- H
  127.                         PCON |= 0x02;0 v$ }& Y1 }. @8 o$ t3 s! D2 x
  128.                         _nop_();
    $ C( b# o1 S2 _2 {5 |4 c
  129.                         _nop_();) G6 e5 {0 z1 d/ O7 C# y
  130.                         _nop_();
    + h* X) }) q7 _5 a4 T! G
  131.                         _nop_();
    2 ~9 k. L/ O2 Y; b
  132.                         // 唤醒,清标志位
    8 m  {( j& d3 w4 k0 L
  133.                         isReadyToHalt = 0;
    / `8 e* _# I5 ^: l' G# ?
  134.                         // 重开定时器0中断
    ) x9 ]' w6 @( |" \# I7 r2 I* p* v6 R  r
  135.                         ET0 = 1;9 P+ U$ {7 F2 h9 \8 {
  136.                 }9 b0 p5 k/ I1 y6 G+ l9 P+ ~
  137.         }5 B, ^( j6 \7 K* J0 q/ C' K
  138. }% {1 o5 w. N  ~) m
复制代码

% X* I) K/ }3 q' d2 V' E硬件参数配置:
3 S' D, `, s- ]. `. Z3 F8 ]2 b
* o) @$ {; D. z1 p6 B  a8 ~5 R& R( I0 W  G
接收端:4 ]/ r, _3 O# i( O& q2 g
  1. #include <INTRINS.H>0 i% d0 T* ?$ h  M# N" x" w& O$ V
  2. #include "STC15W.h"& l* Z, A! F, a% H6 Y

  3. $ n! n0 [8 B) {$ v

  4. 6 D; j3 M0 l- l+ x
  5. /*
    - a/ A0 V" F8 C
  6. " r% m, D$ A; _( d6 b, h
  7. *---------------------------*7 k5 p$ v. C- _/ N# W4 n  ]
  8. |1 (GPIO2)         \__/  (GPIO1)16|" H- h% M% u+ U; p) u5 Z% @
  9. |                                                        |! ^+ ]# M8 \( X2 l
  10. |2 (GPIO3)                   (GPIO0)15|
    1 w  v$ X7 v7 U6 S6 W0 C9 S3 W
  11. |                                                        |6 ?/ j( i1 R8 j, N% l% n. y
  12. |3 (GPIO4)                                  14|
    + y2 V/ X- y7 O+ a6 [4 X
  13. |                                                        |7 {- Y9 @1 B0 v: V7 t# {
  14. |4 (GPIO5)                        (DATA)13|
    1 x% ~1 z  ~$ J5 B; C0 x
  15. |                  STC15W204S                |! e" a% A1 W2 e4 K
  16. |5 (GPIO6)                   (LATCH)12|
    , x* u: @5 N1 a4 Q! i+ g  f& K
  17. |                                                        |0 Y" {1 @/ m1 |8 [% m
  18. |6 (VCC)                         (CLK)11|
    . X4 `9 Y0 a& {6 a# x
  19. |                                                          |
    3 j$ r$ a5 d; y+ ^$ b7 l. j
  20. |7 (GPIO7)                         (TXD)10|
    2 B6 p) M7 k% p5 U' g  N+ N
  21. |                                                        |/ [& }* d! Z% X0 R% Y0 [- `
  22. |8 (GND)                         (RXD) 9|
    ! {: ^4 Z8 I+ z: ~6 E# L- `
  23. *---------------------------*
    2 [* \# g( p- K- I3 v2 f
  24. Fosc = 12MHz( L, [7 r, ]" j! |2 ]+ K

  25. 4 _! A. V/ C7 P- G/ ^0 j
  26. P1.0 -> 上
      H9 p* G/ H% w9 O# D. M
  27. P1.1 -> 左) J. {  p% ^. I+ J
  28. P1.2 -> 下
    5 _/ D& W9 h5 z+ E' x
  29. P1.3 -> 右, f% c7 }3 U$ R+ h: P* X! V4 ~9 S
  30. P1.4 -> SEL
    & f  T# z* r8 v/ z7 }9 L
  31. P1.5 -> STA
    - K2 N( U6 F9 @/ H5 U5 g7 P
  32. P5.4 -> B+ j4 Q+ p& b5 \+ x4 a' ]
  33. P5.5 -> A
    * T1 U2 Y* n2 [( D2 G( j

  34. : e% Y. T; b$ z* `! I
  35. */
    . q: L# a* \# G6 K( E. g& F
  36. 4 f1 Y( s; O; r# z2 A) P! ]

  37. ) z6 R! B: X$ ^! ~: Q+ `
  38. sbit CLK        = P3^2;
    6 Y1 D1 R5 h1 S
  39. sbit LATCH        = P3^3;
    * a$ W/ d7 R: B9 q
  40. sbit DATA        = P3^6;
    4 G. R- v2 o, M% O; e( _2 @' ?0 p2 X

  41. 5 z+ w. m" F. T- b
  42. bit isReady = 0;. e& W" e2 }9 j* I( n  o& J; I
  43. static unsigned char key = 0;, ]% Y; B& G3 Q' F/ {5 i4 s! T) O
  44. static unsigned char buf = 0;        // 双缓冲。这个缓冲区保存从P1和P5组合而来的键值. N+ y% v, p2 N4 ^! K8 c
  45. static unsigned char bufReady = 0;        // 双缓冲。这个缓冲区保存上面那个缓冲区的备份
    1 V( \1 {( I# a! U1 x) U
  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" M- |: {) ~2 c3 W/ u9 ^
  47. static unsigned char idx = 0;4 i  F; _" p; d; r% S. S
  48. , n- H* t/ E! a- B8 p0 v: ^
  49. 6 {* ]  I- Z6 G% v
  50. static void GPIO_Init(){
    . ^2 E( w3 z5 Z; E, k
  51.         // P1口和P5口用于接收并行信号,全部初始化为准双向,依靠内部弱上拉输出高电平+ D, }* L4 ?# Q) S" _  p. y5 v
  52.         P1M0 = 0;  R+ r0 y1 ^5 t
  53.         P1M1 = 0;
    . O0 B3 Q. B2 ~3 o8 F6 [
  54.         P1= 0xFF;
    . y, N* X; ~, {6 Y- G' h
  55.         P5M0 = 0;
    7 o+ v# E2 @7 `% N- o
  56.         P5M1 = 0;8 T$ f6 ^1 u1 x3 Q/ C# B
  57.         P5= 0xFF;
    ' [5 f* P- Y9 J, T4 a$ @' [' P
  58.         // P3口初始化为准双向: [$ W# H( A' P  B4 k" I
  59.         P3M0 = 0;
    3 T  `) @8 R! e6 P% a! ]
  60.         P3M1 = 0;
    2 O! f: |. t% f
  61.         P3 = 0xFF;
    2 U, `; t" n7 f% Q3 U$ c, ~* F
  62. }% g( K* y3 l7 ]1 M% ~

  63. " a0 N8 k5 l0 N$ X# r+ d) F' {* l
  64. static void Interrupt_Init(){6 Y2 H( H8 T# b( Y' @# u1 @4 M/ {
  65.         // INT0中断(CLK)触发类型为上升沿+下降沿
    % S5 R' J; C+ T+ ~7 L0 u5 p& a
  66.         IT0 = 0;/ q4 ]. ^4 a8 ~% z5 x& S
  67.         // 允许INT0中断
    : P1 h' h; [& q" O7 \: W6 [0 E
  68.         EX0 = 1;7 j( X  G9 D) R8 W* b
  69.         // INT1中断(LATCH)触发类型为上升沿+下降沿
    1 l* o* k! f) i* I3 m" {3 h
  70.         IT1 = 0;( ~1 ]* H; C0 F7 L
  71.         // 允许INT1中断+ ]* |- I$ r0 ]: W
  72.         EX1 = 1;" w' c/ ?' f) P8 n2 o
  73.         // 开启全局中断
    ; K3 H# v2 U0 i$ X
  74.         EA = 1;
    0 b6 p2 e; d* @' g1 Y1 _' b1 A/ o9 {) C
  75. }+ J  N% F& }* b% w& z) ~

  76. . v4 W3 t0 Y# |- v% m. d, U
  77. static void INT0_Isr() interrupt 0{& s5 t( e, a4 a& a1 b5 K% ]) W
  78.         // 只有已经成功锁存才允许CLK移位
    9 ^0 f( L: p9 S" w
  79.         if(isReady == 0)
    ! b- w" N2 K0 f( J( Y' l
  80.                 return;/ h) J8 m. N* `4 M0 _2 Y. h% a/ t
  81.         // 读当前引脚电平,如果是低电平则说明是下降沿,此时直接忽略该中断% I# O* V2 \3 Y" q( P
  82.         if(CLK == 0)' o* x! B1 j1 |% |8 `  ~
  83.                 return;
    7 p) A* t0 C0 T' i
  84.         // CLK上升沿到来的时候,取锁存值的下一位输出
    2 B: t, _8 L  @- |2 U& |+ c
  85.         idx++;
    : s4 U6 u0 A7 @2 n2 ~$ h8 ^2 m
  86.         DATA = key & mask[idx];
    " Q# L8 I/ x+ ^& f; A
  87.         // 如果已经完成7次移位,则一轮读取完成$ p" j5 @9 U  h" d' `' `
  88.         if(idx >= 7)' S% A& Y5 e" b) q; c
  89.                 isReady = 0;
    ) Z5 G7 ~  f+ f; h! e
  90. }1 h8 k: g4 p$ K( |+ U9 u0 P
  91. ) N3 _( i( r6 g
  92. static void INT1_Isr() interrupt 2{
    : |8 }4 m# ]/ K: \8 k0 R3 \* {, ^
  93.         // 读当前引脚电平,如果是低电平则说明是下降沿,此时直接忽略该中断6 \1 n  f! j( F* R2 q
  94.         if(LATCH == 0)/ P3 q& t$ X& ]1 Q) R
  95.                 return;/ u7 S4 h/ |% q
  96.         // 当LATCH上升沿到来的时候,锁存所有按键状态,同时把键值A输出到DATA  K3 b. ]3 S0 o4 k! x
  97.         key = bufReady;
    + U! {2 T# v8 D% n% Q0 q2 u0 o( N
  98.         DATA = key & 0x80;//mask[0];        // 为了加速运算,直接取表中的值而不是读表
    , Y) I# r" J- b9 ]  s  h
  99.         idx = 0;
    6 {' ]" H! V- i4 x
  100.         // 允许CLK进行移位! Z& k# N- p1 D1 F3 v
  101.         isReady = 1;! K8 W+ P# `3 W
  102. }9 ^1 g! V$ L- @5 k! @% \1 i
  103. " X+ H! Y( E; K" O! l
  104. void main(){) }) {) d+ |) u& V
  105.         GPIO_Init();1 q+ d4 F! J; w) f5 B6 @7 G
  106.         Interrupt_Init();
    . O- b$ i6 U' I, _2 G, S
  107.        
    " L4 Q* W- P+ a
  108.         while(1){
    1 z! E5 D& C0 f, B: Z4 [; h" I' j
  109.                 //PCON |= 0x01;        // 进入省电模式$ S6 q$ u2 r9 [, Q& h6 _
  110.                 //_nop_();
    " D8 F3 G7 s8 l$ |* g$ M
  111.                 //_nop_();
    9 P/ G& G0 y; D' p# x
  112.                 //_nop_();1 }, i0 h5 H4 i  d4 r5 d
  113.                 //_nop_();
    6 E/ @) k' J& M1 T4 `0 ~0 I' J
  114.                 buf = ~((P1 & 0x3F) | ((P5 << 2) & 0xC0));
    % b) k/ n" b- M# |: X
  115.                 bufReady = buf;
    ( L  w' A9 t0 x! P
  116.         }6 G1 v- `$ _' e) {9 `5 T
  117. }
    0 F9 P" a4 k% j& W4 G. P
复制代码

8 D2 R, I. R+ @7 {# @$ J* H0 y硬件参数配置无特殊要求,晶振频率选择12M即可。
7 P) w7 F* s8 S2 Y0 l3 Z: f
6 \' l  J: }( |$ E4 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
2 K' Q$ q1 c2 x& K不错的设计,想问一下楼主,FC的15针公头怎么解决?普通的公头太短了,插不进去FC的扩展接口。 ...
* J& `9 m" \) W( ~; I$ g
坛友的改造方案
回复

使用道具 举报

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

使用道具 举报

发表于 2019-5-25 12:07:18 | 显示全部楼层
精彩,楼主动手强,也写得很详细。
9 m8 ~- x! g( ]4 e) C8 Q2.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
; z4 G; D. u) L精彩,楼主动手强,也写得很详细。. @+ U7 `* v4 T8 k5 N2 v' u
2.4G方案是目前无线的最低延迟吗?
  k) ?& W- t- A, @
我没用过其他无线手柄,所以实在不知道我自己做的这个手柄到底是不是最低延迟。
- a! o) h9 \5 l9 u5 ]  f. Q不过根据网上的说法,延迟高低主要是由通信协议的复杂程度,以及数据传输速率决定的。这个模块虽然是2.4G无线模块,但由于协议很简单,所以延迟比较低。$ ^# e. c. f3 N/ Z. Q
我用这个手柄玩一些ACT游戏,比如超级马里奥、忍者龙剑传、热血系列,完全感觉不到延迟,和游戏机自带的手柄没有任何区别。唯一的区别就是这个手柄是用火花山寨手柄改造的,外壳是垃圾回收塑料,粗糙+脆弱,导电橡胶弹性不佳,手感不是一般的差。
3 \* V" G* a; W5 J& }' ^我手里还有十几张板子,等我有空了我再做一套,到时候买一个好一点的手柄改造。
回复

使用道具 举报

 楼主| 发表于 2019-5-29 16:56:14 | 显示全部楼层
ppad 发表于 2019-5-28 17:27! X; |" n) h* @$ t" s& w
给技术帝赞一个,有半成品发布吗,自己焊接改造就可以,编程实在不会啊 ...
6 h' x0 b. x8 Y9 Q4 S
很可惜,我手里没有多余的单片机了,LDO也找不到了,锂电池以及充电模块更是没有了。反正就是该用到的元件基本都没了,所以没法发布半成品。! w& o8 v* e2 l+ m
两个板子倒是有十几张剩余。( z- K* w  Q0 v
你要是有USB转TTL串口板,完全可以自己买这两种单片机,然后我给你编译好的固件,你自己用串口板下载到单片机里面就行了。两个2.4G无线模块也得通过串口板用AT命令设置参数,不过好在我在设计电路的时候就已经预留好了串口,可以直接在线下载和在线设置参数。总的来说并不麻烦。
回复

使用道具 举报

 楼主| 发表于 2019-5-29 17:00:34 | 显示全部楼层
孙大师 发表于 2019-5-28 18:551 a  t; V' ^, ^
非常好,楼主是技术帝,到目前我都还没开发fc的无线套件,等空了,开发一套套件,等玩家自己组装。 ...
  [- r0 j1 M" P  u7 @( v, b
能得到孙大师的赞誉,不胜荣幸!
1 c6 z6 z* \  f1 W4 w不如开发一个多功能手柄,比如用SFC手柄改造,L/R键配合其他组合键可以用来切换2P~4P、调节连发速度、软重启等各种功能。接收端插到15PIN扩展口。
回复

使用道具 举报

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

本版积分规则

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

GMT+8, 2026-6-29 08:50 , Processed in 0.095417 second(s), 14 queries .

Powered by Discuz! X3.5

© 2001-2025 Discuz! Team.

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