找回密码
 注册

QQ登录

只需一步,快速开始

查看: 26959|回复: 33

自制FC无线手柄

 荐 [复制链接]
发表于 2019-5-22 14:16:45 | 显示全部楼层 |阅读模式
本帖最后由 雷精灵2046 于 2019-6-14 09:28 编辑 1 N) l5 B  d  V1 g
; @: k1 @; a2 @! ]5 y( v  y6 M( c
没有用复杂的分立元件搭建发射接收电路,直接用的现成的2.4G无线模块jdy-40。2 T6 p9 x- \: g3 w) G
/ p4 Y! p5 s) M& @4 E8 [1 U! @
4 D4 Q, W/ r/ E3 P7 u& w: n
发射端靠3.7V锂电池供电,用了一片SOP8封装的STC单片机,负责产生连发脉冲,同时负责检测电池电量,电压低于3V左右的时候触发低压中断,低压指示LED就会亮起来告知该充电了。平时发射模块和单片机均处于睡眠状态,有按键按下才会唤醒,从而实现省电。实测睡眠状态下整机电流约1~2uA。板子洗了一下稍微干净了一点。因为对于微功耗设备来说,焊接残余的助焊剂可能会增加漏电流。8 _, Z- W4 o7 ?. t2 i5 h0 r7 _* T
. r( S/ U# ~. @7 F
买了一个火花的FC山寨手柄,去掉里面的牛屎板子,并修正一下塑料挡板,把锂电池和充电模块装进去。, \2 Y2 }# C' J) z( y' g3 ?: N
为了减少体积,充电模块裁剪得十分小,并且更换了充电电阻使之适应这个小小的锂电池。这么小容量的电池,也不需要多么大的充电电流是吧?. h1 D! t1 c, z% b7 U
然后统统用热熔胶粘上。充电电流比较小,所以发热很少,不会熔化热熔胶。' \% ]/ |- R. C2 u0 y& F$ E+ j

0 P6 x. K5 P4 x, Q$ i% a8 ?* G; D" T4 |% w: r, t

  l, @' F( I2 z0 o3 h最后把按键、导电橡胶和电路板装上去。
6 O+ ^, U/ b6 A' S' J, R精心裁剪了电路板,正好扣上,不会阻碍其他元件,也不会影响后盖和拧螺丝。6 D; z0 i7 B1 o2 ?
: j; j8 d6 f, v2 a0 C2 R$ D
- \& ]# m; J5 [: \- F
完工!5 o  v" u4 h# D5 ?& G* H* W
0 e- ~2 Q6 v/ l; S
) t$ [8 _5 [" a/ q& f
这是充电的MicroUSB插座。旁边的小孔用于透出低压报警LED的光线。
7 m3 O' b9 L, X* H, h
4 ^5 i  B4 P2 D9 _
. k" X, O8 A/ Z7 O7 V接收端用一片DIP16封装的STC单片机模拟CD4021。为啥要用单片机模拟而不是直接用CD4021?因为jdy-40模块接收端在有按键按下的时候输出高电平,无按键按下输出低电平,和普通手柄正好相反。当然我也可以用两片74HC00或者74HC04之类的逻辑门进行反相,但那就增加了芯片的数量。对于FC手柄这种工作频率并不高的设备来说,STC单片机完全可以胜任模拟工作。( M$ m# I; ~0 n1 N& p
/ G7 u1 i4 s. ]/ L' H
# a0 r/ I& I5 o: x3 E
, s% `3 f! Y1 a$ f
电路设计有点小小的错误,所以有几根飞线。原本设计使用低压差LDO是XC6206,结果在做这个接收模块的时候,买的LDO居然找不到了!无奈只好用了AMS1117。幸好对于接收模块来说是5V降到3.3V,1117可以胜任。要是发射端手柄的话,3.7V降到3.3V,那就非得用6206不可了。
" G& k5 G4 r3 l. I3 K% {6 R/ \! ?$ r# P7 [
实测十分灵敏,延迟极小几乎感觉不出来。可惜这山寨手柄的手感并不佳,尤其是方向键,软塌塌的。看来我得买个剪线手柄改装。1 T3 S% W5 x+ n) `" ^. R, H3 m( U

. E, c$ a6 v- y/ i! h- l这是电路图,有兴趣的朋友可以参考。' `# y5 Y' j3 }

% L4 b5 [9 `3 e, Q/ c% f
7 \  t& q9 m/ g8 l9 K2 s( T: h4 k我信奉开源主义,十分痛恨把技术藏着掖着。好东西大家分享嘛!所以两个单片机的源代码大公开!, s% R# T: y6 A- R
编译器:Keil 51。3 u0 o4 u& @3 i& r" k' F2 `! H

; j+ Z( s0 b: v! d发射端:0 n. r& L' }$ _9 ~" Q; K
  1. #include <INTRINS.H>" \5 g+ `; ~- @
  2. #include "STC15W.h"4 K, J/ Z# f$ z9 h8 }" _" g  m

  3. " {; K) y- ~( O8 x7 D9 U2 }
  4. - @9 n' s' i* \. i0 h. _
  5. /*
    ' N0 O- C2 u& S) ~8 f+ ]3 A* h
  6. --------------------------
    8 [- r0 X3 r8 F' J1 l0 i
  7. |1 (OUT)        \__/   (INT1) 8|4 p$ g0 N+ s2 _) q% F8 H0 S9 q0 G4 j
  8. |                                                   |
    6 P. \" {2 C, ?1 Q" [8 |: D
  9. |2 (VCC)                   (INT0) 7|1 E4 X3 h0 J: K# q
  10. |                 STC15W204S                   |  I0 Y! V! y  Q7 p3 x% @- V+ ]
  11. |3 (LED)                         (TXD) 6|7 C5 m" \. x) v/ T* G
  12. |                                                   |
    " F4 Q/ E% ]/ k9 z
  13. |4 (GND)                         (RXD) 5|; j- y; f3 Y6 K
  14. --------------------------
    - f! l6 P- [: p/ e0 a

  15. 3 k: {1 X6 s  x2 N
  16. LED ---|<|---[===]--- VCC
    6 F9 j0 o3 H6 o2 ~0 g
  17.            Red          3306 R- v( A( v* V8 y! ^5 Z) j8 w
  18. % z& V  d( W8 G4 o0 V5 \
  19. Fosc = 6MHz5 I7 b) Y: m  L* P& a4 Z6 w9 M
  20. */" C2 Q  r( G4 @9 L1 D  n8 ^6 ~

  21. 4 Q6 l1 F" U$ r! e' S7 ]+ e

  22. ! u  Y; Z3 Y# p) h6 F
  23. // 矩形波输出脚9 T2 Q4 c* g0 b3 ]  j2 B
  24. sbit OUT = P5^4;0 z7 C0 c3 r7 O( S
  25. // 低压指示灯引脚
      c1 j* @' W$ s9 d: \% v2 m( X( E* r
  26. sbit LED = P5^5;
    6 T; w4 d  w& R

  27. ( T% Y/ d0 R; Q, q! E
  28. // 停机标志位
    . [0 d( V+ f: F' ]  M9 H- P$ F
  29. bit isReadyToHalt = 0;6 Y' r. t" r" j; x' J2 q
  30. / t5 v" `# l, D2 ]2 I
  31. // 矩形波次数累计$ ?8 R. e9 b1 n  J3 q% P& x
  32. static volatile unsigned char count = 0;, e4 ?3 X4 C+ l1 l* e+ ]4 w3 k
  33. : j6 \5 [( Z- I4 d" p. u

  34. * z& [- h# t  n. I
  35. static void GPIO_Init(){% H' U$ e* ~  x7 X. `- }  y
  36.         // P3口设置为准双向,默认靠内部弱上拉输出高电平
    & d4 V3 ]/ @: g0 s; v8 u
  37.         P3M0 = 0;
    ; D& K: S4 E3 Z, J& I* }1 o
  38.         P3M1 = 0;  e- G) j& M* n7 y! H
  39.         P3 = 0xFF;, M" P4 p! q$ r9 Z9 Z  ?
  40.         // P5口设置为准双向,默认靠内部弱上拉输出高电平
    : @3 G; I" |. X9 K
  41.         P5M0 = 0;
    - F7 K7 ^  m4 e7 @( x+ j- _* v
  42.         P5M1 = 0;& ]+ Z+ o" x1 h- p# F
  43.         P5 = 0xFF;
    9 c* U  y+ I- y, q  M
  44. }
    $ I* D* u6 q  k( N
  45. " ^- ~! \) j1 O( X, I* D) m
  46. static void Timer0_Init(){! C: N" ?! s0 U+ Y6 i& n8 z- O2 T
  47.         // 16毫秒@6.000MHz  K4 X+ p  m) c$ P  @
  48.         AUXR &= 0x7F;        // 定时器时钟12T模式
    ! B  m# d4 @( b7 p
  49.         TMOD &= 0xF0;        // 设置定时器模式3 N! u& n$ g" o+ D" E* [; j6 h
  50.         TL0 = 0xC0;                // 设置定时初值4 `# w* `2 u, T# m. Y
  51.         TH0 = 0xE0;                // 设置定时初值4 Q$ j* y1 ~; ]0 r% |, B8 n9 T
  52.         TF0 = 0;                // 清除TF0标志# a+ n9 M' ^1 E$ D! [; }2 ]- ?
  53.         TR0 = 1;                // 定时器0开始计时2 l$ D* F8 a+ z) l0 a- Y8 h' h
  54. }
    $ }- m: ^7 s5 {+ l! l& J/ h
  55. / H8 e$ i4 \% I6 L: z, K7 N! n
  56. static void Interrupt_Init(){7 Z# |' c; M. L. }+ I
  57.         // INT0中断触发类型为下降沿触发
    5 y+ W; c$ S  B6 ^) Q4 ]
  58.         IT0 = 1;
    * m" ^+ a  {3 `" S# u7 b4 Q! h! b
  59.         // 允许INT0中断
    4 I, S+ b: b; ?8 ^* t! d- ^1 o
  60.         EX0 = 1;( h5 [8 \. v$ u
  61.         // INT1中断触发类型为下降沿触发
    & p0 k& W) |9 f& N& `. q
  62.         IT1 = 1;, J5 z+ |- A4 I# {
  63.         // 允许INT1中断
    ( o2 x1 ]' j  U0 l
  64.         EX1 = 1;
    3 {4 w* s6 O- G7 D+ W# V$ I! A
  65.         // 允许定时器0中断
    : y: V4 T$ Q% D$ y. V
  66.         ET0 = 1;1 \% P9 F& [5 J+ q& f
  67.         // 允许全局中断
    % U& `# \0 z1 s2 y" ]) r
  68.         EA = 1;
    8 G! U% m1 H$ H9 b9 ]/ y  z. I1 x
  69. }7 G8 z! o2 @/ W
  70. ! \' n! k4 k, C1 }; i
  71. static void INT0_Isr() interrupt 0{
    : J% Z/ G" z% M2 T! |+ P8 i
  72.         // 矩形波次数累计归零
    9 t6 F, c  B( R
  73.         count = 0;
    . H" D1 K' Z$ g2 }- J) j# u8 k# z
  74.         // 重开定时器0中断
    / U. k4 K+ Q( E: x& f# m; i) @
  75.         ET0 = 1;1 [0 P  _4 Y" D" Y! f0 u& \
  76. }
    # |5 x9 }8 `2 Y! G1 h

  77. 3 z2 @2 o, V) I# `
  78. static void Timer0_Isr() interrupt 1{2 Q8 v$ ?8 I# {7 N5 @
  79.         // 输出矩形波
    : D/ J! s; d9 `% R) J. u2 o
  80.         OUT = ~OUT;
    / ~: t9 \- I6 V" M. V
  81.         // 累计矩形波次数
    4 f, q- w$ C: R9 \  t0 A
  82.         count++;8 a7 X. A  h1 A( j- y2 z8 C# i) ~
  83.         // 超过250个矩形波,准备停机" g7 O, U1 a7 }' C. `2 A
  84.         if(count > 250){
    $ |- @  t: A# z' }5 L; }
  85.                 count = 0;# v* F4 r* `# C+ A7 L
  86.                 isReadyToHalt = 1;
    ! }$ h- W/ g% x5 l4 w
  87.         }( o" s: v9 [- q
  88. }% D8 {' s) U, @5 Q2 T

  89. 0 d6 f8 M/ Y, r5 u, m- d
  90. static void INT1_Isr() interrupt 2{9 t9 y8 A: U: W( i+ G& U
  91.         // 矩形波次数累计归零6 Q5 M9 X" k# b# e
  92.         count = 0;
    , ^5 q4 B& \# @# j7 }% B
  93.         // 重开定时器0中断7 i4 Z0 s" W8 M
  94.         ET0 = 1;
    1 Q/ h8 Q5 Z1 K/ ?0 b
  95. }  l9 x1 L+ i  ]9 h* m) D6 e1 ]: A

  96. ! S1 g! k7 H; |, d) R. r
  97. 2 E, K$ j, O' G( N
  98. void main(){
    % ?0 `* \; c1 F- X* f. s' T3 i
  99.         // 初始化P3和P5口
    ; k0 T) q8 \6 i$ f
  100.         GPIO_Init();( e* V+ ^% Y8 t2 @2 J+ B: D3 C
  101.         // 初始化定时器0$ I& p; ~  e% O* Y; e) X
  102.         Timer0_Init();
    ) a& M+ F7 \. m3 T0 N: s
  103.         // 初始化中断
      F3 ^7 k6 X# m$ m7 u* j4 g
  104.         Interrupt_Init();9 Z# b2 D6 ]6 N
  105.        
    + U9 t5 i2 K' Q: S5 `4 T
  106.         while(1){, l5 E2 l' f5 H1 ?' ?1 o: J
  107.                 // 检测电量* d" I! I' `* l( i5 v
  108.                 if(PCON & (1 << 5)){1 y& T4 G/ I3 v* c
  109.                         // 如果电量低,低压指示灯亮
      L1 g# k: N3 J" `* ?
  110.                         LED = 0;
    ( ]& z$ ]6 K0 A7 T
  111.                         // 清电量检测硬件标志位* K, w1 d! B, _  R, X+ H! e6 l; Q
  112.                         PCON &= ~(1 << 5);
    2 U2 L+ ]* V7 e. U4 q+ B) O# ~
  113.                 }else{
    ' ~7 ?/ X/ G7 ^- c
  114.                         // 电量正常,低压指示灯灭" ^" @9 c% }/ P6 Y2 T
  115.                         LED = 1;
    5 M: ~3 {  X% u1 u3 Y- H
  116.                 }
    ! e/ Z- S6 D9 f+ F; X4 _5 O

  117. , o8 J5 b* x9 F. M
  118.                 // 检测到停机标志/ [! O9 E- U( O( w9 E; L
  119.                 if(isReadyToHalt == 1){" {9 w) K; o5 V, M
  120.                         // 暂时关闭定时器0中断
    6 {! O: g" R& h' R; r- V
  121.                         ET0 = 0;
    8 }  I; |; \6 Y# G/ g
  122.                         // 停机之前先把矩形波输出脚置低电平,以方便INT0和INT1唤醒CPU
    + `7 L0 m* F, H2 l% R
  123.                         OUT = 0;
    ' W2 [4 m) j8 j8 v0 d. I- O6 h
  124.                         // 停机之前先把低压指示灯灭掉,以省电
    ; w% t1 e% x5 j! y# w0 n: {
  125.                         LED = 1;' q4 c- \* e2 `' h3 W8 u  {& T" F
  126.                         // 进入停机模式+ K) k. [; i. i6 \) g& T  S3 b
  127.                         PCON |= 0x02;
    & S. E% l) M/ @. G4 ^
  128.                         _nop_();
    * O- A( Q; Q9 @, Y8 H# E3 f9 k. ]  J$ @
  129.                         _nop_();
    # M1 |, j: l- d, R7 J2 {& i
  130.                         _nop_();1 K% Q( F( o% N8 d3 C0 N
  131.                         _nop_();
    4 k# ~2 X5 L9 b5 |: B5 \
  132.                         // 唤醒,清标志位5 c4 Z& ~7 u5 ?' m
  133.                         isReadyToHalt = 0;
    - {) N3 H1 ^' F! A1 i% e- `8 u9 ^7 }3 @
  134.                         // 重开定时器0中断. }, ?, ]' |7 i5 n& C, B
  135.                         ET0 = 1;3 |- k" W& f# \4 e& U; P$ s- u
  136.                 }  f- }/ b" F3 T( L
  137.         }2 a& B5 P3 B) j0 v8 y
  138. }
    9 I6 y: M$ g$ Q9 i% ?4 I3 o. ?
复制代码

' ]/ Y' W  C1 f5 k硬件参数配置:1 C) v3 \9 o% K

6 i0 P4 v: n& }# t
1 f" \% @$ c; m接收端:
- K' l" l, v, Z* T1 O! }
  1. #include <INTRINS.H>
    : u5 w) {- {( X9 d; Y+ |& a; A
  2. #include "STC15W.h"
    + x$ o1 t/ J. v1 l" W5 |; ?/ a% ?

  3. 7 ]7 o5 r  l3 ?  B1 i5 z! [
  4. : b7 ~% d6 U0 b; E- Q$ ]& C
  5. /*
    ! o$ Q" k6 x  P7 ~+ O- N9 [$ B
  6. 1 a2 Z& t2 k! {" x
  7. *---------------------------*
    2 Y' |8 G; h$ i' h8 r+ w$ l9 Q
  8. |1 (GPIO2)         \__/  (GPIO1)16|7 q* b* x/ b5 S2 l7 E9 Z
  9. |                                                        |
    0 g& W8 V: x3 U
  10. |2 (GPIO3)                   (GPIO0)15|
    ; ?4 V% j2 M& t" t  J& t
  11. |                                                        |2 N+ d/ V  s4 c' o$ w
  12. |3 (GPIO4)                                  14|
    . e, C+ [# n. Y2 x" @
  13. |                                                        |
    . H4 x4 J* c; ?8 \! v! P
  14. |4 (GPIO5)                        (DATA)13|
    5 Q; M  G& _, {5 v9 C  F
  15. |                  STC15W204S                |
    / B8 J9 F9 X( q0 Y
  16. |5 (GPIO6)                   (LATCH)12|
    , x" [& T5 X" S- A+ k3 _, [# c' k
  17. |                                                        |/ Q( [+ Z2 m6 J: C' G1 y2 ~
  18. |6 (VCC)                         (CLK)11|5 ~/ K1 Z, x+ U% a
  19. |                                                          |
    / w5 S; G+ `9 L7 N  u
  20. |7 (GPIO7)                         (TXD)10|
      {2 A9 i3 u0 M; e- ?4 c
  21. |                                                        |: R/ i8 j: X, ]  L# H
  22. |8 (GND)                         (RXD) 9|
    , o; M2 K& K4 L4 l1 g
  23. *---------------------------*
      d7 }# k! x3 f& B
  24. Fosc = 12MHz
    5 l; m' V) [& o
  25. & Z& |' K9 a* h/ P2 K$ I
  26. P1.0 -> 上
    ) Z! K: e0 s2 P+ b3 s! u4 p; h
  27. P1.1 -> 左
      w0 m& l1 G( L. ]/ L, t# F8 v5 x
  28. P1.2 -> 下" R4 Q; P8 [. W& @3 G
  29. P1.3 -> 右# }$ Z! @; V( l9 _5 P
  30. P1.4 -> SEL
    / |7 p9 a0 a8 ?5 S" L& T; |& H+ D
  31. P1.5 -> STA
    2 E7 D) L6 o5 C
  32. P5.4 -> B' f* J7 _. r) @
  33. P5.5 -> A
    3 ?7 E5 L; t9 s

  34. 0 _0 O: }; S/ U' n
  35. */
    5 Q* ^% \; l4 [0 o7 O& o+ q9 Q' O

  36. 0 [6 m+ X# ^4 A
  37. & Z$ [" }: q1 m- y# X
  38. sbit CLK        = P3^2;
    % n3 z/ @+ f5 A6 Z4 d1 q# ?
  39. sbit LATCH        = P3^3;
    2 X, I9 @$ l# D, R1 L4 X9 O
  40. sbit DATA        = P3^6;* ~& o3 e+ s$ X' `! D

  41. 8 W5 \* ~3 K8 ~+ b; G% s! U
  42. bit isReady = 0;- X. h2 Q+ I2 C3 j+ b; z* I& u
  43. static unsigned char key = 0;
    . m2 B& Z, U- O9 C
  44. static unsigned char buf = 0;        // 双缓冲。这个缓冲区保存从P1和P5组合而来的键值6 `3 h' Y  E" g2 N) E" P
  45. static unsigned char bufReady = 0;        // 双缓冲。这个缓冲区保存上面那个缓冲区的备份* {1 e7 d% G9 @. z$ ^
  46. static const unsigned char data mask[] = {0x80, 0x40, 0x10, 0x20, 0x01, 0x04, 0x02, 0x08};        // A B SELECT START UP DOWN LEFT RIGHT。为提升速度,这个表放到RAM中' Q: M$ r; N9 U8 R
  47. static unsigned char idx = 0;- u( a0 H2 w" E+ n% p& t
  48. # w; u  e* U: o5 S; c& `

  49. . y- N, j; E4 i3 E
  50. static void GPIO_Init(){
    , o% W, O8 U$ b/ u/ o% n2 y
  51.         // P1口和P5口用于接收并行信号,全部初始化为准双向,依靠内部弱上拉输出高电平
    ; v, n  M+ P" {: O
  52.         P1M0 = 0;
    6 `6 Q: L' G$ r0 K+ q# F+ |
  53.         P1M1 = 0;0 |( e8 p' f& }0 l3 J# ~
  54.         P1= 0xFF;5 G3 d  E+ W* q% D+ \/ C$ K) z6 c
  55.         P5M0 = 0;& U+ d: j6 a1 ]- `, E5 Q/ \3 i! [; X
  56.         P5M1 = 0;
    9 F+ B& ~7 u2 T! D. s! B7 j
  57.         P5= 0xFF;6 [* n& E4 @1 g3 |. Q) \& J8 E
  58.         // P3口初始化为准双向
    + ~# \1 e4 l( Y0 g% B* V4 n( y
  59.         P3M0 = 0;
    * M  C7 T" Z# p* n
  60.         P3M1 = 0;) r3 ?; w" U- D0 ?
  61.         P3 = 0xFF;
    4 k& O/ {' `$ ~- A& w/ t
  62. }& K! ]. Y# t3 i/ y$ b
  63. ) P+ Y1 [3 T; I: {( \) g
  64. static void Interrupt_Init(){
    ; r7 v% t. \% J# `0 e7 x) H! Q
  65.         // INT0中断(CLK)触发类型为上升沿+下降沿
    7 Y( G2 p4 T% r: r' ~* O  n- ~5 E
  66.         IT0 = 0;4 w7 `+ Z; b6 X1 F# y0 U
  67.         // 允许INT0中断. I: Z/ F  W! `8 F
  68.         EX0 = 1;4 I7 T( _; o6 b. b7 f
  69.         // INT1中断(LATCH)触发类型为上升沿+下降沿! Q) U5 C& O, j2 \2 ]# t6 y
  70.         IT1 = 0;
    : [- N6 O' b7 F0 H
  71.         // 允许INT1中断' \2 ?, N: H7 h3 u2 ]' R# ?: C
  72.         EX1 = 1;# ^/ `! |% X6 n, _% H4 V* c
  73.         // 开启全局中断+ ^- m& `9 O; _, ~
  74.         EA = 1;5 f6 o7 L5 |# k" q% d
  75. }  I; O# \6 k% \/ r1 q, D! G
  76. + I2 j7 _% B; B0 F8 X
  77. static void INT0_Isr() interrupt 0{
    # o9 V0 {6 f: q# q+ ^9 W9 C, ?0 A
  78.         // 只有已经成功锁存才允许CLK移位# A) C) i) a# [* H5 W
  79.         if(isReady == 0)
    4 X4 C* R/ e, ]& U: G0 A
  80.                 return;
    - g( ~1 ^4 Y- }. _3 o* L
  81.         // 读当前引脚电平,如果是低电平则说明是下降沿,此时直接忽略该中断. G/ V" a) I/ U5 V
  82.         if(CLK == 0)
    3 O9 v9 K9 s) ^% k8 |# ~8 `& W0 ]5 t
  83.                 return;
      Z. S) y9 k; I3 p5 z
  84.         // CLK上升沿到来的时候,取锁存值的下一位输出
    # U  I5 ^  M5 t" D! W5 E. a1 c( W( ^
  85.         idx++;
    % e# ]* d* W& k: {
  86.         DATA = key & mask[idx];
    , j9 M7 f4 ~9 q  h
  87.         // 如果已经完成7次移位,则一轮读取完成
    ) o4 W- p6 @+ N* R, [
  88.         if(idx >= 7)1 U4 K- G2 `, \
  89.                 isReady = 0;. ^4 S- D, Z5 v( x+ N
  90. }
    # J7 L$ y) l" n: _% z& G5 y3 l

  91. - Z6 N- R" `8 F
  92. static void INT1_Isr() interrupt 2{
    " U% ], h! E$ K# |1 w7 K- D
  93.         // 读当前引脚电平,如果是低电平则说明是下降沿,此时直接忽略该中断
    3 N1 J- ], g4 D
  94.         if(LATCH == 0)' P6 v& z) z$ P# X( w- e& \3 X3 s
  95.                 return;: X( C' F- a% k# g. @) _! b
  96.         // 当LATCH上升沿到来的时候,锁存所有按键状态,同时把键值A输出到DATA
    9 J2 c5 [3 G" T% Z( P* _$ e+ q
  97.         key = bufReady;
    : {" I' d4 y8 s. I& Z( n
  98.         DATA = key & 0x80;//mask[0];        // 为了加速运算,直接取表中的值而不是读表
    5 K4 W9 h- @; O' p# V8 k: ]- F
  99.         idx = 0;, w8 e. w& ?$ S5 e! d  y+ y
  100.         // 允许CLK进行移位
    8 M0 J- r6 [! Z0 ]: ?3 [; O
  101.         isReady = 1;9 m: G# ^6 q+ ?4 Q  P) r! R
  102. }
    / k5 G/ p+ l( I) c% `8 ]
  103. 6 C7 ^) J# p0 }2 }* J  C' J
  104. void main(){  Q: `5 V, w/ b# }& O8 B8 T/ z
  105.         GPIO_Init();% E1 G6 V% q2 A3 X3 s  q7 |& h5 y8 m
  106.         Interrupt_Init();
    2 \' R8 I1 K( o2 S
  107.         - v1 `* C5 X' s7 {9 B( u
  108.         while(1){( h6 l% z3 G/ b% ?" U  ~1 N
  109.                 //PCON |= 0x01;        // 进入省电模式
    5 y  E0 w  X( C) t0 ~* Q9 J/ {) ?
  110.                 //_nop_();$ u" S* X9 K" x) {
  111.                 //_nop_();% G; h0 {1 u$ Y( B: I4 S
  112.                 //_nop_();
    - s" {% m+ o' c  ]. f
  113.                 //_nop_();
    * O0 [  O) {1 y2 x/ ]; I
  114.                 buf = ~((P1 & 0x3F) | ((P5 << 2) & 0xC0));6 R8 X, {4 u' y9 E
  115.                 bufReady = buf;
    4 |7 D, u# k0 X2 B  @0 C/ [1 y- Y
  116.         }. ?4 O6 Q6 p5 s; L% x/ r  S
  117. }
    ! U0 q& o( g2 E9 o
复制代码

5 I8 W  \. B2 _( c# k硬件参数配置无特殊要求,晶振频率选择12M即可。
, }" U6 E( n0 ]- h! G. o7 T
$ D, D' ^/ U  B6 @( I这是编译好的固件。

本帖子中包含更多资源

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

×

评分

参与人数 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 Y* v8 B% u3 O- l7 i$ z5 B
不错的设计,想问一下楼主,FC的15针公头怎么解决?普通的公头太短了,插不进去FC的扩展接口。 ...
9 \# w- z7 \7 I; Q# J: D" u6 ^& q
坛友的改造方案。
回复

使用道具 举报

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

使用道具 举报

发表于 2019-5-25 12:07:18 | 显示全部楼层
精彩,楼主动手强,也写得很详细。
" z$ Q5 Z" u5 M, B7 L2 }' I) A' p2.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
/ W4 A8 ^3 [: b精彩,楼主动手强,也写得很详细。( [+ w# K! z, n& g
2.4G方案是目前无线的最低延迟吗?
. i5 R; [2 C  j9 s$ P, s
我没用过其他无线手柄,所以实在不知道我自己做的这个手柄到底是不是最低延迟。
) W- L4 k( ^7 I% O不过根据网上的说法,延迟高低主要是由通信协议的复杂程度,以及数据传输速率决定的。这个模块虽然是2.4G无线模块,但由于协议很简单,所以延迟比较低。% S+ t& E3 p% W" Y. \' y
我用这个手柄玩一些ACT游戏,比如超级马里奥、忍者龙剑传、热血系列,完全感觉不到延迟,和游戏机自带的手柄没有任何区别。唯一的区别就是这个手柄是用火花山寨手柄改造的,外壳是垃圾回收塑料,粗糙+脆弱,导电橡胶弹性不佳,手感不是一般的差。
: L( L, K  Y' i% R3 n6 v) H& ^+ c我手里还有十几张板子,等我有空了我再做一套,到时候买一个好一点的手柄改造。
回复

使用道具 举报

 楼主| 发表于 2019-5-29 16:56:14 | 显示全部楼层
ppad 发表于 2019-5-28 17:27' n  k% L. O- ]* q" a
给技术帝赞一个,有半成品发布吗,自己焊接改造就可以,编程实在不会啊 ...

$ i6 I2 x9 e1 x( M4 {9 S很可惜,我手里没有多余的单片机了,LDO也找不到了,锂电池以及充电模块更是没有了。反正就是该用到的元件基本都没了,所以没法发布半成品。
# |1 y% h# L! C4 x: I两个板子倒是有十几张剩余。1 [& R" ^  d$ r( b8 X8 d% p
你要是有USB转TTL串口板,完全可以自己买这两种单片机,然后我给你编译好的固件,你自己用串口板下载到单片机里面就行了。两个2.4G无线模块也得通过串口板用AT命令设置参数,不过好在我在设计电路的时候就已经预留好了串口,可以直接在线下载和在线设置参数。总的来说并不麻烦。
回复

使用道具 举报

 楼主| 发表于 2019-5-29 17:00:34 | 显示全部楼层
孙大师 发表于 2019-5-28 18:55; U5 T& |2 j9 S& P: G/ k
非常好,楼主是技术帝,到目前我都还没开发fc的无线套件,等空了,开发一套套件,等玩家自己组装。 ...
& x3 q% }# Y0 }6 O; Y! j4 n7 Z
能得到孙大师的赞誉,不胜荣幸!5 |7 H* c0 ?2 k7 \6 u8 k7 ~& t+ Y3 E
不如开发一个多功能手柄,比如用SFC手柄改造,L/R键配合其他组合键可以用来切换2P~4P、调节连发速度、软重启等各种功能。接收端插到15PIN扩展口。
回复

使用道具 举报

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

本版积分规则

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

GMT+8, 2026-9-27 10:51 , Processed in 3.196826 second(s), 17 queries .

Powered by Discuz! X3.5

© 2001-2025 Discuz! Team.

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