找回密码
 注册

QQ登录

只需一步,快速开始

查看: 18738|回复: 27

自制FC无线手柄

  [复制链接]
发表于 2019-5-22 14:16:45 | 显示全部楼层 |阅读模式
本帖最后由 雷精灵2046 于 2019-6-14 09:28 编辑 , c3 b+ q* }! v! U1 S0 t
5 \: A9 L2 a* B: c" a
没有用复杂的分立元件搭建发射接收电路,直接用的现成的2.4G无线模块jdy-40。
9 n0 D9 _2 a4 U% {+ k" I+ l5 m/ j& Z: z) b

& P& a1 }& Y7 R! W( H$ _$ m) i发射端靠3.7V锂电池供电,用了一片SOP8封装的STC单片机,负责产生连发脉冲,同时负责检测电池电量,电压低于3V左右的时候触发低压中断,低压指示LED就会亮起来告知该充电了。平时发射模块和单片机均处于睡眠状态,有按键按下才会唤醒,从而实现省电。实测睡眠状态下整机电流约1~2uA。板子洗了一下稍微干净了一点。因为对于微功耗设备来说,焊接残余的助焊剂可能会增加漏电流。
9 B/ H8 K, \/ v: {' r
. t) \1 m6 j' e% t. N3 \买了一个火花的FC山寨手柄,去掉里面的牛屎板子,并修正一下塑料挡板,把锂电池和充电模块装进去。6 {$ l; M+ p. W! H
为了减少体积,充电模块裁剪得十分小,并且更换了充电电阻使之适应这个小小的锂电池。这么小容量的电池,也不需要多么大的充电电流是吧?) q8 ?; ^1 X1 q. Q# B" T! X' T& F
然后统统用热熔胶粘上。充电电流比较小,所以发热很少,不会熔化热熔胶。
  p5 ^# ]# d1 ?+ ?/ ]
4 l! p! v7 g( f! }$ i$ o9 E( x% v& R) P4 u5 H. g9 ^0 c

4 l2 A/ B0 G! ]最后把按键、导电橡胶和电路板装上去。/ L0 L" _, z( \* ~) M
精心裁剪了电路板,正好扣上,不会阻碍其他元件,也不会影响后盖和拧螺丝。8 y) u8 s' ]5 b5 B

) |4 t- a9 b4 X) F$ I' ]3 a# H1 |4 J( x6 `* y9 [! y
完工!
8 e! Z7 v- |% ]
! d( H' r0 W0 d3 x7 [/ F2 d2 N
  }/ A8 ~3 d$ B7 f  o这是充电的MicroUSB插座。旁边的小孔用于透出低压报警LED的光线。1 ?! d7 \6 A0 e

* i+ G) G' M5 J1 n) b1 Q0 k* x$ \+ F8 y* j
接收端用一片DIP16封装的STC单片机模拟CD4021。为啥要用单片机模拟而不是直接用CD4021?因为jdy-40模块接收端在有按键按下的时候输出高电平,无按键按下输出低电平,和普通手柄正好相反。当然我也可以用两片74HC00或者74HC04之类的逻辑门进行反相,但那就增加了芯片的数量。对于FC手柄这种工作频率并不高的设备来说,STC单片机完全可以胜任模拟工作。
1 D2 ]5 b! y6 F5 _! x
) g8 g0 A, ~$ K! p  o0 R  b; F
- Z1 A# D9 |% }% T& d+ v$ F3 l! S* y+ X
电路设计有点小小的错误,所以有几根飞线。原本设计使用低压差LDO是XC6206,结果在做这个接收模块的时候,买的LDO居然找不到了!无奈只好用了AMS1117。幸好对于接收模块来说是5V降到3.3V,1117可以胜任。要是发射端手柄的话,3.7V降到3.3V,那就非得用6206不可了。
* U5 A5 A! j; z. I4 O" M
- d1 f# s& B. ]/ ?实测十分灵敏,延迟极小几乎感觉不出来。可惜这山寨手柄的手感并不佳,尤其是方向键,软塌塌的。看来我得买个剪线手柄改装。! F6 @, E. H$ n: T% u( b
7 _6 z2 L' ~' L% f8 p" V9 G9 j" q
这是电路图,有兴趣的朋友可以参考。3 J1 l- r( j% T) J: \' P* s

" C; J. f/ {. d/ u! w6 z6 G' `- m0 v& f4 _% ~3 Y
我信奉开源主义,十分痛恨把技术藏着掖着。好东西大家分享嘛!所以两个单片机的源代码大公开!+ Z8 k2 `! h/ }  N* R9 m/ W$ |* [
编译器:Keil 51。: j9 u/ R# @0 Y- l, s

/ O$ \1 r, J5 G' D& K% |7 |7 e' D发射端:' L4 Y/ }# x9 W2 N
  1. #include <INTRINS.H>& ]/ |# M' B5 s( H' i3 ^
  2. #include "STC15W.h"
    4 B* B3 ~! l% m# `9 M4 Y
  3. 7 W4 Z, E# U. @- O
  4. 5 O) T3 h2 ~) i) }
  5. /*; o2 N. W/ q+ W/ L( ^3 k8 d1 n
  6. --------------------------' _1 i6 z+ r5 N" O' o1 R
  7. |1 (OUT)        \__/   (INT1) 8|
    . k4 l% R  ]/ c! Y' u& l
  8. |                                                   |& s+ K  `' Q" O  m
  9. |2 (VCC)                   (INT0) 7|# Y( D" |0 D5 h( o" o) z
  10. |                 STC15W204S                   |0 d$ X, ]) l1 }9 w$ Y# a
  11. |3 (LED)                         (TXD) 6|; q3 a% {$ v) ^7 U$ P( Q2 k# |
  12. |                                                   |
      s6 D" x+ w' j4 B+ |$ g
  13. |4 (GND)                         (RXD) 5|3 W" x/ O" o3 ?( O; d$ y
  14. --------------------------
    * u. U% ^- u8 F2 p' n
  15. 8 \4 g1 i2 w$ [/ o
  16. LED ---|<|---[===]--- VCC4 R- i. m+ ?0 [. J; u+ o7 Y- L
  17.            Red          330
    6 n$ ^1 G- R0 k* Q/ w
  18. . g) E) U" n- x* I! m" k2 I8 v
  19. Fosc = 6MHz
    $ _1 ?& Y' B8 m' K+ R
  20. */
    4 z- C( v8 x( u7 ^% j& ^5 @; k, G

  21. % w9 V- A0 n- z' r1 N! x7 O" @

  22. $ j4 L) K3 l6 |% S- M  w
  23. // 矩形波输出脚) ~' ]  J' Y/ i6 h0 l) T) O
  24. sbit OUT = P5^4;. {4 c4 D4 u& i# q: q" E
  25. // 低压指示灯引脚
    5 s7 A9 O5 A" K# y  ^" k
  26. sbit LED = P5^5;
    / M) I+ k6 \& r. }( [  g6 a5 q, c

  27. 7 W7 P5 m! z5 ]  B
  28. // 停机标志位
    : h/ M6 [$ E1 x5 i* Q! {
  29. bit isReadyToHalt = 0;9 Z* B, t- Z0 p& i
  30. 8 |) ~$ _- m( o8 r
  31. // 矩形波次数累计: S6 a6 L5 T5 T/ \; x7 ?
  32. static volatile unsigned char count = 0;
    " ]9 e+ T3 g. K2 Q0 `+ j5 ^
  33. % A7 y  G& v0 ?8 P( ?

  34. & }* F7 W0 Q2 L: C8 Y4 \: h8 v9 S% M
  35. static void GPIO_Init(){
    5 O7 L' R8 f; ?' J' S
  36.         // P3口设置为准双向,默认靠内部弱上拉输出高电平" q* U6 U0 D) S: T
  37.         P3M0 = 0;
    - g) ]$ V& M9 a  z) m
  38.         P3M1 = 0;
    & E2 x+ }8 j& D6 R7 p/ p3 A  V
  39.         P3 = 0xFF;5 k1 G3 w! g4 \2 E0 [
  40.         // P5口设置为准双向,默认靠内部弱上拉输出高电平
    2 `" L  A# P, c5 l: o
  41.         P5M0 = 0;/ {2 o/ x6 r( V9 j" W
  42.         P5M1 = 0;
    4 T1 _8 r+ I% T. [) ^4 R% a
  43.         P5 = 0xFF;+ T5 I, ^* L8 ^. C
  44. }
    , c# r; D' x/ R3 X+ f( {

  45. - ~/ g8 U/ f$ w, A% H
  46. static void Timer0_Init(){
      d  e+ _8 C& Q8 w" G7 Z
  47.         // 16毫秒@6.000MHz
    * o4 P0 c+ j0 J, ]  }: N0 i* K
  48.         AUXR &= 0x7F;        // 定时器时钟12T模式
    + a$ b. t1 n  e$ Y
  49.         TMOD &= 0xF0;        // 设置定时器模式) {: g- O  y3 e$ U2 E0 a2 ^1 O
  50.         TL0 = 0xC0;                // 设置定时初值! h4 A& n- K# ?( f
  51.         TH0 = 0xE0;                // 设置定时初值
    9 [/ R. T, ~3 m$ ^; Y
  52.         TF0 = 0;                // 清除TF0标志
    ; k8 m/ c8 S( Q' n6 i8 ?8 ^
  53.         TR0 = 1;                // 定时器0开始计时
    : Z0 i1 [' j+ h, f) @9 o0 g& F
  54. }% g5 N5 t! {. B8 c

  55. $ A# o  D7 B& [6 A
  56. static void Interrupt_Init(){
    2 J- ?% J' h6 y6 o& W9 t
  57.         // INT0中断触发类型为下降沿触发  {) E( G. Z% x, s* ^7 Q
  58.         IT0 = 1;% W  t/ r7 a8 K+ U) J& G
  59.         // 允许INT0中断
    6 O& B# ?' `* x+ J) v: C3 M' n  P
  60.         EX0 = 1;
    6 H/ m/ ~: [; ^- k
  61.         // INT1中断触发类型为下降沿触发
    0 ^7 z  x6 y% X! J5 x
  62.         IT1 = 1;' z$ X" f! @$ P7 U5 y
  63.         // 允许INT1中断
    * u5 O: L( ^1 K8 ]% L
  64.         EX1 = 1;
    0 h8 `# n' [0 u9 P- W
  65.         // 允许定时器0中断0 W$ K6 @2 L, W6 C
  66.         ET0 = 1;
    . X. g2 F. n4 o3 x- F3 a  s7 |
  67.         // 允许全局中断5 @+ P; ~9 P5 p+ Q0 c
  68.         EA = 1;
    3 g8 g/ ?) V4 w- H1 \! m2 n
  69. }
    " x5 g/ {& u; t7 r% w$ `

  70. % [4 K6 L8 }8 t0 _
  71. static void INT0_Isr() interrupt 0{4 N# L4 l, y6 C# W
  72.         // 矩形波次数累计归零' L& ?+ t' @$ U+ n8 {
  73.         count = 0;) q  T2 P5 V# ?5 d
  74.         // 重开定时器0中断' V& ~! ]0 L% H; k0 s6 L
  75.         ET0 = 1;
    / j' O2 \  ?- ]5 V
  76. }
    . j  C. K$ B5 C9 v% y' w
  77. ! d9 `( Z8 X! x8 F8 J5 b5 D
  78. static void Timer0_Isr() interrupt 1{
    1 [" H& c8 v3 F  T
  79.         // 输出矩形波
    6 u, O9 [$ k- s4 ]; |
  80.         OUT = ~OUT;9 @- n7 C; ~% Z
  81.         // 累计矩形波次数$ s: _8 {5 B  E0 f8 M- K
  82.         count++;
    & [; M5 L& S1 c- ]6 E0 {
  83.         // 超过250个矩形波,准备停机. \! W& i/ w1 r4 o* z
  84.         if(count > 250){
    ' f  A* N* M& L' m
  85.                 count = 0;: x; O# n* l: Y/ t) Y! ~/ T
  86.                 isReadyToHalt = 1;
    5 u# f  {- L# s; K: U4 \2 G
  87.         }
    , |* i8 D7 P% |
  88. }- L+ G+ P5 p; D$ U" u9 `
  89. 4 l- C: D. ^# x, [  n
  90. static void INT1_Isr() interrupt 2{
    # s+ |+ [. x, c
  91.         // 矩形波次数累计归零
    5 q' X8 p: C7 p6 C0 K* p% F
  92.         count = 0;
    1 z, h4 C2 ?! s/ r! k+ [
  93.         // 重开定时器0中断
    & O; b) A( b7 R9 T0 x2 G
  94.         ET0 = 1;
    1 `# T& o3 q) h
  95. }
      w: m/ b8 Y- ?9 U5 y
  96. % d7 k. S' Y/ Z7 r# k% ^5 U
  97.   d1 K& I  X" T# e0 W- F
  98. void main(){
      O" X( K' z7 G2 Z+ F
  99.         // 初始化P3和P5口% c! L( E" j5 t* W) b: ~# h( ]+ F
  100.         GPIO_Init();% n7 u- Y1 Y6 T" E2 I: k/ T* l
  101.         // 初始化定时器0
    & H$ d: d! |1 u, A1 M6 ?: [, z
  102.         Timer0_Init();
    ' x& H8 T$ k/ p! Y& i$ R0 @
  103.         // 初始化中断) c( A( N$ ~; Y$ r" U' W/ T
  104.         Interrupt_Init();
    + |/ P& O* k6 a
  105.         : p* d* u0 J7 }) Q( q/ T% v* ^
  106.         while(1){
    1 a7 ?, z( T" M# Z
  107.                 // 检测电量! ~5 Y1 ]$ b" @( c# m% G
  108.                 if(PCON & (1 << 5)){
    + C& D" _% h! \$ x
  109.                         // 如果电量低,低压指示灯亮
    " `0 i: [8 L7 ]( I5 v4 f
  110.                         LED = 0;
    1 j' g3 O+ Y0 B9 ?4 h6 F5 ?; r* P
  111.                         // 清电量检测硬件标志位
    % }. `# i, k0 `/ R$ `5 `
  112.                         PCON &= ~(1 << 5);
    ; i! r9 Z- N& U" f9 t6 g: @7 s  b+ G
  113.                 }else{4 F; M* Z/ e" M7 L& i6 o  D4 G
  114.                         // 电量正常,低压指示灯灭
    . w  I2 d: [, s( ?" V
  115.                         LED = 1;
    " p6 G/ n: v3 r, `! h. p
  116.                 }
    % x2 i! j- F, L* q" K7 X) l

  117. ; Q" V! v' u/ n2 ~4 t% u+ U1 T
  118.                 // 检测到停机标志% d2 A' |) \  v" N. m0 H
  119.                 if(isReadyToHalt == 1){7 j8 f% y1 u2 s9 T  W
  120.                         // 暂时关闭定时器0中断& }' B) R& }, ]! u7 I4 X
  121.                         ET0 = 0;
    3 {1 w8 t! b% x" N/ h
  122.                         // 停机之前先把矩形波输出脚置低电平,以方便INT0和INT1唤醒CPU
    ! Q% Z1 x+ F7 [$ l  q. Z9 E9 E
  123.                         OUT = 0;
    - W! X3 n$ \  W2 X# Z
  124.                         // 停机之前先把低压指示灯灭掉,以省电
    . G) ~* Y/ Y3 S7 E; x
  125.                         LED = 1;9 H% I: M) G) j/ b6 ^. ^1 Q
  126.                         // 进入停机模式* P% k: u# \1 X: w/ J& M3 U
  127.                         PCON |= 0x02;, ?/ k5 C' H- N: W0 ~
  128.                         _nop_();
    , k& P( o! s" ~/ L& s% B  [4 D1 U
  129.                         _nop_();; `1 y1 `0 Z5 g. s2 j7 ?; e4 Q
  130.                         _nop_();
    6 j: N1 T" \  ~1 j# |3 d" U
  131.                         _nop_();. z2 v6 ^9 _3 q4 Z: |
  132.                         // 唤醒,清标志位$ `" m5 s7 W7 y) S
  133.                         isReadyToHalt = 0;& {" N) R- P3 I+ l! R, G: X
  134.                         // 重开定时器0中断  w& Y# U, J$ u! P3 p
  135.                         ET0 = 1;1 d" J# O: _& L5 Y: X* s& Z; j4 h
  136.                 }! b6 K+ M! S' }6 |
  137.         }
    ) t' ]: j/ ]" P
  138. }$ R; o, ], c  R! j+ F' X
复制代码
: V. O) _+ T8 `
硬件参数配置:: S" |! ]5 K2 Z0 `9 c2 ~2 J; W

# ?4 ^9 W9 u  e( e6 \/ q. \! z7 p  v
接收端:3 `+ n$ h. |8 e6 b/ w
  1. #include <INTRINS.H># d4 j& W& T% P. L
  2. #include "STC15W.h"2 t4 J. [9 ^: ~( u

  3. ; F6 M" {; ?0 F; `1 C
  4. 8 d$ w% u; J; L! K6 U- o8 s
  5. /*$ D8 g+ |" d9 K; V; h
  6. , O; C- A1 P1 J2 u/ S
  7. *---------------------------*  F! K; O8 o3 N2 q6 O2 X% e
  8. |1 (GPIO2)         \__/  (GPIO1)16|8 L9 c1 _. }  D) U: B3 f
  9. |                                                        |
    ' l4 z/ ^  s) |9 D
  10. |2 (GPIO3)                   (GPIO0)15|0 D' Z0 V  p; r3 v3 [6 h
  11. |                                                        |
    ! N- S2 r' |  I- D, q
  12. |3 (GPIO4)                                  14|+ Z' s3 O, a% y3 Q% b$ j
  13. |                                                        |. w/ n* ~( C$ w
  14. |4 (GPIO5)                        (DATA)13|. j# [3 B% m( @1 Y( R
  15. |                  STC15W204S                |3 s; s, L: _) U. C
  16. |5 (GPIO6)                   (LATCH)12|
    , X3 R& U. _( @
  17. |                                                        |* ~( Y' W9 [# v6 Q+ P) t+ J
  18. |6 (VCC)                         (CLK)11|; i+ s$ d* e1 {
  19. |                                                          |
    & J( ?+ ]5 Z0 E1 B# I4 C; e
  20. |7 (GPIO7)                         (TXD)10|) }* q4 g2 w# {3 H
  21. |                                                        |
    ( @+ |4 \0 _9 E# L3 I
  22. |8 (GND)                         (RXD) 9|
    2 R* y% I" P6 c
  23. *---------------------------*
    * v) i3 ^" b/ Y
  24. Fosc = 12MHz
    ' \/ t3 h7 \, E: u/ ]( e6 R6 \) M" U

  25. ! k) q; t4 a6 T( ]" C
  26. P1.0 -> 上
    / R8 F& S2 g; o" W8 l! \7 Q8 _( p
  27. P1.1 -> 左8 d9 `" [6 O0 Y+ T8 j5 d
  28. P1.2 -> 下
    8 }1 {+ {) E1 F' N( t8 [  J& P2 |$ N
  29. P1.3 -> 右, u7 O% u" H3 ~, ^) Z
  30. P1.4 -> SEL
    . b' T; V8 s& V
  31. P1.5 -> STA
    ' [. ?  {% x: T
  32. P5.4 -> B
    : c) y8 j9 k8 ~6 K
  33. P5.5 -> A
    + ^- o3 }0 X/ d) A1 n

  34. # O8 i5 }* o* x. V" T# B0 y1 V) S
  35. */
    $ j/ V, T+ o" U5 ?. ?% }" Z( u' m
  36. ! {4 }8 i% g( ~9 O% u6 o- ^! l
  37.   K! H  H  s$ e" t( ~8 Y; G
  38. sbit CLK        = P3^2;8 ~. E, K6 [* x1 f
  39. sbit LATCH        = P3^3;, M& ^1 s" C" I7 Z& W& ?  d
  40. sbit DATA        = P3^6;+ t, o4 p  s4 V! N" k/ H+ w$ [: z

  41. 7 S2 f8 {, E; U) B# A, i
  42. bit isReady = 0;
    6 {! r0 x# \( w  h+ y
  43. static unsigned char key = 0;
    ) |2 t2 \) }" c; s3 a7 \
  44. static unsigned char buf = 0;        // 双缓冲。这个缓冲区保存从P1和P5组合而来的键值
    4 B' X  X# B: g0 p; q3 [
  45. static unsigned char bufReady = 0;        // 双缓冲。这个缓冲区保存上面那个缓冲区的备份
    7 U6 x" y# p7 Z7 f2 E
  46. static const unsigned char data mask[] = {0x80, 0x40, 0x10, 0x20, 0x01, 0x04, 0x02, 0x08};        // A B SELECT START UP DOWN LEFT RIGHT。为提升速度,这个表放到RAM中4 T. q# \9 d/ Y0 Z
  47. static unsigned char idx = 0;
    " [% W+ x! ?: |9 G7 B" W4 x  d

  48. , b- x+ l5 L  g1 }: c
  49. ! X* r: r9 I; J' ]  p( T6 Y
  50. static void GPIO_Init(){
    7 U: e$ X8 s) _+ S6 _: X/ }
  51.         // P1口和P5口用于接收并行信号,全部初始化为准双向,依靠内部弱上拉输出高电平% K. \4 p& W9 C0 \& @
  52.         P1M0 = 0;
    % X- R4 G; n6 a& g) H
  53.         P1M1 = 0;
    3 `" M/ G( v$ ]! e$ F9 y
  54.         P1= 0xFF;
    & t& A% o# |2 `2 S) [# s. l
  55.         P5M0 = 0;3 N* u8 l8 p8 M, h; F& U
  56.         P5M1 = 0;* m$ K0 M. D* w& ^
  57.         P5= 0xFF;( `2 W2 K4 m! m& T' d5 z
  58.         // P3口初始化为准双向) {. `& y( n- F" C
  59.         P3M0 = 0;
    ) y# G; x. c3 K1 j4 G
  60.         P3M1 = 0;5 u* m6 |# z/ j9 {7 W
  61.         P3 = 0xFF;$ S' \/ ~3 E: Z; G2 N# A
  62. }
    , _7 {" u. B- n7 ]7 O: Z+ n- N( W
  63. 2 A4 ?1 Q- f4 S9 Q8 R
  64. static void Interrupt_Init(){$ K# Q. ]  O- Q6 ~! [. N
  65.         // INT0中断(CLK)触发类型为上升沿+下降沿
    & d* ~1 V1 J5 |( T. z
  66.         IT0 = 0;
    + f8 n+ j0 J4 g% U; J3 z8 J
  67.         // 允许INT0中断
    $ o4 E/ r" n& C) U& L! B
  68.         EX0 = 1;$ |; t" Q4 l% Y. c! I7 l
  69.         // INT1中断(LATCH)触发类型为上升沿+下降沿. ^* k  x8 U9 `- a2 O6 O9 K
  70.         IT1 = 0;1 I, N3 z$ {+ ]6 p8 g
  71.         // 允许INT1中断
    " G, N" I7 v2 V+ s4 X
  72.         EX1 = 1;
    + O! y) L, ?+ W! T' [8 m
  73.         // 开启全局中断
    2 h4 ?' q" _0 A' A7 p' w$ \
  74.         EA = 1;& y2 X4 t+ G5 s5 C/ n6 F) X' U3 `
  75. }- S9 M% u# u+ ?! E

  76. ( y6 D5 A, {/ }: D6 A$ B+ l$ K
  77. static void INT0_Isr() interrupt 0{
    3 g9 A; }5 g! k& `
  78.         // 只有已经成功锁存才允许CLK移位5 X4 ^$ z, e8 T1 V7 f9 m. Y
  79.         if(isReady == 0)
    & ?; s9 L- p3 b
  80.                 return;- K" c( ]; j# J0 ]0 I2 ~. N
  81.         // 读当前引脚电平,如果是低电平则说明是下降沿,此时直接忽略该中断2 X  V' [- i0 @
  82.         if(CLK == 0)& J: c0 _$ ?7 e9 S( W' A; R
  83.                 return;
    $ K* K1 X( j9 G; `  ]6 ?. j
  84.         // CLK上升沿到来的时候,取锁存值的下一位输出
    6 J/ m5 g/ V$ H! s$ l8 c% {
  85.         idx++;
    3 V8 B6 `$ O! m, J) ^* t
  86.         DATA = key & mask[idx];) F) `4 c- r2 N; j1 u
  87.         // 如果已经完成7次移位,则一轮读取完成9 {- K) K* a1 n+ }( Y% m- f
  88.         if(idx >= 7)
    5 N' j- `4 b* G/ e
  89.                 isReady = 0;
    9 `% O9 r& U$ j. t9 ~& N( @5 D
  90. }: g. k3 e' y! }" b3 f; {$ ~" U2 a

  91.   C9 v" S- z1 [6 N0 [' O
  92. static void INT1_Isr() interrupt 2{
    % |: E. _, N/ V) _; Z: P/ u
  93.         // 读当前引脚电平,如果是低电平则说明是下降沿,此时直接忽略该中断! P+ w4 y4 e6 K( [6 M4 l2 V
  94.         if(LATCH == 0)
    ' Y6 P6 D3 `7 h/ O
  95.                 return;2 D  \* \4 y; |3 d, D. W% P
  96.         // 当LATCH上升沿到来的时候,锁存所有按键状态,同时把键值A输出到DATA
    5 N. z7 O8 L9 |' s3 X
  97.         key = bufReady;
    # U# w$ F. N" L/ B
  98.         DATA = key & 0x80;//mask[0];        // 为了加速运算,直接取表中的值而不是读表
    ( x+ e- S$ k) l! B
  99.         idx = 0;
    1 j5 P' v+ H! A; @
  100.         // 允许CLK进行移位. P$ ~$ B6 t; ~, [
  101.         isReady = 1;
    $ f/ L! f6 ]% @1 e( p& t
  102. }
    1 ~2 t% S4 E, D3 e! X7 n7 `

  103. ) {2 J, m! X# X8 W5 T( O, K8 m# r
  104. void main(){
    " F) }3 ?! R8 V
  105.         GPIO_Init();
    9 \' ~( `# A+ j$ \) i
  106.         Interrupt_Init();
    ; b8 O; c! f6 j; b9 v/ C  L% c! s
  107.         ( `2 y) L& j" N
  108.         while(1){
    7 B2 l1 s$ E, B. R, M1 R/ t$ k
  109.                 //PCON |= 0x01;        // 进入省电模式6 b7 o% Q: P: c1 {( @
  110.                 //_nop_();- j6 l9 E$ w5 Y, q4 }
  111.                 //_nop_();* W2 V" e! |7 n5 }) I8 e1 j* I
  112.                 //_nop_();
    4 ^9 @; X: K! ?+ T" P! K
  113.                 //_nop_();$ N4 V; {6 K4 ~
  114.                 buf = ~((P1 & 0x3F) | ((P5 << 2) & 0xC0));
    & U3 o) D4 K/ s# n7 K! v8 ?
  115.                 bufReady = buf;( H8 v+ Y. _( \8 m6 J
  116.         }
    9 ^$ R+ J4 P& \, v3 }: I
  117. }8 X. z0 d5 {) E2 o( k/ N
复制代码
  W9 x8 O8 q+ {
硬件参数配置无特殊要求,晶振频率选择12M即可。% O- D6 d$ j4 q4 _3 v4 I" R
6 H% w% w5 j; ^
这是编译好的固件。

本帖子中包含更多资源

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

×

评分

参与人数 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
4 V6 u3 \& H* H- [7 s不错的设计,想问一下楼主,FC的15针公头怎么解决?普通的公头太短了,插不进去FC的扩展接口。 ...

, R, S0 \" ^2 Z2 y  n坛友的改造方案
回复

使用道具 举报

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

使用道具 举报

发表于 2019-5-25 12:07:18 | 显示全部楼层
精彩,楼主动手强,也写得很详细。, i0 I/ w5 C# L1 Y& S
2.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
* Z1 E: J+ N2 U精彩,楼主动手强,也写得很详细。
& l3 n' I) J. W+ D2.4G方案是目前无线的最低延迟吗?

$ c4 f6 u) f5 C7 G我没用过其他无线手柄,所以实在不知道我自己做的这个手柄到底是不是最低延迟。
5 z2 c- }4 b2 d, t. a不过根据网上的说法,延迟高低主要是由通信协议的复杂程度,以及数据传输速率决定的。这个模块虽然是2.4G无线模块,但由于协议很简单,所以延迟比较低。
- |, r) ~8 T0 a/ _我用这个手柄玩一些ACT游戏,比如超级马里奥、忍者龙剑传、热血系列,完全感觉不到延迟,和游戏机自带的手柄没有任何区别。唯一的区别就是这个手柄是用火花山寨手柄改造的,外壳是垃圾回收塑料,粗糙+脆弱,导电橡胶弹性不佳,手感不是一般的差。
. k1 O7 R  y9 N9 w: i我手里还有十几张板子,等我有空了我再做一套,到时候买一个好一点的手柄改造。
回复

使用道具 举报

 楼主| 发表于 2019-5-29 16:56:14 | 显示全部楼层
ppad 发表于 2019-5-28 17:27
8 u* m, B% _3 P9 A1 i2 Q给技术帝赞一个,有半成品发布吗,自己焊接改造就可以,编程实在不会啊 ...
; |( ~% W: X% |8 m9 s+ Z
很可惜,我手里没有多余的单片机了,LDO也找不到了,锂电池以及充电模块更是没有了。反正就是该用到的元件基本都没了,所以没法发布半成品。
/ y8 K4 d! W3 ~! t# q4 ^$ W两个板子倒是有十几张剩余。
% `2 h* O$ G# h& X你要是有USB转TTL串口板,完全可以自己买这两种单片机,然后我给你编译好的固件,你自己用串口板下载到单片机里面就行了。两个2.4G无线模块也得通过串口板用AT命令设置参数,不过好在我在设计电路的时候就已经预留好了串口,可以直接在线下载和在线设置参数。总的来说并不麻烦。
回复

使用道具 举报

 楼主| 发表于 2019-5-29 17:00:34 | 显示全部楼层
孙大师 发表于 2019-5-28 18:55" A) e5 B$ K" |$ @8 u
非常好,楼主是技术帝,到目前我都还没开发fc的无线套件,等空了,开发一套套件,等玩家自己组装。 ...
8 y) E! C1 i9 z& `! C8 y# D
能得到孙大师的赞誉,不胜荣幸!
4 N/ d8 v1 h0 }( M1 H8 i8 ]不如开发一个多功能手柄,比如用SFC手柄改造,L/R键配合其他组合键可以用来切换2P~4P、调节连发速度、软重启等各种功能。接收端插到15PIN扩展口。
回复

使用道具 举报

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

本版积分规则

Archiver|手机版|小黑屋|Video Game Do It Yourself ( 闽ICP备14000865号 )

GMT+8, 2024-12-28 06:52 , Processed in 0.462661 second(s), 14 queries .

Powered by Discuz! X3.5

© 2001-2024 Discuz! Team.

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