找回密码
 注册

QQ登录

只需一步,快速开始

查看: 26164|回复: 32

自制FC无线手柄

  [复制链接]
发表于 2019-5-22 14:16:45 | 显示全部楼层 |阅读模式
本帖最后由 雷精灵2046 于 2019-6-14 09:28 编辑
  i0 ]/ T  J" J2 Q
% K# l1 M/ z# L& q  B* e& O8 Y没有用复杂的分立元件搭建发射接收电路,直接用的现成的2.4G无线模块jdy-40。
* H. C" y9 p( A. }' q3 ]% ^: A

( G  e4 ]" B% {+ o3 s: A- b5 B7 s发射端靠3.7V锂电池供电,用了一片SOP8封装的STC单片机,负责产生连发脉冲,同时负责检测电池电量,电压低于3V左右的时候触发低压中断,低压指示LED就会亮起来告知该充电了。平时发射模块和单片机均处于睡眠状态,有按键按下才会唤醒,从而实现省电。实测睡眠状态下整机电流约1~2uA。板子洗了一下稍微干净了一点。因为对于微功耗设备来说,焊接残余的助焊剂可能会增加漏电流。; U' }5 s/ M* o0 W2 [

' C1 m) A' Z! I; g% p7 J, \2 j买了一个火花的FC山寨手柄,去掉里面的牛屎板子,并修正一下塑料挡板,把锂电池和充电模块装进去。
7 U: C7 h+ |9 {2 ~0 G# X为了减少体积,充电模块裁剪得十分小,并且更换了充电电阻使之适应这个小小的锂电池。这么小容量的电池,也不需要多么大的充电电流是吧?5 u: f: m+ F# T# A% [
然后统统用热熔胶粘上。充电电流比较小,所以发热很少,不会熔化热熔胶。# G9 ~, a$ w7 O( x0 w

+ r  e. |* ?/ r$ P
* o* b, }. b) k$ r1 j" H" F
1 ]/ ]2 E$ O4 L) s/ r7 `! I. w7 _最后把按键、导电橡胶和电路板装上去。
( a- e$ h( O9 L) c; I) q8 e: @精心裁剪了电路板,正好扣上,不会阻碍其他元件,也不会影响后盖和拧螺丝。# K9 p1 j' v$ f
) {0 O' c3 c: q0 _9 N

* v. Q9 C- \8 Q/ ^: Z$ a& p完工!! o, _0 s% N* _9 ^" z9 ~3 y

/ C" ]% B% |, b- R" _, ?2 W/ s1 X- |
这是充电的MicroUSB插座。旁边的小孔用于透出低压报警LED的光线。
5 M* P- r0 Z% p. `  ]
% @0 b) f: N5 N- e
( A5 a, ?5 r; o! W1 A4 s. ?接收端用一片DIP16封装的STC单片机模拟CD4021。为啥要用单片机模拟而不是直接用CD4021?因为jdy-40模块接收端在有按键按下的时候输出高电平,无按键按下输出低电平,和普通手柄正好相反。当然我也可以用两片74HC00或者74HC04之类的逻辑门进行反相,但那就增加了芯片的数量。对于FC手柄这种工作频率并不高的设备来说,STC单片机完全可以胜任模拟工作。. S* m# O5 l9 _/ k; W0 {

% Y( \* U3 j" O& V$ @$ \( w
$ |0 ~+ P! F% x" n1 J
. N6 q' P. V0 ?3 G4 C$ w电路设计有点小小的错误,所以有几根飞线。原本设计使用低压差LDO是XC6206,结果在做这个接收模块的时候,买的LDO居然找不到了!无奈只好用了AMS1117。幸好对于接收模块来说是5V降到3.3V,1117可以胜任。要是发射端手柄的话,3.7V降到3.3V,那就非得用6206不可了。/ p' t* }# o$ B( U4 a6 @+ ^; L, V4 e

: J, k, N* x4 i4 w: _6 J* L- S  ^实测十分灵敏,延迟极小几乎感觉不出来。可惜这山寨手柄的手感并不佳,尤其是方向键,软塌塌的。看来我得买个剪线手柄改装。* r6 j2 p$ Z% I3 Q& B1 o" t7 ]$ F2 ?
# Y9 ~# g3 L) j4 P- Z0 d! G5 o6 _6 B* x
这是电路图,有兴趣的朋友可以参考。" I1 A- v- Y) q0 Z
2 d( }1 M& _1 \! o  j! R

" K2 ^4 e6 c6 x$ L* M( g& t0 y我信奉开源主义,十分痛恨把技术藏着掖着。好东西大家分享嘛!所以两个单片机的源代码大公开!
) C4 |$ T) {4 O! Z编译器:Keil 51。
  ?/ [2 e8 c. o/ c6 n3 j' S+ x5 L5 ~! w8 p  C
发射端:
  a9 a' g2 d: r4 z. V; ?
  1. #include <INTRINS.H>
    + E6 u8 H& q0 \$ I0 `" t$ T
  2. #include "STC15W.h"8 p& Y2 J8 i/ Y4 h

  3. % q, L; ~3 t. T; t' h0 [3 a7 v

  4. 5 X7 Q! N4 R# N, H- d
  5. /*
    - u; B# h/ A3 Q0 }; H
  6. --------------------------! y" b. z0 ~, M& |" I
  7. |1 (OUT)        \__/   (INT1) 8|
    4 F6 Z% x+ g) I+ p0 P: d
  8. |                                                   |4 ]1 }" S/ [2 q1 e
  9. |2 (VCC)                   (INT0) 7|; |- h; ?, n" o3 p3 P
  10. |                 STC15W204S                   |, T/ n+ x+ x- [, a/ J+ ~; `# v  z6 M
  11. |3 (LED)                         (TXD) 6|5 a  J* ]5 J: i. a) q$ `$ x: D
  12. |                                                   |
    . z& Q4 ^7 f9 [. q) Y
  13. |4 (GND)                         (RXD) 5|
    6 N8 K" }0 M" q% @5 N- `
  14. --------------------------
    7 x6 h) n# w" A  w! l( b; c5 h* l) {

  15. 6 ^6 e( `6 E: c) k
  16. LED ---|<|---[===]--- VCC$ V# a8 s9 y! A
  17.            Red          330% x" [. X' e: o' \, I* D
  18. 5 m9 G8 ^* Y1 w0 O* Y( S. `  D
  19. Fosc = 6MHz. |3 W8 ^1 K6 Y% }( ]
  20. */1 d  h0 x2 Q( [* `
  21. 8 I- P& z; A" F  j9 |
  22. $ s2 j4 a8 i. [3 x+ k& O: o3 l. H5 J
  23. // 矩形波输出脚
    . D+ ]* x& e6 b# x# e: f' r( y
  24. sbit OUT = P5^4;1 ~& Z  ^7 n5 e, K4 X- d
  25. // 低压指示灯引脚
    ( h( `, q3 D2 V6 n! L9 }3 ]& ~
  26. sbit LED = P5^5;
    4 Q) H( w. T/ u3 W

  27. 9 H' `7 u9 ]9 N; t
  28. // 停机标志位& @" ?4 n1 g* ^& _
  29. bit isReadyToHalt = 0;
    * Z7 N! |: r7 x' D, _
  30. : U8 j4 H, t; d5 j# V# @
  31. // 矩形波次数累计
    3 [! J& l$ r, e; f" D( e
  32. static volatile unsigned char count = 0;
    ! k) J3 P! {. N% {/ I

  33. % J- ~  D) D' Q) m. R) d- t

  34. 9 N2 t5 W4 k2 c3 G
  35. static void GPIO_Init(){5 }  i7 s3 `% B9 q8 v6 b+ U
  36.         // P3口设置为准双向,默认靠内部弱上拉输出高电平* C) g- U' u$ a1 e
  37.         P3M0 = 0;) x7 Z6 O; Q: g
  38.         P3M1 = 0;5 x8 x" l7 y" [4 }
  39.         P3 = 0xFF;* j. x  P3 W( W
  40.         // P5口设置为准双向,默认靠内部弱上拉输出高电平; A: _8 \5 y7 }3 S
  41.         P5M0 = 0;
    - V/ z1 F* O7 O, S1 ?
  42.         P5M1 = 0;
    , ~7 _. ]( o/ F% T* R
  43.         P5 = 0xFF;
    & q1 X% e$ Q' ^4 `& Y$ v
  44. }/ V4 U6 B9 W6 J9 G: z5 G

  45. ' X1 @' Z7 q7 B+ ^% S" B- `
  46. static void Timer0_Init(){3 U% v& F/ R! Y$ B6 D9 v7 J: r' N
  47.         // 16毫秒@6.000MHz
    8 ^* \  g1 D* G( X4 @8 Q, C
  48.         AUXR &= 0x7F;        // 定时器时钟12T模式
    4 F' D4 \1 }6 P
  49.         TMOD &= 0xF0;        // 设置定时器模式& U- y: D1 Y& X7 b1 ^1 ~& k
  50.         TL0 = 0xC0;                // 设置定时初值# c, a+ H9 H3 [0 d2 m- q
  51.         TH0 = 0xE0;                // 设置定时初值
    7 ]+ G1 |% }) P
  52.         TF0 = 0;                // 清除TF0标志
      d3 q$ f7 _! U4 j/ d; `8 x0 Z
  53.         TR0 = 1;                // 定时器0开始计时8 Y( \) G$ c! |+ W4 I
  54. }
    ( Y" _8 q7 h3 I1 o7 Q

  55. 0 y& S2 r1 V& Z  e
  56. static void Interrupt_Init(){9 _9 E$ T0 t- k4 b8 v3 }
  57.         // INT0中断触发类型为下降沿触发, ?% g$ G3 z+ `* {+ M
  58.         IT0 = 1;
    3 }% t0 M% A! Z  e
  59.         // 允许INT0中断. m- U# ^% O$ `& m8 S" V
  60.         EX0 = 1;9 x! p/ X5 w& Y1 \6 m6 ~& u
  61.         // INT1中断触发类型为下降沿触发
    + {( y* Y3 Z7 I" S3 j
  62.         IT1 = 1;
    * w) i* f3 L- H/ V* q
  63.         // 允许INT1中断7 U9 b+ ~* V. [" r; n, U/ y
  64.         EX1 = 1;
    2 m( y7 P5 _+ Y% A5 C
  65.         // 允许定时器0中断" q. T+ r  B& _1 M, j5 }
  66.         ET0 = 1;
    - L& F! k% Y3 s3 p0 ~# e5 u) N/ R
  67.         // 允许全局中断. q+ X1 f" n! E$ H  U
  68.         EA = 1;% f, X8 Q4 O# s" _+ F
  69. }
    * ]! d5 x/ \& l

  70. 5 s6 }) Z. M- I- K' C: @
  71. static void INT0_Isr() interrupt 0{- V0 A6 y5 u& z2 f6 G  H
  72.         // 矩形波次数累计归零+ V/ o# \7 ^4 a6 v7 ?( S
  73.         count = 0;
    ' h4 ?* L8 u7 m$ S2 ~" A  B
  74.         // 重开定时器0中断& m& R" E6 x" A1 ~6 G# X( y
  75.         ET0 = 1;9 j+ \4 X' }% a) z5 m) s& o* _
  76. }; J; u6 `2 E! @9 H. K7 f* ^

  77. * N5 g# n" o1 M2 O
  78. static void Timer0_Isr() interrupt 1{
    1 j; \2 r: Z& o1 I% d
  79.         // 输出矩形波
      e: e% r! c7 V% ]6 D" M
  80.         OUT = ~OUT;
      s8 E6 M! {: j9 A3 P
  81.         // 累计矩形波次数
    5 }9 N/ M  R3 P
  82.         count++;) Y4 [0 a" M  l7 X, u
  83.         // 超过250个矩形波,准备停机) r. F0 o! g3 _' `4 p
  84.         if(count > 250){# H. ~  B3 A# X7 o6 Y6 Y9 Y
  85.                 count = 0;3 h# ]3 h  Y+ d9 M2 p
  86.                 isReadyToHalt = 1;
    % B" W, R8 I. J, J+ o/ c3 X5 w
  87.         }* ?1 l5 ~" L% G' T% l" d/ |
  88. }
    / ^: W( Y( F' Z. a; y! Y* u

  89. : Z/ t" y) A. u
  90. static void INT1_Isr() interrupt 2{7 y5 X& B2 o+ o$ d5 [
  91.         // 矩形波次数累计归零
    # M6 K( u6 R6 R- t
  92.         count = 0;
    - a) W# H! e* j, h1 K$ o6 i' R9 C
  93.         // 重开定时器0中断1 V) B# |: H- F6 L3 I" D
  94.         ET0 = 1;/ B1 D& g: C, n$ u1 u, y
  95. }
    3 w: s' ^: G, e2 B+ ?7 M

  96. - p  O1 ~7 t, u" R0 p; |: X5 x$ r

  97. " H# g* D! y9 x9 G0 y
  98. void main(){" r- R: ~, |5 y/ G4 g0 b3 A4 P
  99.         // 初始化P3和P5口- N4 ?, z$ w1 C5 b% M* g
  100.         GPIO_Init();1 g4 X( O& U+ }2 f
  101.         // 初始化定时器0
    # q" T4 G) c% g/ R
  102.         Timer0_Init();$ `6 r* a& ^: T( ~
  103.         // 初始化中断
    $ U) U) |0 B) J( O$ y' q! s  S
  104.         Interrupt_Init();- g6 s6 g7 V3 d3 g( r- T9 O
  105.        
    5 Q1 q5 ~" q2 Z! p4 h: G  F; f
  106.         while(1){
    * m2 H, t' n1 W& h
  107.                 // 检测电量- W( m7 v" z9 a( Q! |) O
  108.                 if(PCON & (1 << 5)){4 I! O/ Y% j* p* e
  109.                         // 如果电量低,低压指示灯亮
    # B. P; a& n$ R
  110.                         LED = 0;5 }. u7 A7 S7 ^0 q
  111.                         // 清电量检测硬件标志位) X- g0 O8 E6 s6 Z4 D  e
  112.                         PCON &= ~(1 << 5);; ^2 K: m# I8 z2 t
  113.                 }else{" ^0 I; s) B4 ^9 X! K! ~
  114.                         // 电量正常,低压指示灯灭- h. u# Z& o: V* j5 R9 `
  115.                         LED = 1;
    & Z9 f: {6 U4 k+ L  c1 p5 A! b7 T  X$ H0 c
  116.                 }* _; [" ]# d) a6 P4 X/ g8 q- b6 u9 G1 H

  117. % j. t. Z7 f0 W; q
  118.                 // 检测到停机标志
    : y& u. H& |! S$ Z# s' v/ k
  119.                 if(isReadyToHalt == 1){5 j2 w$ q# B2 z+ {2 b
  120.                         // 暂时关闭定时器0中断
    ( u4 b9 j, o$ p, V  X
  121.                         ET0 = 0;' F; }# F% l/ i$ h4 G& e& U0 _
  122.                         // 停机之前先把矩形波输出脚置低电平,以方便INT0和INT1唤醒CPU* T1 b/ H+ P3 t5 q
  123.                         OUT = 0;& X1 K- h# B/ |. p! L9 l# h- \
  124.                         // 停机之前先把低压指示灯灭掉,以省电5 ^, j+ Z! a$ ^  @' M3 P, f
  125.                         LED = 1;; P7 y  i) h! Q
  126.                         // 进入停机模式: g' o2 V6 {+ G& w4 }1 w
  127.                         PCON |= 0x02;
    - Q7 `% }( Q# ?" h& F$ S
  128.                         _nop_();: l7 h' s! a" z; \
  129.                         _nop_();
    / ]# ?& b: L7 H) W8 E
  130.                         _nop_();
    9 R2 y4 h: g: c' \/ P
  131.                         _nop_();
    " d! L8 h7 V/ b0 E
  132.                         // 唤醒,清标志位
    ' E# a1 u+ I9 _  j" m) \5 e. \
  133.                         isReadyToHalt = 0;
    7 t# D! G2 F2 ]% Y, j
  134.                         // 重开定时器0中断
    0 w$ v' e1 t4 ~5 S1 R1 g3 o
  135.                         ET0 = 1;
      r) `2 D' `& |: I+ O6 x: y# t
  136.                 }' ]# R+ @+ q  x/ c
  137.         }+ d2 r! r# I8 L# T8 r# b/ K9 t
  138. }5 G; t" G( ^" N
复制代码
2 j) D' r: ]  {1 t  K$ D
硬件参数配置:1 ^: o) L: O5 z4 X6 M9 ]' ^

5 c1 J2 S! T$ p- s9 c  G& ]
! ?" z1 V, u, q; h/ V7 @! T$ U接收端:
4 R( w4 ?8 r( u% W" I
  1. #include <INTRINS.H>, I, h( B, d2 ^
  2. #include "STC15W.h"  x0 C+ W, e% s
  3. 6 R5 n  \+ I9 k! D
  4. . i( z  [/ J/ m: h9 M7 ?7 H" Y+ V9 W
  5. /*' J8 n: V( a6 H3 Y
  6. 1 p4 F4 Q9 A3 O" Y5 q3 h2 T
  7. *---------------------------*
    % x3 {8 ]- b1 {$ r( d4 J3 O
  8. |1 (GPIO2)         \__/  (GPIO1)16|+ S; R1 C8 d: h
  9. |                                                        |3 B7 g" F7 X  D0 E
  10. |2 (GPIO3)                   (GPIO0)15|
    + I4 d6 S' \, G2 N9 ^0 R
  11. |                                                        |9 c1 n* w2 m: H6 h  Z9 K
  12. |3 (GPIO4)                                  14|! D+ H) v! A  `
  13. |                                                        |
    , e' E4 C5 B) i$ ^- V9 x  R
  14. |4 (GPIO5)                        (DATA)13|) K4 l. ^4 D/ L2 B3 L
  15. |                  STC15W204S                |1 w- G( H, x* f% h! W2 A8 E4 ^: A1 E
  16. |5 (GPIO6)                   (LATCH)12|& c5 u& d* q' X. L7 ^" q; Y0 g7 q8 L
  17. |                                                        |
    $ c) d% I0 q* q! q$ E) l  |
  18. |6 (VCC)                         (CLK)11|
    1 e! M' O) Y* O7 D* b) U
  19. |                                                          |
    ! `- g5 Q  T. p+ Q1 e5 p* B* k% U
  20. |7 (GPIO7)                         (TXD)10|- H! G( J2 D7 C2 W: e& j
  21. |                                                        |9 o8 Y3 S% x7 V7 v9 j- @- a
  22. |8 (GND)                         (RXD) 9|
    1 r% A7 j/ G) L/ x( m* S) f# n7 T. w
  23. *---------------------------*
    ! {  s6 _8 U+ @2 @
  24. Fosc = 12MHz% }- L' Z3 N" H6 Z
  25. 0 l9 @0 L) u4 w* P/ o. Q; K
  26. P1.0 -> 上, n+ T+ \) C9 i( A8 B
  27. P1.1 -> 左
    ! f9 F' E% N( Y& D" i
  28. P1.2 -> 下
    % i5 s/ C, @1 }" c  W( J
  29. P1.3 -> 右9 k$ r; v$ F4 O
  30. P1.4 -> SEL5 R9 r: v( S1 i; w& K% K' v
  31. P1.5 -> STA
    3 m3 F9 c4 u/ M
  32. P5.4 -> B
    * U" x' q! j; g" i' W
  33. P5.5 -> A
    7 c  {) t  w, V1 u( d9 ^/ `) p

  34. , @% Q4 _$ o) F/ F' V; a; ~) r
  35. */
    # p5 H# F4 F  B0 c3 O0 c
  36. & ^6 }8 U+ C# A* E0 k) ]

  37. & u$ l: T* S( D- A/ }
  38. sbit CLK        = P3^2;. d+ n4 d$ ?& J; h1 d
  39. sbit LATCH        = P3^3;' S) h, ^: Q) a4 D
  40. sbit DATA        = P3^6;% g' X  S3 C7 h; g+ B1 R2 q

  41. # r/ Q$ _4 |  f. s$ d6 g. }
  42. bit isReady = 0;% S% l+ I0 C& s3 l
  43. static unsigned char key = 0;* k! }4 Q+ p* I+ f# D. t) Q
  44. static unsigned char buf = 0;        // 双缓冲。这个缓冲区保存从P1和P5组合而来的键值
    # K, [* V# l8 [* C$ M5 f
  45. static unsigned char bufReady = 0;        // 双缓冲。这个缓冲区保存上面那个缓冲区的备份8 G5 ~4 m. {0 c2 q3 G& q7 d6 V
  46. static const unsigned char data mask[] = {0x80, 0x40, 0x10, 0x20, 0x01, 0x04, 0x02, 0x08};        // A B SELECT START UP DOWN LEFT RIGHT。为提升速度,这个表放到RAM中
    ! p7 v7 @- ?+ ~' _$ X  U
  47. static unsigned char idx = 0;
    8 t/ H* T6 t+ q7 k+ u! U4 G: g

  48. ) K/ a9 Y: d2 k* ~

  49. ! p/ B! h) w' y# o
  50. static void GPIO_Init(){7 b) f  ~0 E5 M7 t7 z6 z2 \
  51.         // P1口和P5口用于接收并行信号,全部初始化为准双向,依靠内部弱上拉输出高电平
    ! V! F  f9 u2 ]7 Q# q: `
  52.         P1M0 = 0;( o5 w# O* u* A6 E% Z& q4 c
  53.         P1M1 = 0;
    % o. B( y" b8 R% }# h
  54.         P1= 0xFF;
    ( S* `  q) w. A) ~
  55.         P5M0 = 0;9 d0 @1 b' y6 ?' M
  56.         P5M1 = 0;
    % R- S6 }" B4 v; I5 v& H5 ]
  57.         P5= 0xFF;! Y+ w# ?6 Q& b) E: H+ l7 t
  58.         // P3口初始化为准双向
    . |8 ]' _8 N& [* \
  59.         P3M0 = 0;: @2 j" f0 P% W
  60.         P3M1 = 0;" G8 l" J! @0 C; H$ L" j7 o! J
  61.         P3 = 0xFF;
    # W! Y- K  {6 m  y) [% k# k3 H
  62. }( K8 S; p, ?/ c$ k
  63. - |1 |1 R& l* X  h3 f& G
  64. static void Interrupt_Init(){
    ; U8 v# ^- G0 ^- m' {
  65.         // INT0中断(CLK)触发类型为上升沿+下降沿
    1 ^; Q6 e) }$ Y% u& h, N
  66.         IT0 = 0;
    + ]5 Y7 {8 {' L, ]* l
  67.         // 允许INT0中断
    4 N( e/ m! N, L
  68.         EX0 = 1;
    : X7 X4 n' N: S* ]
  69.         // INT1中断(LATCH)触发类型为上升沿+下降沿
    1 u- V# D) `8 i; s! M
  70.         IT1 = 0;1 i9 S( N0 }. Z$ S( m6 U" k
  71.         // 允许INT1中断0 j5 H0 r! I7 o) t% x& B
  72.         EX1 = 1;: e( T( _+ Q. ]. C3 i% B
  73.         // 开启全局中断
    % l" q* L5 g" j+ O
  74.         EA = 1;
    & _9 ~9 m. E# |4 }6 b& T/ V
  75. }) w( f5 B% B! [. @3 r
  76. 2 X9 @( N, d$ ]( Y4 ]4 j
  77. static void INT0_Isr() interrupt 0{, U( S. u' w: A1 _# w
  78.         // 只有已经成功锁存才允许CLK移位* x# O- V- x3 g) i1 b/ U3 p6 h
  79.         if(isReady == 0)5 k* H* }$ A- g9 \4 ?
  80.                 return;! K: v1 a" ?! f7 O1 a/ m4 _
  81.         // 读当前引脚电平,如果是低电平则说明是下降沿,此时直接忽略该中断
    " k$ |9 b, m: E
  82.         if(CLK == 0)3 b2 j! I, S, a% d" C
  83.                 return;
    $ R* x& I! T* ?* d* L' B' {
  84.         // CLK上升沿到来的时候,取锁存值的下一位输出) r3 K" B4 c$ d$ Z
  85.         idx++;
    ! g1 Y1 Q+ G9 n, A  C% e
  86.         DATA = key & mask[idx];
    1 g4 E0 m9 S, X0 [& i- S1 Z
  87.         // 如果已经完成7次移位,则一轮读取完成
    - ]5 n% ^9 F* I# z' p6 [% V
  88.         if(idx >= 7)
    ; ^8 |# V" d# @
  89.                 isReady = 0;
    5 ^$ a. E  s0 E2 t  [
  90. }
    ' H( O- b! i0 d! }2 ~9 @! [' Q  [

  91. $ p- {' X) A  k8 ?- J. P, M
  92. static void INT1_Isr() interrupt 2{
    ) L0 \" E2 ^  f# j1 F& u
  93.         // 读当前引脚电平,如果是低电平则说明是下降沿,此时直接忽略该中断3 W) h; }* V- D! @; e1 O3 }% z  t
  94.         if(LATCH == 0)- k: S) G3 x! l
  95.                 return;/ g6 X2 x- @0 k5 s2 d
  96.         // 当LATCH上升沿到来的时候,锁存所有按键状态,同时把键值A输出到DATA
    ( d0 `0 V; ~, G8 A
  97.         key = bufReady;2 Z$ b: B/ K9 y* ~9 m' F2 @% b3 |3 A
  98.         DATA = key & 0x80;//mask[0];        // 为了加速运算,直接取表中的值而不是读表
    - R$ X0 `2 j  h. }; z$ z+ {
  99.         idx = 0;
    4 k- {( `) P9 E3 t
  100.         // 允许CLK进行移位
    3 m+ a7 X! X8 o, I
  101.         isReady = 1;( L- @) k; |( O- T3 x
  102. }
    ' P# `3 `: @, T& e

  103. 5 X0 x' ~" H6 y  _+ i5 c1 j; k: }
  104. void main(){6 f% _6 t7 L3 }+ G; {. F* R
  105.         GPIO_Init();
      E6 u; V7 Z/ ^5 c% \
  106.         Interrupt_Init();1 h7 V5 d5 n" L, c* I% Z. g# \
  107.        
    % }9 |5 [/ [) ~
  108.         while(1){
    * {+ g3 d- B" R9 j2 b: }
  109.                 //PCON |= 0x01;        // 进入省电模式- @: F$ ?0 U! P# ~; {$ E
  110.                 //_nop_();
    2 b* W9 u9 s/ U6 i/ o1 D
  111.                 //_nop_();
    + a* ]& I/ x9 e* C
  112.                 //_nop_();
    ( h1 _/ P$ H9 _' H3 m# Y! e
  113.                 //_nop_();. ^" L2 U  o; Q6 g$ K* p
  114.                 buf = ~((P1 & 0x3F) | ((P5 << 2) & 0xC0));6 p. E) {" g  Y1 j$ X6 Y3 n) R
  115.                 bufReady = buf;6 P3 z, u. A8 o+ J2 ^
  116.         }( \0 e8 g# ]# R& l- s" k, R' ?
  117. }
    ' u) [0 _7 J- R' c7 N
复制代码

2 c4 O6 W+ b8 M2 M$ S硬件参数配置无特殊要求,晶振频率选择12M即可。& y6 i4 t* V9 ?3 h# A
/ I" [( w% e- E# ^7 I: k2 Z  A0 n
这是编译好的固件。

本帖子中包含更多资源

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

×

评分

参与人数 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:051 m9 u0 z5 H& K# O7 S# n
不错的设计,想问一下楼主,FC的15针公头怎么解决?普通的公头太短了,插不进去FC的扩展接口。 ...
' P9 r7 I, [( J6 N) c
坛友的改造方案
回复

使用道具 举报

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

使用道具 举报

发表于 2019-5-25 12:07:18 | 显示全部楼层
精彩,楼主动手强,也写得很详细。
% H  I* U: e- J  O9 X  R3 N. Z* o2.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
' r  w% j2 n% w( E2 |$ c  a+ p精彩,楼主动手强,也写得很详细。
* W/ S$ j# q3 T9 b2.4G方案是目前无线的最低延迟吗?
3 G9 |0 [2 H6 V
我没用过其他无线手柄,所以实在不知道我自己做的这个手柄到底是不是最低延迟。
2 M& R5 ?* r7 P# g- s* ?6 z  Y不过根据网上的说法,延迟高低主要是由通信协议的复杂程度,以及数据传输速率决定的。这个模块虽然是2.4G无线模块,但由于协议很简单,所以延迟比较低。
1 f. ^; x4 O3 V0 h我用这个手柄玩一些ACT游戏,比如超级马里奥、忍者龙剑传、热血系列,完全感觉不到延迟,和游戏机自带的手柄没有任何区别。唯一的区别就是这个手柄是用火花山寨手柄改造的,外壳是垃圾回收塑料,粗糙+脆弱,导电橡胶弹性不佳,手感不是一般的差。: K6 h2 h3 w% y# M2 }, n% j
我手里还有十几张板子,等我有空了我再做一套,到时候买一个好一点的手柄改造。
回复

使用道具 举报

 楼主| 发表于 2019-5-29 16:56:14 | 显示全部楼层
ppad 发表于 2019-5-28 17:27, \9 I) U) u+ A" P
给技术帝赞一个,有半成品发布吗,自己焊接改造就可以,编程实在不会啊 ...

2 G  M3 e- {1 u. Y: v9 x很可惜,我手里没有多余的单片机了,LDO也找不到了,锂电池以及充电模块更是没有了。反正就是该用到的元件基本都没了,所以没法发布半成品。# i+ v5 R6 H* y' ]* I
两个板子倒是有十几张剩余。7 A$ y& c1 u* F, {9 X8 c4 P
你要是有USB转TTL串口板,完全可以自己买这两种单片机,然后我给你编译好的固件,你自己用串口板下载到单片机里面就行了。两个2.4G无线模块也得通过串口板用AT命令设置参数,不过好在我在设计电路的时候就已经预留好了串口,可以直接在线下载和在线设置参数。总的来说并不麻烦。
回复

使用道具 举报

 楼主| 发表于 2019-5-29 17:00:34 | 显示全部楼层
孙大师 发表于 2019-5-28 18:55
. _% O. X# w" ?( b非常好,楼主是技术帝,到目前我都还没开发fc的无线套件,等空了,开发一套套件,等玩家自己组装。 ...

* r7 h$ ~. q& a  J能得到孙大师的赞誉,不胜荣幸!
/ y2 P  y$ h  o不如开发一个多功能手柄,比如用SFC手柄改造,L/R键配合其他组合键可以用来切换2P~4P、调节连发速度、软重启等各种功能。接收端插到15PIN扩展口。
回复

使用道具 举报

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

本版积分规则

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

GMT+8, 2026-8-5 16:17 , Processed in 0.332944 second(s), 14 queries .

Powered by Discuz! X3.5

© 2001-2025 Discuz! Team.

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