找回密码
 注册

QQ登录

只需一步,快速开始

查看: 23669|回复: 28

自制FC无线手柄

  [复制链接]
发表于 2019-5-22 14:16:45 | 显示全部楼层 |阅读模式
本帖最后由 雷精灵2046 于 2019-6-14 09:28 编辑
; ^9 F" E" |7 ?' o& Y: A0 O4 ^4 z2 Q% G) _- G' B; m' x7 A
没有用复杂的分立元件搭建发射接收电路,直接用的现成的2.4G无线模块jdy-40。
# W! j/ u6 M  q1 d" ?3 w- t
9 l( d  j; C+ e0 n
3 S8 b8 W9 z. k* G) C# ~- P0 o9 s发射端靠3.7V锂电池供电,用了一片SOP8封装的STC单片机,负责产生连发脉冲,同时负责检测电池电量,电压低于3V左右的时候触发低压中断,低压指示LED就会亮起来告知该充电了。平时发射模块和单片机均处于睡眠状态,有按键按下才会唤醒,从而实现省电。实测睡眠状态下整机电流约1~2uA。板子洗了一下稍微干净了一点。因为对于微功耗设备来说,焊接残余的助焊剂可能会增加漏电流。# m2 q6 e8 A8 B1 q- c& }. D
" N6 B, T- M0 ~2 d( u
买了一个火花的FC山寨手柄,去掉里面的牛屎板子,并修正一下塑料挡板,把锂电池和充电模块装进去。
  M4 a* V% q1 V9 x0 C2 r1 T1 ?为了减少体积,充电模块裁剪得十分小,并且更换了充电电阻使之适应这个小小的锂电池。这么小容量的电池,也不需要多么大的充电电流是吧?' d; \  T, F3 l2 V& p9 u' F5 k& Z
然后统统用热熔胶粘上。充电电流比较小,所以发热很少,不会熔化热熔胶。  f" P+ C& M; l6 l$ Z0 z
8 b- _  T2 w  D8 w6 }
/ E9 e$ k1 Q0 X% n+ M2 J

3 e! i5 P5 {% \最后把按键、导电橡胶和电路板装上去。
# T  y2 n: w/ X! l, n精心裁剪了电路板,正好扣上,不会阻碍其他元件,也不会影响后盖和拧螺丝。/ q+ b, W9 `  `1 M  F( K9 a7 \

2 ?4 n$ ]  H+ `& G( y0 p( l: Z' S, Y, U5 h  L/ |4 P
完工!
5 a' q$ m8 J. p5 J& a! x- [  U; X0 O# y7 p
4 [9 ^$ b0 Z$ |$ Q: _/ J) U, i
这是充电的MicroUSB插座。旁边的小孔用于透出低压报警LED的光线。
9 X2 W) x  F2 |! b) r* O: ?# S" s$ I

' m9 c1 }- ^2 }+ ]: |接收端用一片DIP16封装的STC单片机模拟CD4021。为啥要用单片机模拟而不是直接用CD4021?因为jdy-40模块接收端在有按键按下的时候输出高电平,无按键按下输出低电平,和普通手柄正好相反。当然我也可以用两片74HC00或者74HC04之类的逻辑门进行反相,但那就增加了芯片的数量。对于FC手柄这种工作频率并不高的设备来说,STC单片机完全可以胜任模拟工作。
0 ^6 }+ ~; p& [6 T8 D) g/ U  m2 o# c* ?/ f7 Q
" H9 P( ]+ F3 H
7 n% H1 j$ G' ?' B* c
电路设计有点小小的错误,所以有几根飞线。原本设计使用低压差LDO是XC6206,结果在做这个接收模块的时候,买的LDO居然找不到了!无奈只好用了AMS1117。幸好对于接收模块来说是5V降到3.3V,1117可以胜任。要是发射端手柄的话,3.7V降到3.3V,那就非得用6206不可了。
! J9 D2 |0 C9 [+ J
. I  E  s/ k" R+ K$ A! J实测十分灵敏,延迟极小几乎感觉不出来。可惜这山寨手柄的手感并不佳,尤其是方向键,软塌塌的。看来我得买个剪线手柄改装。
5 w' z$ h5 W3 v: C0 I- T) R: H
& l$ D# a. |. D* F6 c- l这是电路图,有兴趣的朋友可以参考。
+ ~  `/ b0 a) f( ]# i6 @3 A/ I% |7 m& u6 }: G

  S6 W7 V' S2 T: R8 A( |我信奉开源主义,十分痛恨把技术藏着掖着。好东西大家分享嘛!所以两个单片机的源代码大公开!
/ [5 z$ Y9 J; u6 |/ @6 M编译器:Keil 51。
1 E6 j* }* I! f9 F
- O0 g+ B, L% }- B. I2 W/ I4 o发射端:0 j# l' P" c/ h1 T, S+ B
  1. #include <INTRINS.H>6 o3 x. Y% h9 a% d( {1 q, m
  2. #include "STC15W.h"
    " L$ J/ m8 [9 G) d1 e
  3. ! y9 {6 a, j- N% o& [
  4. 6 s* t3 @' `% B* F
  5. /*( ?7 x! ]3 d, v$ y' J/ P
  6. --------------------------) @; E% q! y8 F: X
  7. |1 (OUT)        \__/   (INT1) 8|
    1 Q' z: A5 _3 H
  8. |                                                   |
    1 Z  x1 K/ T0 K9 R% [. K2 p4 g
  9. |2 (VCC)                   (INT0) 7|
    : A7 ^* C1 V/ @- r7 U% e- q
  10. |                 STC15W204S                   |
    ' W8 T4 E& d# W, K* B
  11. |3 (LED)                         (TXD) 6|
    7 H3 ^' G5 y) x+ N- y
  12. |                                                   |1 }$ J$ w7 k/ J( k6 M! w
  13. |4 (GND)                         (RXD) 5|4 l8 A" o/ ~3 E4 @& O; t
  14. --------------------------
    $ [0 M$ W8 H0 w) @# M/ R

  15. : `- p! c3 R8 q+ _: H' V) r% t
  16. LED ---|<|---[===]--- VCC' I  w7 k" m9 W
  17.            Red          330  _0 Q6 z7 ]( y/ t3 S2 Z
  18. , U9 V, Q# I1 n0 N
  19. Fosc = 6MHz
    - S( k$ ~/ ?8 H. `; |
  20. */
    # Z# Z/ D& t5 V8 ]; ~+ s9 K$ W

  21. 3 C* |$ P! i/ C; m* u8 ]5 q
  22.   I2 q- u6 m. t5 j. h* ?5 P$ B1 c
  23. // 矩形波输出脚/ V  }9 y# t; X0 x  ~$ l
  24. sbit OUT = P5^4;  |) B$ E( m: e3 K9 ~- o2 V
  25. // 低压指示灯引脚* B  T% H! i& ?- O7 P  a( [
  26. sbit LED = P5^5;( |7 |5 U0 P- Y* }) U7 U

  27. ; m' \) ^  w5 `# a. D. Q
  28. // 停机标志位8 n+ m  J  z" c1 ~9 \$ a
  29. bit isReadyToHalt = 0;, X0 a4 Q! _+ m" `! \: L
  30. ; k: K# f$ p/ w. ^& s( s6 P; }- d  o
  31. // 矩形波次数累计
    / R1 o& F/ ]0 d( d5 n
  32. static volatile unsigned char count = 0;
    0 k5 ^% _% J. x/ e9 i+ A

  33. ' v1 e" x  ~) u3 @

  34. & s9 v: p" A# N8 [  U- Y: N- H) P
  35. static void GPIO_Init(){
    9 u, r7 N( _" ~& y
  36.         // P3口设置为准双向,默认靠内部弱上拉输出高电平6 Z) M2 K5 X5 w
  37.         P3M0 = 0;
    / ^* I$ |# e) e& u$ D
  38.         P3M1 = 0;
    7 |8 T, E0 Z2 u& F0 C- j2 h
  39.         P3 = 0xFF;' h) E' d* R$ r& m7 b& [7 E, X$ m
  40.         // P5口设置为准双向,默认靠内部弱上拉输出高电平5 J& x7 A+ |( r" G9 H5 [/ V: }
  41.         P5M0 = 0;
    6 O7 ]4 g" R' J$ d' C
  42.         P5M1 = 0;- C% \9 q/ A% Y! d' I
  43.         P5 = 0xFF;& n) [% M5 v- V& _  h
  44. }5 p( S# c. X2 ]
  45. 4 p- H+ g: ^! x( ^) J5 b* D
  46. static void Timer0_Init(){/ f8 F( T- n$ [9 t4 ~9 f  r
  47.         // 16毫秒@6.000MHz
    % J7 A' Q5 a7 D8 N; R4 k* j7 `
  48.         AUXR &= 0x7F;        // 定时器时钟12T模式
    ! E( \! ?, e) J) `- Q# h5 N
  49.         TMOD &= 0xF0;        // 设置定时器模式
    5 u* I+ J9 B& u* N6 g
  50.         TL0 = 0xC0;                // 设置定时初值
    1 p9 ~* v! r, d+ @3 s
  51.         TH0 = 0xE0;                // 设置定时初值$ D3 c6 \( }* v
  52.         TF0 = 0;                // 清除TF0标志: u7 {4 y( A) K6 w
  53.         TR0 = 1;                // 定时器0开始计时
    6 Y2 G( f5 ?) E
  54. }  l) S+ }( o6 Y" R1 t/ y
  55. / ]+ Z% Y  p& m! c! l2 ~: U+ d
  56. static void Interrupt_Init(){* \: I+ y0 K/ z8 l
  57.         // INT0中断触发类型为下降沿触发
    " M: u! [5 b; y8 w3 G5 @1 x, _
  58.         IT0 = 1;* P. O$ P2 @* T" ?) Z; @
  59.         // 允许INT0中断
    " I  z, B* n0 k4 K1 e0 q
  60.         EX0 = 1;
    . N# y, E6 v" s  P' ^$ E
  61.         // INT1中断触发类型为下降沿触发
      x' j9 ^4 P: O5 s' C
  62.         IT1 = 1;+ m- n) R; f  ?- r' H  D
  63.         // 允许INT1中断0 q3 e' t( o5 u; Q6 c7 V. D
  64.         EX1 = 1;5 }; b; U  V* f3 q! V, ^
  65.         // 允许定时器0中断! B8 n$ G, Y5 {# ?: F
  66.         ET0 = 1;2 x3 o" {5 a& n
  67.         // 允许全局中断( i9 B, q# t7 i- V' d3 s) {. N
  68.         EA = 1;. @( n+ T5 H/ g/ [
  69. }  k2 L+ [! e" K( V( I9 j! }: E
  70. ! q/ c8 k( x) N7 Q4 `
  71. static void INT0_Isr() interrupt 0{  R+ |( H3 R. p: ?' f
  72.         // 矩形波次数累计归零
    , [' Q9 F( q6 Q6 z' s0 `
  73.         count = 0;
    7 ~- p- ?% D5 i2 Q; A
  74.         // 重开定时器0中断7 n8 }  p4 `: F2 J, U
  75.         ET0 = 1;. O. \- g$ n4 Y) U/ d' o
  76. }
    9 P2 ]# I* s! \# C+ m- _0 ^" l

  77. 0 J! C! e% X8 ^4 Z, |
  78. static void Timer0_Isr() interrupt 1{
    2 J) Z3 ^* F  Q, H3 j
  79.         // 输出矩形波
    6 V$ I. W7 G3 C. g' y3 w
  80.         OUT = ~OUT;
    2 l* {' [/ {- B! E
  81.         // 累计矩形波次数" P' X+ [# f" f: }0 B8 _
  82.         count++;
    , d9 W6 U! |1 X& N# `5 |1 C
  83.         // 超过250个矩形波,准备停机" n0 X: r6 s! F( e) Y
  84.         if(count > 250){
    . e0 U( \3 l5 n" N/ @
  85.                 count = 0;
    3 C% y  W! F' E
  86.                 isReadyToHalt = 1;8 @8 F. S$ Q5 j; ]
  87.         }
    . C& ?/ l, u' v$ n, [6 U+ P1 v
  88. }
    " S# l0 F& v2 L/ ]
  89. + p& F2 ]2 W, S4 ]
  90. static void INT1_Isr() interrupt 2{: v/ W: |. ~" J( r6 ]- r/ L- Q) [$ _! C
  91.         // 矩形波次数累计归零
    . v5 V. P9 Y$ n  ^5 k* f3 W, S# j) _
  92.         count = 0;$ g: h" d: ^( \. b6 X& V  d- T
  93.         // 重开定时器0中断+ Q8 s7 ~$ ?" x. y5 R. C  W
  94.         ET0 = 1;
    * z  y# f2 }6 r
  95. }* f" G. b- {5 {- ]. E7 A

  96. - d1 o6 p% N6 @; V5 N' S% A
  97.   W9 x: H0 [/ t; O) o& P
  98. void main(){
    . C& D7 q2 n: B  y3 H
  99.         // 初始化P3和P5口
    ( g& v5 R; i; i' O$ @
  100.         GPIO_Init();
    * ^+ T  ?: d  R0 F" u1 c( W
  101.         // 初始化定时器0+ P; o9 N: \% E
  102.         Timer0_Init();( x9 \6 w7 C  c+ t% j
  103.         // 初始化中断
    + S) W1 M! a" J1 X
  104.         Interrupt_Init();& ~& U: d& i3 h, f- u' W
  105.         , i. r; x( g! B9 z0 a
  106.         while(1){
    ! t* j5 `8 l/ Z& ?2 _2 f
  107.                 // 检测电量/ A4 g8 q3 [$ A: @& _! @
  108.                 if(PCON & (1 << 5)){5 v& ?- L( u7 _, ]
  109.                         // 如果电量低,低压指示灯亮- s/ @" o) `. Y( W$ T4 {
  110.                         LED = 0;2 p% T8 z" A# Q9 J' h& x
  111.                         // 清电量检测硬件标志位, |/ }1 Z& ?( C, V
  112.                         PCON &= ~(1 << 5);1 e. r4 H* V$ R
  113.                 }else{
    5 z! i  ?, Z/ S, i+ u7 ?3 B
  114.                         // 电量正常,低压指示灯灭/ i7 Z( b; A7 u1 V7 O1 j
  115.                         LED = 1;' O0 [7 N' F: N6 k. z; Q
  116.                 }
    / H4 N1 D3 k/ Y% I
  117. # C" |0 R3 z" |/ f: Y3 R: z
  118.                 // 检测到停机标志1 ^/ m! F) E. g' `6 [* Y/ m
  119.                 if(isReadyToHalt == 1){$ t# ]8 l: f" D" T' @$ }' I& I& S# H
  120.                         // 暂时关闭定时器0中断& e0 L# z" o+ }  }) x$ C
  121.                         ET0 = 0;
    % j, Z  N0 F4 D- k8 u7 e; ~
  122.                         // 停机之前先把矩形波输出脚置低电平,以方便INT0和INT1唤醒CPU
    & ]  b  W. \# F) E* l% Y2 Y
  123.                         OUT = 0;) W, }* i( p9 e; T, x5 `
  124.                         // 停机之前先把低压指示灯灭掉,以省电
    9 t! L# x, R; \0 ?+ x; D, C
  125.                         LED = 1;
    * Q2 }4 X- D& I  Z
  126.                         // 进入停机模式
    * i- ]5 z4 t- X9 Z# ]
  127.                         PCON |= 0x02;8 ~* b+ ^+ @& F" [' N
  128.                         _nop_();
    . q2 _! {1 c4 y8 @
  129.                         _nop_();( Y: ]; C2 E' i8 P; W/ g- D  T' |: o9 o
  130.                         _nop_();
    3 L  U1 g$ _3 t1 G9 M
  131.                         _nop_();
    ( n7 I' r: j6 L& K0 _/ k
  132.                         // 唤醒,清标志位
    ( `5 x5 J! E" ]4 {0 l5 W0 Q0 O
  133.                         isReadyToHalt = 0;" r  {5 u2 r% q
  134.                         // 重开定时器0中断
    * j' V& ~4 v. T0 l! }
  135.                         ET0 = 1;
    : O/ S, h9 r2 ^4 d! y( s1 v$ k5 l
  136.                 }
    # ?1 Y$ j% W. R3 m7 `+ x  h! }
  137.         }
    " s" Y% a* w' b, X5 ?' b0 c
  138. }
    + @& X* u1 G8 y8 [
复制代码
  m* P: O+ v; g- H5 t8 w
硬件参数配置:/ F1 [, v' V( _" v2 @
7 G2 v& N+ K: f" Y; X  j0 B" |- Z

7 @# b2 C3 ?8 y9 }+ y2 y8 E( r接收端:
( D3 `! h" a2 G# h: d1 m/ o0 v
  1. #include <INTRINS.H>
    5 l* \$ {: j) k/ C4 P/ ?5 M
  2. #include "STC15W.h"
    , _6 t2 u* \7 P. p: W! }! D5 M
  3. + ]- p$ `/ y. n8 `+ A( Q- d

  4. * w1 a8 l9 k% J% V9 c. s
  5. /*! z* S/ t6 n* ]4 k( c2 V
  6. 0 E9 u( B( |0 N7 y; V# B  s
  7. *---------------------------*7 p3 d% G; a. v5 a# }
  8. |1 (GPIO2)         \__/  (GPIO1)16|
    % B9 N5 m. c. {  V  W
  9. |                                                        |1 l6 @2 ~3 r+ U5 \( N
  10. |2 (GPIO3)                   (GPIO0)15|2 l) p* m+ e3 m
  11. |                                                        |
    5 K  K* e9 R4 W( V2 e+ f. O7 F
  12. |3 (GPIO4)                                  14|( z) i: ?1 Z) i% a( }) Z# M
  13. |                                                        |
    , i8 y# P# H; W1 e
  14. |4 (GPIO5)                        (DATA)13|6 H( x9 R* j9 u( J# H  u
  15. |                  STC15W204S                |
    ! w) a3 S2 j  t" c; G+ _& u
  16. |5 (GPIO6)                   (LATCH)12|
    ; b8 g2 H6 t  e7 n8 s: i$ \
  17. |                                                        |
    3 I0 G4 u/ j9 g. h7 h# }
  18. |6 (VCC)                         (CLK)11|( F/ e; G* t! p2 b8 ~. p
  19. |                                                          |) A7 A* R5 W+ R
  20. |7 (GPIO7)                         (TXD)10|, v; d! r* m( h( T) a
  21. |                                                        |
    / ?5 |0 g* R- O+ Z4 z" E) f
  22. |8 (GND)                         (RXD) 9|
    8 k& `' I8 V% J; d" o$ _3 X6 T
  23. *---------------------------*0 G3 ?. Y0 ~2 q% a. w4 K! W
  24. Fosc = 12MHz  h' I$ ~) h$ u! R
  25. 5 k9 O5 v7 o, U: Y% D, f( [4 x  N" K
  26. P1.0 -> 上7 z. z" `9 e3 s0 b  p. B9 \
  27. P1.1 -> 左& K) P- L( k  {: Z0 k; B
  28. P1.2 -> 下
    3 ^. b& g5 C. q& v3 Q0 Q
  29. P1.3 -> 右
    " l: O; e3 d% m  w1 ~# Q  [
  30. P1.4 -> SEL: d1 X$ N0 [4 e, y- W' r# q
  31. P1.5 -> STA; _1 }7 j5 V' i
  32. P5.4 -> B& N) b- @4 n- ]8 y  w! I% O$ P
  33. P5.5 -> A
    + h1 B% q+ X6 S$ k
  34. - x2 d' _$ ^- Z# Q) c
  35. */# H3 k. y$ S% P. `! X
  36. 3 W4 G+ T  Z% h1 r/ r/ \. Z
  37. 8 s( _4 V2 n* q* o$ I! |
  38. sbit CLK        = P3^2;8 a0 _: d" D5 m/ b: S
  39. sbit LATCH        = P3^3;
    ' ?: Z" T3 M5 H
  40. sbit DATA        = P3^6;
    8 L6 D5 w* G& x
  41. 2 ?0 o% i+ d2 t- `0 n
  42. bit isReady = 0;% a- E% m9 z/ H9 o" ]; w
  43. static unsigned char key = 0;. c. X9 R7 L1 j
  44. static unsigned char buf = 0;        // 双缓冲。这个缓冲区保存从P1和P5组合而来的键值
    4 P6 G+ ]* M& {" W& I# k
  45. static unsigned char bufReady = 0;        // 双缓冲。这个缓冲区保存上面那个缓冲区的备份+ I0 _3 |. i5 Q% h' @# P7 ^
  46. static const unsigned char data mask[] = {0x80, 0x40, 0x10, 0x20, 0x01, 0x04, 0x02, 0x08};        // A B SELECT START UP DOWN LEFT RIGHT。为提升速度,这个表放到RAM中- @5 G" ?, F9 i5 U; v. M( R% H9 X
  47. static unsigned char idx = 0;
    : H3 D/ x* y- z; {2 s& o9 J' u
  48. " g3 x$ b) l( p7 c) w

  49. + t' f, j% h. ^( U. ]. l6 F
  50. static void GPIO_Init(){  D, @& O5 x5 W9 D7 i
  51.         // P1口和P5口用于接收并行信号,全部初始化为准双向,依靠内部弱上拉输出高电平
    " R9 B2 o, i) `8 u, c! J: r
  52.         P1M0 = 0;
    $ }. L3 Q- _9 u* Y) I% R3 l
  53.         P1M1 = 0;6 \3 s& \2 i3 ^2 f: X3 H0 v" R
  54.         P1= 0xFF;
      ^  D: x& f( C. A6 t
  55.         P5M0 = 0;
    , ^; m  L( I& P
  56.         P5M1 = 0;1 l3 ^) X/ z# G2 p* Z, Q- L
  57.         P5= 0xFF;
      l% A' X6 S7 K% k  X3 w+ q+ e3 B* P, b8 X
  58.         // P3口初始化为准双向
    1 T! T$ g7 a; c: c9 N; Q
  59.         P3M0 = 0;
    ( t% X1 g; j! Q; i
  60.         P3M1 = 0;
    $ R- I+ ], |5 k# I2 Y
  61.         P3 = 0xFF;3 n) e" `# J) }0 I; S9 O8 C
  62. }
    9 `# a2 y# a' J: r4 m4 L

  63. 2 T# B2 e2 d; p0 V  g0 d1 y# E
  64. static void Interrupt_Init(){
    % D$ J$ ?+ M8 ^! P5 k7 \
  65.         // INT0中断(CLK)触发类型为上升沿+下降沿
      F5 n5 z/ {7 r; X, z  E. x9 j& B
  66.         IT0 = 0;
    ' q9 g$ v- r0 A9 }" w/ @! R5 A
  67.         // 允许INT0中断
    " b; {* y! o; a- S4 s" E8 A
  68.         EX0 = 1;1 d$ \2 q2 r: f
  69.         // INT1中断(LATCH)触发类型为上升沿+下降沿
    5 |% B7 l; Q+ A2 h0 N
  70.         IT1 = 0;
    ( ^7 h, H3 U0 h7 C  ^; h6 }( @
  71.         // 允许INT1中断
    % k  C8 u' U" }2 @: }4 i
  72.         EX1 = 1;
    7 L5 |5 R/ G6 x5 {
  73.         // 开启全局中断
    , C! A2 f) K) b1 Y$ e/ }
  74.         EA = 1;
    , w  M& ^: n" Q1 o* F% A$ A& R
  75. }
    $ ]5 x2 L) U( V- ^, H8 q5 h( ^
  76. ; }: S( @5 M* q$ L  ]- P( F2 `- X
  77. static void INT0_Isr() interrupt 0{
    ; o/ u: Z$ u# ~" ^
  78.         // 只有已经成功锁存才允许CLK移位
    $ {" T, r: I- H& q; w3 D2 q
  79.         if(isReady == 0)7 @7 v0 i; [8 j& r' G: u$ l; |
  80.                 return;
    ) ~: q" w& |7 y) G9 Z# |6 y
  81.         // 读当前引脚电平,如果是低电平则说明是下降沿,此时直接忽略该中断
    7 y+ P! H7 W2 B  Z* s; w3 \
  82.         if(CLK == 0)
    1 x2 c! U7 r* `0 o
  83.                 return;
    + F8 l4 j' {( j1 u# W
  84.         // CLK上升沿到来的时候,取锁存值的下一位输出) X3 ?  Q! Q1 H; E
  85.         idx++;' z0 E5 C3 _+ |4 G! b* [* m8 C
  86.         DATA = key & mask[idx];
      P- |6 Q0 T) F; `
  87.         // 如果已经完成7次移位,则一轮读取完成! W* _* Y3 d+ X/ k8 M  \
  88.         if(idx >= 7)) o2 h; A% M% `1 Q( P7 L2 _
  89.                 isReady = 0;! X1 f9 B# W5 {! y1 d6 P
  90. }& ^, w* @( Y8 c5 R8 X
  91. ; i: q+ K, n3 i8 n, M- ?/ a
  92. static void INT1_Isr() interrupt 2{9 \( s4 c4 W2 T- T
  93.         // 读当前引脚电平,如果是低电平则说明是下降沿,此时直接忽略该中断
    " M; X/ H* }9 k( P& [7 r- j4 _/ K$ |
  94.         if(LATCH == 0)
    " ]- \5 N3 x! E& u" p$ z8 |  w
  95.                 return;/ X  A- ^3 K8 C7 C
  96.         // 当LATCH上升沿到来的时候,锁存所有按键状态,同时把键值A输出到DATA
    & x1 b, X9 ~/ J' |6 a. ^8 h
  97.         key = bufReady;# e1 Z/ l- e  _+ l/ _% k
  98.         DATA = key & 0x80;//mask[0];        // 为了加速运算,直接取表中的值而不是读表+ {; R$ m2 I2 i  v  |6 y
  99.         idx = 0;
    1 P* p* {3 v' {5 u0 A4 m$ Y
  100.         // 允许CLK进行移位' t" c3 q2 C' z/ S) B
  101.         isReady = 1;
    : n8 K5 _9 E3 ~8 T: q' k5 N2 }
  102. }
    % f) l  I7 i1 Q+ p* N! L
  103. 6 z  X% s6 C' |+ d
  104. void main(){8 c- v2 O# {+ M& ~. _
  105.         GPIO_Init();3 m, Q3 k% D4 X/ K
  106.         Interrupt_Init();- D* d9 ]$ V/ Q: u) k% I
  107.        
    7 O% u/ I- N$ p' Z6 z) e
  108.         while(1){
    & V4 R; _* h- L. f; s
  109.                 //PCON |= 0x01;        // 进入省电模式6 n5 F: y  T( B% \, ^, Y9 C
  110.                 //_nop_();7 t) k. z# |4 U+ H+ U; ]4 S0 Z7 Q* V
  111.                 //_nop_();+ ?2 }" q1 v  m" H
  112.                 //_nop_();
    / w6 V& R2 O2 h  B9 _- }8 O
  113.                 //_nop_();$ O; b  f1 D' e0 T! B3 ~
  114.                 buf = ~((P1 & 0x3F) | ((P5 << 2) & 0xC0));
    ( s. X/ [* @1 Y
  115.                 bufReady = buf;
    $ l! m' E0 o3 z# O2 g! T
  116.         }
    # L$ l% c: @& l0 z2 d8 s' L
  117. }( ^$ |0 J- e+ W2 z( a
复制代码
8 N; G. Q5 ~+ }# C
硬件参数配置无特殊要求,晶振频率选择12M即可。4 h' N, {7 C0 h7 y, K% G
/ _! q% r' P  i: B) ]
这是编译好的固件。

本帖子中包含更多资源

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

×

评分

参与人数 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' l; b) u1 p' M' T1 P# A
不错的设计,想问一下楼主,FC的15针公头怎么解决?普通的公头太短了,插不进去FC的扩展接口。 ...

" H7 O7 i0 A8 Z( w, ?" \9 d- N坛友的改造方案
回复

使用道具 举报

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

使用道具 举报

发表于 2019-5-25 12:07:18 | 显示全部楼层
精彩,楼主动手强,也写得很详细。
; I; [* V$ R0 V  G/ ~. k2.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; \8 v( l7 a: u7 |
精彩,楼主动手强,也写得很详细。) a9 E6 I( W: N7 b
2.4G方案是目前无线的最低延迟吗?
9 h* M" J* Z; P, `6 R
我没用过其他无线手柄,所以实在不知道我自己做的这个手柄到底是不是最低延迟。  h5 v" U! v# y  q3 Q$ w8 w& a
不过根据网上的说法,延迟高低主要是由通信协议的复杂程度,以及数据传输速率决定的。这个模块虽然是2.4G无线模块,但由于协议很简单,所以延迟比较低。
3 F& d4 S4 {0 j) y4 q+ \5 q我用这个手柄玩一些ACT游戏,比如超级马里奥、忍者龙剑传、热血系列,完全感觉不到延迟,和游戏机自带的手柄没有任何区别。唯一的区别就是这个手柄是用火花山寨手柄改造的,外壳是垃圾回收塑料,粗糙+脆弱,导电橡胶弹性不佳,手感不是一般的差。7 D/ @) J; x4 k7 r7 p
我手里还有十几张板子,等我有空了我再做一套,到时候买一个好一点的手柄改造。
回复

使用道具 举报

 楼主| 发表于 2019-5-29 16:56:14 | 显示全部楼层
ppad 发表于 2019-5-28 17:27$ X7 ~) E: V, w- E
给技术帝赞一个,有半成品发布吗,自己焊接改造就可以,编程实在不会啊 ...
% O" u# O# I* z1 t
很可惜,我手里没有多余的单片机了,LDO也找不到了,锂电池以及充电模块更是没有了。反正就是该用到的元件基本都没了,所以没法发布半成品。" G; C( b3 ^1 J9 n2 T2 ^
两个板子倒是有十几张剩余。' O1 L% J! m' `5 _$ [
你要是有USB转TTL串口板,完全可以自己买这两种单片机,然后我给你编译好的固件,你自己用串口板下载到单片机里面就行了。两个2.4G无线模块也得通过串口板用AT命令设置参数,不过好在我在设计电路的时候就已经预留好了串口,可以直接在线下载和在线设置参数。总的来说并不麻烦。
回复

使用道具 举报

 楼主| 发表于 2019-5-29 17:00:34 | 显示全部楼层
孙大师 发表于 2019-5-28 18:55; O, ~) V: m6 C9 h7 K
非常好,楼主是技术帝,到目前我都还没开发fc的无线套件,等空了,开发一套套件,等玩家自己组装。 ...

, H$ ]9 |3 h" \6 y9 m. E, J能得到孙大师的赞誉,不胜荣幸!8 \; p! r0 d: L5 U2 b
不如开发一个多功能手柄,比如用SFC手柄改造,L/R键配合其他组合键可以用来切换2P~4P、调节连发速度、软重启等各种功能。接收端插到15PIN扩展口。
回复

使用道具 举报

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

本版积分规则

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

GMT+8, 2026-2-7 11:42 , Processed in 0.109653 second(s), 15 queries .

Powered by Discuz! X3.5

© 2001-2025 Discuz! Team.

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