找回密码
 注册

QQ登录

只需一步,快速开始

查看: 24848|回复: 32

自制FC无线手柄

  [复制链接]
发表于 2019-5-22 14:16:45 | 显示全部楼层 |阅读模式
本帖最后由 雷精灵2046 于 2019-6-14 09:28 编辑 : u' {! S& ^: s8 q* F
. `5 V4 F% t6 Q: w- }
没有用复杂的分立元件搭建发射接收电路,直接用的现成的2.4G无线模块jdy-40。
, L- E" Z& |$ f9 \/ e# ]
0 z: a: L$ |! Q- _5 f6 u3 y
- b$ d0 \; `$ r& F$ e, e: c$ v发射端靠3.7V锂电池供电,用了一片SOP8封装的STC单片机,负责产生连发脉冲,同时负责检测电池电量,电压低于3V左右的时候触发低压中断,低压指示LED就会亮起来告知该充电了。平时发射模块和单片机均处于睡眠状态,有按键按下才会唤醒,从而实现省电。实测睡眠状态下整机电流约1~2uA。板子洗了一下稍微干净了一点。因为对于微功耗设备来说,焊接残余的助焊剂可能会增加漏电流。3 U& ?3 ^% i' @8 O

, A" T9 k3 |% f# g: C买了一个火花的FC山寨手柄,去掉里面的牛屎板子,并修正一下塑料挡板,把锂电池和充电模块装进去。* S. F+ p8 {9 ]) Q& _" }3 M
为了减少体积,充电模块裁剪得十分小,并且更换了充电电阻使之适应这个小小的锂电池。这么小容量的电池,也不需要多么大的充电电流是吧?
- L. z# U7 T( l& f- @9 l然后统统用热熔胶粘上。充电电流比较小,所以发热很少,不会熔化热熔胶。' e; Z' D& ?! ^. ~
, {9 E. ^$ y7 o6 o0 t0 I

* j7 \# p. Q: U0 S6 e+ p, }- N! x% b
最后把按键、导电橡胶和电路板装上去。2 G( W  t! y6 T- _! z/ @9 s
精心裁剪了电路板,正好扣上,不会阻碍其他元件,也不会影响后盖和拧螺丝。
: l4 m+ E) C0 w3 }1 o7 {5 J5 O" M4 q; J- Z! |0 l% P
  w6 b' f7 [3 \- `4 [% i
完工!
3 L! @" j9 w1 N0 {% h& q( c, |8 M% }" L9 ^2 [

5 g5 f. Y! M5 R0 Q" V这是充电的MicroUSB插座。旁边的小孔用于透出低压报警LED的光线。
& P8 V8 \8 q) J, ?2 _) A( c. Q7 Z3 Z, T1 [* s
+ Q1 c; D3 p+ }  |7 k- l; R
接收端用一片DIP16封装的STC单片机模拟CD4021。为啥要用单片机模拟而不是直接用CD4021?因为jdy-40模块接收端在有按键按下的时候输出高电平,无按键按下输出低电平,和普通手柄正好相反。当然我也可以用两片74HC00或者74HC04之类的逻辑门进行反相,但那就增加了芯片的数量。对于FC手柄这种工作频率并不高的设备来说,STC单片机完全可以胜任模拟工作。9 c3 z$ R8 R7 Y# `

% {" s' V& x8 h; e( |6 A9 c4 K" b* q6 f/ C
8 E, e0 X/ c" n2 Q' ]$ y
电路设计有点小小的错误,所以有几根飞线。原本设计使用低压差LDO是XC6206,结果在做这个接收模块的时候,买的LDO居然找不到了!无奈只好用了AMS1117。幸好对于接收模块来说是5V降到3.3V,1117可以胜任。要是发射端手柄的话,3.7V降到3.3V,那就非得用6206不可了。
2 S6 B2 ~' n' f. R8 G& ~$ w% W9 @7 N' x' b% H% l
实测十分灵敏,延迟极小几乎感觉不出来。可惜这山寨手柄的手感并不佳,尤其是方向键,软塌塌的。看来我得买个剪线手柄改装。+ h0 \4 }% r, P% P" _/ R# t. ^
2 L4 ]+ z- N5 `7 W
这是电路图,有兴趣的朋友可以参考。
* Y/ |9 [6 P4 U' A
. f3 e' K# C/ |- X) y& o  ]4 G$ ?0 _4 x2 u8 _5 m
我信奉开源主义,十分痛恨把技术藏着掖着。好东西大家分享嘛!所以两个单片机的源代码大公开!
5 c: E4 Z: [4 N+ c/ E; X0 \3 d4 V编译器:Keil 51。
6 H( i( e( P" N$ U% N5 `% ?4 V
1 R% C, Q7 G) D" \- E发射端:* c* P4 i. u1 `5 N: O
  1. #include <INTRINS.H>0 o6 J0 I- {2 `" ]# Y- o: s
  2. #include "STC15W.h"
    ( |. i3 j# ?9 a& \* y
  3. . C: X* [& f& d* o8 \; c+ B

  4. + W/ S0 P' n5 n+ C1 u' z: S9 V7 B1 m
  5. /*
      U2 \1 B9 P( Q& y' c; c9 T2 \+ U
  6. --------------------------
    6 j  @! c4 t& s( E
  7. |1 (OUT)        \__/   (INT1) 8|
    . q+ K& e/ K9 ?5 p( y& s
  8. |                                                   |$ ~9 X) g# F, K4 I
  9. |2 (VCC)                   (INT0) 7|, f2 n0 ?# z, S0 a7 F8 E
  10. |                 STC15W204S                   |7 @, O/ \1 j5 w, W
  11. |3 (LED)                         (TXD) 6|
    + C2 T4 W: {3 l+ F" D
  12. |                                                   |
    ; W5 }! r7 M+ F; `6 X3 T
  13. |4 (GND)                         (RXD) 5|
    & h3 g2 H* B7 `  u. B
  14. --------------------------
    8 l  Y& X+ ~! |9 I& Q1 B6 F

  15. 4 V2 P2 V  `! O! ?) M" C) [
  16. LED ---|<|---[===]--- VCC
    . D% T% I: k5 A# S4 P
  17.            Red          330& a6 ?- C9 W8 P# T, u4 d

  18. 4 |& l& ?" ^/ B0 @
  19. Fosc = 6MHz: Z4 i; ^% a; ~+ [7 Q( S& y
  20. */3 l7 ?# a" ^/ q' h

  21. , H8 S3 {* ]6 P0 {
  22. 6 r* \+ Q0 s+ Z* a1 b" H5 v
  23. // 矩形波输出脚$ g6 f) x0 o/ t' q/ L
  24. sbit OUT = P5^4;
    9 @3 W! N/ m7 }, o; A8 ]
  25. // 低压指示灯引脚7 ~" Z) T; T: {/ a: M
  26. sbit LED = P5^5;
    $ ]1 ~/ K6 n) q7 C3 j( y. {9 r! B0 ^

  27. % @' K8 ?" z; w5 ]# {
  28. // 停机标志位
    0 m6 H7 g) z% j5 m6 W4 Q8 s9 B
  29. bit isReadyToHalt = 0;3 \! t: B( F; U+ Q6 u3 L' i4 k
  30. 5 P- I! y. A) k
  31. // 矩形波次数累计
    3 ^: [  r  G  f- ?
  32. static volatile unsigned char count = 0;
    6 l7 x- U. ~: L5 ?/ e7 |

  33. / r* S1 q! M) v% M

  34. : ]7 z9 c9 f7 ?# a  T) V
  35. static void GPIO_Init(){
    . b: F3 D+ _/ Q6 ^$ h' q
  36.         // P3口设置为准双向,默认靠内部弱上拉输出高电平
    + ]# ^2 R1 E7 Y! w" w4 p3 a
  37.         P3M0 = 0;
    7 A& {  `/ S( @8 N: N" P( |
  38.         P3M1 = 0;
    ! d8 E& `* u& S2 u, k( i
  39.         P3 = 0xFF;
    . B" k  A9 E0 t0 }) P0 `! `0 Y# Z' Z
  40.         // P5口设置为准双向,默认靠内部弱上拉输出高电平, y5 y9 ~% d0 G% n- P  [
  41.         P5M0 = 0;
    2 [7 q! a: m, ]% r6 L' P
  42.         P5M1 = 0;
    ( z9 M( s$ |" d# |
  43.         P5 = 0xFF;5 J1 x. B4 P- o5 W0 K
  44. }
    1 n* O1 P: }) z  V$ \: ?* E! X
  45. " [1 I1 I! r1 l, V0 f9 s, ^: Y  O1 k
  46. static void Timer0_Init(){
    - l& w+ U1 G# b. }
  47.         // 16毫秒@6.000MHz1 I9 U/ Y& w+ n8 X
  48.         AUXR &= 0x7F;        // 定时器时钟12T模式
    9 R0 o- `2 ~( \* \% U, j
  49.         TMOD &= 0xF0;        // 设置定时器模式
    ' ?& T- k$ V7 ?: }8 n7 ]2 \
  50.         TL0 = 0xC0;                // 设置定时初值9 t, f% S$ J, J1 \
  51.         TH0 = 0xE0;                // 设置定时初值
    ' B# N4 L0 y. }- q0 V$ w
  52.         TF0 = 0;                // 清除TF0标志
    - Q+ {( x% E# q1 d2 _( k
  53.         TR0 = 1;                // 定时器0开始计时
    3 ~/ A+ j, L$ C! k
  54. }
    7 J! \1 m) l* y$ E+ h: y/ b
  55. 3 H( U# j* P% p& Q3 Y
  56. static void Interrupt_Init(){
    ! Z! n) x. W( A/ H2 k9 ^$ w) O
  57.         // INT0中断触发类型为下降沿触发+ z; _4 z+ F9 N* @' b
  58.         IT0 = 1;# X* [; H' O" O: b" _
  59.         // 允许INT0中断
    + O$ F  o: y. e$ ]
  60.         EX0 = 1;
    ! `2 l, u: A0 h- e  g: ^  g; T) |
  61.         // INT1中断触发类型为下降沿触发1 G, Q2 b3 A8 h. I! ?! o9 G
  62.         IT1 = 1;
    9 I) x  d" w6 `3 ?$ [% A9 H( p
  63.         // 允许INT1中断! H6 u0 ~1 \" U" M
  64.         EX1 = 1;
    # [9 Z0 W+ y  Z
  65.         // 允许定时器0中断: o* f# P, n2 r+ b1 _, |. f0 r
  66.         ET0 = 1;
    6 N7 v/ Y+ ^5 Q& y2 h
  67.         // 允许全局中断
    - I4 A" F+ E& s! |
  68.         EA = 1;6 R6 ~) B( f3 y- y
  69. }
    ' I9 \' }9 y; j$ K
  70. 5 c- S7 L) p1 V9 I8 i
  71. static void INT0_Isr() interrupt 0{
    + N  j# Z1 W" Z4 C/ i. \/ J
  72.         // 矩形波次数累计归零0 X: d" Z, T  s9 O
  73.         count = 0;
    8 ~( r4 _! z$ ~; |6 U( e
  74.         // 重开定时器0中断. E) S0 M) M) Q- S! i
  75.         ET0 = 1;8 q9 J& D, D1 t2 i; ]0 F
  76. }
    9 [* b* Y. N  Z2 l5 j  ^

  77. & Z( ^& v1 T" p+ Z5 f% `! x
  78. static void Timer0_Isr() interrupt 1{
    9 N; \1 u7 T/ s) t
  79.         // 输出矩形波
    5 H4 z2 B: B7 ]0 p
  80.         OUT = ~OUT;$ p! W/ k. U, v
  81.         // 累计矩形波次数4 {2 T# }; B# w/ ~
  82.         count++;
    9 ^0 R$ E/ Z$ i1 l8 y4 t
  83.         // 超过250个矩形波,准备停机
    % V9 h3 p* c& b8 T' m7 \1 a3 Q
  84.         if(count > 250){
      [- G# R& J' h: h" d& x2 t9 r
  85.                 count = 0;& K( @2 |" k9 W0 k, E
  86.                 isReadyToHalt = 1;. m3 ~( X+ J. K( q' Y
  87.         }/ O- `/ T5 I) j; M* O
  88. }
    - A* L/ I( T$ p5 P5 h2 ~) Q

  89. % c' }% s" v0 n6 y3 J; E
  90. static void INT1_Isr() interrupt 2{/ g2 c3 d7 r! S, I
  91.         // 矩形波次数累计归零; G3 e" d- ?4 h- Q* I3 Z7 ?# F
  92.         count = 0;
      z) U. B# v% A/ ^
  93.         // 重开定时器0中断: g( ~4 U) {/ M+ G1 D! ^1 K
  94.         ET0 = 1;8 {7 ]/ u! P! Z5 W6 N
  95. }
    $ |: e' G6 P  r! K' b& n
  96. " p9 d, R" p3 ?/ K7 I5 @" d3 P
  97. 5 u, p* E/ }2 e" M; \% t
  98. void main(){8 ]! a6 v7 {3 o! Q3 N- W) p
  99.         // 初始化P3和P5口4 k/ c2 \) {. M3 ^! w8 K3 _
  100.         GPIO_Init();+ w# P, b" L! Z' s  z) z( _
  101.         // 初始化定时器0# T! ]4 _' d- \( d
  102.         Timer0_Init();3 H3 F2 X8 J% j3 D
  103.         // 初始化中断+ Q; W& f0 K: ?5 `3 L
  104.         Interrupt_Init();5 L0 Q, z6 z1 s- j* K
  105.        
    . I4 @- U' W# k% A4 B0 t
  106.         while(1){- K7 M# @0 n7 G' ]: D$ _# k0 Q
  107.                 // 检测电量
    6 g. C5 I0 n4 ?
  108.                 if(PCON & (1 << 5)){
    ! T& L+ Q* M0 q2 X
  109.                         // 如果电量低,低压指示灯亮1 f# u% P4 X6 ]) E/ q: V. l
  110.                         LED = 0;
    2 l0 T8 e; _$ B+ L, z' U3 `0 T
  111.                         // 清电量检测硬件标志位
    ) U3 q5 C& m; k, F. V% z% T
  112.                         PCON &= ~(1 << 5);/ b# Y2 E1 P& ]( w3 \
  113.                 }else{
      ~: \" O5 @8 ]9 {  Z) l$ G
  114.                         // 电量正常,低压指示灯灭+ W7 R1 v- @2 c# {5 e5 }: @
  115.                         LED = 1;
    . _" B9 P' C7 O! K& g/ x% g% M) Y; t
  116.                 }
    ( ^- x# I- }8 q9 U, ~' X

  117. : x+ O# H8 l( l& z8 H; ^5 K
  118.                 // 检测到停机标志; \8 Z( j# X. y' a. s7 b. L
  119.                 if(isReadyToHalt == 1){  @2 \- h+ N9 O: S0 E- g
  120.                         // 暂时关闭定时器0中断
    3 b# t# {( L1 {$ U* F! m
  121.                         ET0 = 0;7 P; Z: ^" q3 n, h
  122.                         // 停机之前先把矩形波输出脚置低电平,以方便INT0和INT1唤醒CPU6 B* B3 t+ \& v4 R4 V( _
  123.                         OUT = 0;' z; k1 {; [6 F8 U! r
  124.                         // 停机之前先把低压指示灯灭掉,以省电
    ! G: U) w2 c# g! I
  125.                         LED = 1;8 S% R6 Y. k0 `2 Y0 A. k3 S
  126.                         // 进入停机模式1 |  q/ I7 y0 e/ A/ \" z
  127.                         PCON |= 0x02;9 ~# j  z  W6 U6 S! L: K% l
  128.                         _nop_();' E5 x* k: Y* D3 R
  129.                         _nop_();) {8 X, x0 C3 Q! ^- P1 I
  130.                         _nop_();
    ( A" B) k. S' A: H, d. E  W5 t' Y
  131.                         _nop_();
    5 M* T7 _, q% b7 Z
  132.                         // 唤醒,清标志位, `( c! ~# ^. h7 e9 m
  133.                         isReadyToHalt = 0;
    ' [1 i  }: P/ M6 m8 U8 x9 u
  134.                         // 重开定时器0中断+ {- ]' h: a& ~! @
  135.                         ET0 = 1;2 E4 C3 [$ y% L
  136.                 }9 S: J) k; J5 c" `# b. p
  137.         }: S) J7 f- Z: l
  138. }
    3 @% Y+ A# j: b% ~8 t3 n
复制代码
2 e9 ]) P4 C% Q6 p% ], m
硬件参数配置:
7 }5 R5 h* T  {& y, i: s2 S1 L2 z1 ^+ ?" G

/ u. G1 q% b5 M9 X# m接收端:& |% a8 h# v; v. R" {% m5 ]$ n
  1. #include <INTRINS.H>
    1 X3 X* z  f6 S3 `$ Z5 o% x
  2. #include "STC15W.h") x' e( }" q5 ^' `( S. o
  3. 4 z6 M0 R7 c! b: q5 C" j* t
  4. 4 w, @) \: K# q& {& @
  5. /*
    ( I$ r  g6 M* o3 e1 s
  6. 1 Z! t/ v1 `1 t0 \  c3 n
  7. *---------------------------*4 c9 `( h/ ~& z% w) C
  8. |1 (GPIO2)         \__/  (GPIO1)16|
    4 J' a5 b- |" }& A! r! _1 ~/ Y4 I
  9. |                                                        |, F# U7 a( j9 t6 {: J& E9 S6 E
  10. |2 (GPIO3)                   (GPIO0)15|
    / R  r, _! \* m3 u! }; c# U, v" ?
  11. |                                                        |7 K* z! x3 o7 ?7 [; h8 [/ }
  12. |3 (GPIO4)                                  14|
    : T' b: y6 a  j! H
  13. |                                                        |' f3 n% I/ C0 ~1 W7 M8 o
  14. |4 (GPIO5)                        (DATA)13|# C5 h) l) |: u
  15. |                  STC15W204S                |/ S1 \8 ~" I- W7 q4 y& Z) ^
  16. |5 (GPIO6)                   (LATCH)12|
    , F! O/ \; [# i' b! _( w/ a# D% E
  17. |                                                        |8 T- c: t$ f9 K7 C, G
  18. |6 (VCC)                         (CLK)11|$ u% L7 f( v5 q+ n3 s+ s+ q
  19. |                                                          |) h0 Q  i& e5 o% s! l
  20. |7 (GPIO7)                         (TXD)10|
    # u" Z9 f( m+ f
  21. |                                                        |* B3 F6 M' L" o5 \% O" }5 w; X
  22. |8 (GND)                         (RXD) 9|" p) _: {* ?& g/ m4 ~
  23. *---------------------------*8 I; x2 T7 B( p" W: }
  24. Fosc = 12MHz, J1 x# H0 b5 y

  25. " {0 Y% v5 m/ i; c
  26. P1.0 -> 上) V+ i) Q* c- u; G, v* _
  27. P1.1 -> 左
    - f9 m0 ~. Z0 _' o
  28. P1.2 -> 下) M; M  Q4 l' M4 y  [* {8 d8 r
  29. P1.3 -> 右
    6 m) D1 G! M& y+ {, z
  30. P1.4 -> SEL3 j  c& o; ~. L- p# f& d6 X
  31. P1.5 -> STA
    . Z- p% g  o' r7 G9 @6 m
  32. P5.4 -> B* J3 t! P, L9 @* M* N' s2 Y! o
  33. P5.5 -> A, \/ d: S7 b! u% q3 `' F, ]

  34. ; K$ V, ?9 ^+ r# I" U: w
  35. */
    6 m  s2 g9 K! N4 [2 R

  36. ( o8 {5 W/ Z3 `4 t

  37. ' A& l, G6 K7 ^% z$ u
  38. sbit CLK        = P3^2;% l& w- k0 f. W$ S! {% V; p! h9 i
  39. sbit LATCH        = P3^3;% @& _  O' @  z5 ~: O
  40. sbit DATA        = P3^6;
    9 x" s, `6 C; q/ D0 H

  41. " p9 r& s3 F. R* \" Q
  42. bit isReady = 0;8 s! A2 G2 {' f" f) R) Z
  43. static unsigned char key = 0;
    " m# e; X& k: W
  44. static unsigned char buf = 0;        // 双缓冲。这个缓冲区保存从P1和P5组合而来的键值5 ]2 @* p( ^  T' T
  45. static unsigned char bufReady = 0;        // 双缓冲。这个缓冲区保存上面那个缓冲区的备份1 K5 _' P/ [0 |: P: i. q
  46. static const unsigned char data mask[] = {0x80, 0x40, 0x10, 0x20, 0x01, 0x04, 0x02, 0x08};        // A B SELECT START UP DOWN LEFT RIGHT。为提升速度,这个表放到RAM中
    # d% I( [0 ?: y: @
  47. static unsigned char idx = 0;
    " r: @: E2 }* f2 o% [

  48. 1 a; `* {1 L3 O+ n) k# ?% t

  49. * F5 m3 p, ^4 _6 P8 o8 x; R
  50. static void GPIO_Init(){2 x  {$ l3 A5 z7 K( w8 b
  51.         // P1口和P5口用于接收并行信号,全部初始化为准双向,依靠内部弱上拉输出高电平) E0 V" X$ ~: h- L- L* O9 T
  52.         P1M0 = 0;1 |' ?& \# x6 a
  53.         P1M1 = 0;. @/ j* q$ y9 S
  54.         P1= 0xFF;
    ( d; s5 r  f  ]$ f" \8 Z
  55.         P5M0 = 0;
    " L4 C+ Y9 }& i- R4 a. i  u. T1 X
  56.         P5M1 = 0;- {# b. W1 S" u2 o. X( \
  57.         P5= 0xFF;
    ) K# J2 N5 i& n& j$ N( P$ i
  58.         // P3口初始化为准双向
    7 u! L) g5 q# y" s  ]
  59.         P3M0 = 0;
    3 U+ W9 ~8 T+ @: e- Q% s
  60.         P3M1 = 0;' q- U- |+ J) r  u7 d
  61.         P3 = 0xFF;# _: N4 S+ t) S. M" O* b
  62. }
    1 Q' `* Q8 k0 S) w3 L8 E0 S
  63. % s5 f1 D! h# y% B3 ~) ~
  64. static void Interrupt_Init(){+ z) B5 [: w- g9 }% ?& g( L
  65.         // INT0中断(CLK)触发类型为上升沿+下降沿
    9 W& v, b( ~% `9 Z4 [' z  E1 f( T
  66.         IT0 = 0;; ?) P# [" }- ~/ Z5 q
  67.         // 允许INT0中断
    ( f; H; z; l6 u' E, O/ B
  68.         EX0 = 1;5 C) m6 J$ P& a/ t/ w! W/ [4 B% b
  69.         // INT1中断(LATCH)触发类型为上升沿+下降沿& S% F& a& x7 x
  70.         IT1 = 0;
    . B/ F8 t) |4 u% E' ]/ x8 Y. N0 @, M
  71.         // 允许INT1中断) Q: d. f8 Q- G
  72.         EX1 = 1;
    ! q, b% e# c6 X& `$ l, K
  73.         // 开启全局中断
    0 o+ q0 |9 T+ n7 ~8 a& g
  74.         EA = 1;
    ' k" o5 p& e. u' e
  75. }% \' R9 [" z; h) o
  76. - V' }( s/ D3 c6 q$ j0 p4 @: p
  77. static void INT0_Isr() interrupt 0{: O7 d/ D  ?. d3 x
  78.         // 只有已经成功锁存才允许CLK移位9 I6 |: q" i- A# z
  79.         if(isReady == 0)/ M' q7 i3 k1 h# ~$ d
  80.                 return;
    3 Z& H( r9 s, X9 U) `* d
  81.         // 读当前引脚电平,如果是低电平则说明是下降沿,此时直接忽略该中断
    # N& a, @, E( j/ w6 G$ x8 ^
  82.         if(CLK == 0)
    3 A( T8 c2 \: C5 y
  83.                 return;/ K4 Q$ X8 l% w& {
  84.         // CLK上升沿到来的时候,取锁存值的下一位输出
    , d2 H2 _1 t; R  O5 |- R
  85.         idx++;' J0 w8 N2 I" N% Q
  86.         DATA = key & mask[idx];
    - ~# t* k" p1 I6 l  l2 s" x6 C
  87.         // 如果已经完成7次移位,则一轮读取完成1 \4 J" I$ i* c4 i4 @, ?" \
  88.         if(idx >= 7)' b: Y" s+ J' I  }4 _2 M+ }
  89.                 isReady = 0;5 ~) f/ p( j4 K
  90. }8 i, L! a  p9 `$ {* Z

  91. 8 p, g8 r- g" z0 C3 C" I. p
  92. static void INT1_Isr() interrupt 2{) h6 |* T2 S/ l2 H. E# t! w
  93.         // 读当前引脚电平,如果是低电平则说明是下降沿,此时直接忽略该中断  n3 ?, o; \$ F
  94.         if(LATCH == 0)- s7 _% B- f" a; K- L
  95.                 return;
    0 w% p4 d7 ~; l8 {
  96.         // 当LATCH上升沿到来的时候,锁存所有按键状态,同时把键值A输出到DATA
    " n3 e2 ~& ?0 h0 ^; @1 n# h
  97.         key = bufReady;8 m' s- ?+ r$ H4 o; X0 C
  98.         DATA = key & 0x80;//mask[0];        // 为了加速运算,直接取表中的值而不是读表
    3 z; K7 v: I$ k/ j
  99.         idx = 0;
    ' U* y8 _7 N9 q9 H" i
  100.         // 允许CLK进行移位5 O/ P  T% t7 K6 H
  101.         isReady = 1;
    6 {+ S! f" B1 U1 L' a. Y
  102. }
    9 Q2 L2 Q1 @; {* {# v" n
  103. / v( o9 @: r) o. D
  104. void main(){4 F6 u! H6 S$ V0 e& e/ e* E
  105.         GPIO_Init();
    8 R$ r0 W( y3 F8 M( {
  106.         Interrupt_Init();
    ; [' f9 P* S( k4 M# F9 z
  107.        
    $ n( D: Q1 ?; V/ G! ?: s
  108.         while(1){
    ) k( q( _  e/ W" L" l' k
  109.                 //PCON |= 0x01;        // 进入省电模式! b$ k( ?8 h+ \1 q5 r% c) x* X2 h
  110.                 //_nop_();
    $ d8 Q4 Y5 K2 w) X) C2 d
  111.                 //_nop_();
    # u1 U) a5 ]9 {6 E* n
  112.                 //_nop_();; f# o% x2 f% L: |8 o
  113.                 //_nop_();  n1 e) W) p9 v' _
  114.                 buf = ~((P1 & 0x3F) | ((P5 << 2) & 0xC0));* H  P5 @0 Y' o& L1 m0 R+ E  X
  115.                 bufReady = buf;2 W# R/ I* h# j
  116.         }6 X7 j: n# |/ [! Y% V
  117. }
    4 L" ]5 L, x# I* L9 i9 R: Q
复制代码

- m/ J* M4 t  v7 X" K硬件参数配置无特殊要求,晶振频率选择12M即可。% _, y+ C  H' t( Q  u3 t

7 c8 R" r+ O7 T, 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
0 u6 }9 a; X9 d# x) z9 i不错的设计,想问一下楼主,FC的15针公头怎么解决?普通的公头太短了,插不进去FC的扩展接口。 ...
" c+ Z) |# P  Q! Q6 m
坛友的改造方案
回复

使用道具 举报

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

使用道具 举报

发表于 2019-5-25 12:07:18 | 显示全部楼层
精彩,楼主动手强,也写得很详细。
5 }+ H7 L, e% u2.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
% w6 Q. r( W8 h1 f精彩,楼主动手强,也写得很详细。
' G! J5 U7 v' ]  ^2.4G方案是目前无线的最低延迟吗?
9 W% p" }3 }0 @; w
我没用过其他无线手柄,所以实在不知道我自己做的这个手柄到底是不是最低延迟。
" s* A0 D" I# F. ?3 v5 ^$ h7 `, r不过根据网上的说法,延迟高低主要是由通信协议的复杂程度,以及数据传输速率决定的。这个模块虽然是2.4G无线模块,但由于协议很简单,所以延迟比较低。
2 L8 X5 O) @; L7 ~) N# U# q* b我用这个手柄玩一些ACT游戏,比如超级马里奥、忍者龙剑传、热血系列,完全感觉不到延迟,和游戏机自带的手柄没有任何区别。唯一的区别就是这个手柄是用火花山寨手柄改造的,外壳是垃圾回收塑料,粗糙+脆弱,导电橡胶弹性不佳,手感不是一般的差。
3 k0 _4 t' }+ ]; M我手里还有十几张板子,等我有空了我再做一套,到时候买一个好一点的手柄改造。
回复

使用道具 举报

 楼主| 发表于 2019-5-29 16:56:14 | 显示全部楼层
ppad 发表于 2019-5-28 17:27
* p4 P/ j. V. d/ q! {) L/ a9 ^2 e给技术帝赞一个,有半成品发布吗,自己焊接改造就可以,编程实在不会啊 ...

' \3 C! X" |0 g很可惜,我手里没有多余的单片机了,LDO也找不到了,锂电池以及充电模块更是没有了。反正就是该用到的元件基本都没了,所以没法发布半成品。; `/ k1 |! d' c2 U* @5 A
两个板子倒是有十几张剩余。
  q; A' v% n  {$ Q2 k你要是有USB转TTL串口板,完全可以自己买这两种单片机,然后我给你编译好的固件,你自己用串口板下载到单片机里面就行了。两个2.4G无线模块也得通过串口板用AT命令设置参数,不过好在我在设计电路的时候就已经预留好了串口,可以直接在线下载和在线设置参数。总的来说并不麻烦。
回复

使用道具 举报

 楼主| 发表于 2019-5-29 17:00:34 | 显示全部楼层
孙大师 发表于 2019-5-28 18:55
+ r0 N0 E+ I+ d& ]% O7 d2 E非常好,楼主是技术帝,到目前我都还没开发fc的无线套件,等空了,开发一套套件,等玩家自己组装。 ...

) I5 z( ?5 t+ c# X5 l% d. e. X1 Z  @能得到孙大师的赞誉,不胜荣幸!
$ C" X  m% ?7 \: q! y# A9 g# Q  F不如开发一个多功能手柄,比如用SFC手柄改造,L/R键配合其他组合键可以用来切换2P~4P、调节连发速度、软重启等各种功能。接收端插到15PIN扩展口。
回复

使用道具 举报

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

本版积分规则

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

GMT+8, 2026-5-6 19:51 , Processed in 0.104341 second(s), 15 queries .

Powered by Discuz! X3.5

© 2001-2025 Discuz! Team.

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