电玩DIY [ VG DIY ] - Video Game Do It Yourself

 找回密码
 注册

QQ登录

只需一步,快速开始

查看: 14728|回复: 27

自制FC无线手柄

  [复制链接]
发表于 2019-5-22 14:16:45 | 显示全部楼层 |阅读模式
本帖最后由 雷精灵2046 于 2019-6-14 09:28 编辑
7 a% O/ G4 I  T/ M. N$ W5 s
" M9 r) g/ t' ^4 U没有用复杂的分立元件搭建发射接收电路,直接用的现成的2.4G无线模块jdy-40。
6 C) O+ k( C3 D1 J; z+ q. |  E) f+ U7 y5 `$ O/ }
6 b5 x2 d8 h, l$ ]$ L. S7 z
发射端靠3.7V锂电池供电,用了一片SOP8封装的STC单片机,负责产生连发脉冲,同时负责检测电池电量,电压低于3V左右的时候触发低压中断,低压指示LED就会亮起来告知该充电了。平时发射模块和单片机均处于睡眠状态,有按键按下才会唤醒,从而实现省电。实测睡眠状态下整机电流约1~2uA。板子洗了一下稍微干净了一点。因为对于微功耗设备来说,焊接残余的助焊剂可能会增加漏电流。
: Z! A& R  r% R7 V! O/ X  c) s7 j7 Q: W
买了一个火花的FC山寨手柄,去掉里面的牛屎板子,并修正一下塑料挡板,把锂电池和充电模块装进去。+ f$ i$ c) O* \4 P4 ]8 Y5 m& w+ Y# o
为了减少体积,充电模块裁剪得十分小,并且更换了充电电阻使之适应这个小小的锂电池。这么小容量的电池,也不需要多么大的充电电流是吧?: z9 {& f( ~; L4 [  N$ K
然后统统用热熔胶粘上。充电电流比较小,所以发热很少,不会熔化热熔胶。; q: @, ]. S2 O& @# _

+ u/ T( d  D+ p4 X$ Z
5 g; k* k. A; r( k1 m# [2 M2 t
5 e# C0 P2 f7 X/ X最后把按键、导电橡胶和电路板装上去。
3 {' }: V; m2 j7 j精心裁剪了电路板,正好扣上,不会阻碍其他元件,也不会影响后盖和拧螺丝。5 I  V% s. i  B; l+ T
8 i: G6 ?$ J. w% @4 Y$ M3 V
8 A7 Y: i+ b" ]& |) C! x
完工!9 C( s9 X" }% v* X* s/ |
& k" P+ o7 P( p9 [) Z2 S3 e

# b; J& [+ ~$ ~! n' f这是充电的MicroUSB插座。旁边的小孔用于透出低压报警LED的光线。
' e* e$ P& u) j  Z/ N, q1 p7 d8 o1 _6 y$ g3 W

. T7 ?  |2 d+ ~# q/ k5 n6 S- k接收端用一片DIP16封装的STC单片机模拟CD4021。为啥要用单片机模拟而不是直接用CD4021?因为jdy-40模块接收端在有按键按下的时候输出高电平,无按键按下输出低电平,和普通手柄正好相反。当然我也可以用两片74HC00或者74HC04之类的逻辑门进行反相,但那就增加了芯片的数量。对于FC手柄这种工作频率并不高的设备来说,STC单片机完全可以胜任模拟工作。
! ^% s& |# s# Q# q( d+ g
1 n% G* o7 @4 N+ n# }
  F! y) j0 c; O: C
7 W+ d& d  P: \6 R1 `+ e电路设计有点小小的错误,所以有几根飞线。原本设计使用低压差LDO是XC6206,结果在做这个接收模块的时候,买的LDO居然找不到了!无奈只好用了AMS1117。幸好对于接收模块来说是5V降到3.3V,1117可以胜任。要是发射端手柄的话,3.7V降到3.3V,那就非得用6206不可了。8 h# t- {9 q7 w; u

' m& S2 o$ f3 m8 F! D实测十分灵敏,延迟极小几乎感觉不出来。可惜这山寨手柄的手感并不佳,尤其是方向键,软塌塌的。看来我得买个剪线手柄改装。
9 ^7 A- {: ^( u1 i- U! Y# Z1 L
; i* I# J( p; Y! r" Y0 t) }这是电路图,有兴趣的朋友可以参考。- d, S! ]( b9 E) u. c

/ f2 U2 u+ B( B: \/ T
% O5 h( Q( u* D" w3 O我信奉开源主义,十分痛恨把技术藏着掖着。好东西大家分享嘛!所以两个单片机的源代码大公开!
2 y% i% A# M! n: K/ t; O9 K+ Y1 R编译器:Keil 51。
6 P  b# J" M% e6 {  E0 W' E& @: W8 Y! I0 f& K5 }) e# n9 F; ~
发射端:8 A$ T: k# L- A1 |) o; O
  1. #include <INTRINS.H>! ?& p7 S2 R; R. T- i% Z
  2. #include "STC15W.h"7 J1 ]1 X  e( H% J6 K' g. I& J

  3. . b2 c; ?) a8 e+ y
  4. / Y' j5 f7 m4 y; D
  5. /*% B; b) z' k6 f
  6. --------------------------
    0 _: T, q( g! m# G
  7. |1 (OUT)        \__/   (INT1) 8|
    9 V. R8 m6 l; t
  8. |                                                   |
    9 B; _  C' v5 I; e! D3 `
  9. |2 (VCC)                   (INT0) 7|
    " d+ j7 ?3 a, \: R  [9 m+ T' c3 ^
  10. |                 STC15W204S                   |( l' v: D9 y/ O/ u
  11. |3 (LED)                         (TXD) 6|
    : n8 J5 ?* T1 U0 \
  12. |                                                   |
    0 C8 O  t1 V: s' Z; M
  13. |4 (GND)                         (RXD) 5|
    . ^; I# A0 g8 _* T
  14. --------------------------
    + O4 Y& x) q/ t. o* q1 P0 R

  15. ' I6 }: B7 }) N9 Y
  16. LED ---|<|---[===]--- VCC
    ; @5 p) g# B" e# |/ n- i; X" x2 d
  17.            Red          330
    0 K% y: e* u- ]  i( F* `/ B

  18. 5 v$ Z% v3 d! q' w
  19. Fosc = 6MHz
    . T" ], {5 z( S. q" R; _, `5 _
  20. */2 i$ x- y6 ~6 ]4 U2 k0 z0 A

  21. . b/ H* k# x$ l9 A; X
  22. + \7 j- f" ?4 K" K7 \& R5 i1 r. Y
  23. // 矩形波输出脚& s6 s+ H$ U" h* `. \1 u
  24. sbit OUT = P5^4;8 W& w8 W) R  x1 w9 Y
  25. // 低压指示灯引脚
    4 r9 F# P! p% R( ?6 Q2 p5 P
  26. sbit LED = P5^5;
    : M. \+ x- Y* h8 V6 X! A
  27. ) \# z5 Z6 r9 A- O
  28. // 停机标志位
    7 G7 B# Q; A% `4 R8 O4 A# T3 E
  29. bit isReadyToHalt = 0;
    ! O( K1 w4 N& `
  30. 7 C% G4 Z% f& A( l# _  D+ n" b/ O
  31. // 矩形波次数累计, B. `/ J- U1 d# [3 W
  32. static volatile unsigned char count = 0;. A: `% U4 R7 i; v
  33. 5 u! u! O) z0 M7 A# b1 Q' b
  34. # E# O5 k7 R" j) W1 R
  35. static void GPIO_Init(){
    : ?( f! f1 ]7 ~( P
  36.         // P3口设置为准双向,默认靠内部弱上拉输出高电平
    - [. i& |2 K5 t! d+ _  f; Y
  37.         P3M0 = 0;/ n/ z; n& d8 ]$ }
  38.         P3M1 = 0;
    % h; H- Q9 t: R& N) A
  39.         P3 = 0xFF;5 g  C4 ?) R/ k7 E. t8 v& O: u
  40.         // P5口设置为准双向,默认靠内部弱上拉输出高电平
    ! R; K* l/ E# |1 o
  41.         P5M0 = 0;- ~1 D# r! d% e  o8 M
  42.         P5M1 = 0;3 D0 V, f) }+ l2 M* E
  43.         P5 = 0xFF;$ ~0 J' ~3 P. t8 x( W
  44. }: {$ h3 f0 v4 _; o, T: B5 K

  45. ! r7 s/ {: |- U1 H4 M
  46. static void Timer0_Init(){$ v6 g9 }9 N) T' I3 b- s, B
  47.         // 16毫秒@6.000MHz; ^& }: ~, g$ ?2 l; T7 e- {
  48.         AUXR &= 0x7F;        // 定时器时钟12T模式/ B; L; A: Q* C0 u9 U5 @  x0 g& Z% V5 x
  49.         TMOD &= 0xF0;        // 设置定时器模式
    ! D2 b+ E( j+ }& X
  50.         TL0 = 0xC0;                // 设置定时初值
    , }% f0 U0 g+ x  w6 G. F
  51.         TH0 = 0xE0;                // 设置定时初值' v  Y/ _& s/ M  Y# F
  52.         TF0 = 0;                // 清除TF0标志
    ( u! b0 u) M9 k; a! c: ~
  53.         TR0 = 1;                // 定时器0开始计时& }) ]0 Y" p: t, r: K5 A
  54. }/ K$ F8 m( h9 l1 F! p; N3 f

  55. 8 Z! A: b$ U! N7 K( \, @
  56. static void Interrupt_Init(){
    ' ~% z- K+ E- F1 P4 I
  57.         // INT0中断触发类型为下降沿触发
    / ~5 t' y# r; [
  58.         IT0 = 1;
    # n4 s  H+ e# @  ?
  59.         // 允许INT0中断
    8 S* S# W6 [  D8 H$ E
  60.         EX0 = 1;
    7 N! O2 j9 `7 v5 q0 J( U& l8 G
  61.         // INT1中断触发类型为下降沿触发
    3 W# }- c2 u3 V$ p
  62.         IT1 = 1;+ f4 ~1 ?# |% H. O( l
  63.         // 允许INT1中断
    1 a4 u' a  J6 I0 X4 i9 n
  64.         EX1 = 1;8 ^/ i( b5 P2 @6 u1 U& f
  65.         // 允许定时器0中断
    : K# w& e/ d- S7 U( f  s
  66.         ET0 = 1;. ]- V  y9 q& X; h$ Q, u% X( C0 {
  67.         // 允许全局中断
    / {1 o% e+ C0 @0 S2 F+ H
  68.         EA = 1;/ J) N: V6 i% w! a$ u% Z* g
  69. }7 y/ T+ S  R& v: |- X0 p& B
  70. & f& k8 O/ ]& [1 x0 f
  71. static void INT0_Isr() interrupt 0{9 T/ F+ J, j1 q, S* [! N
  72.         // 矩形波次数累计归零7 M9 t' U* Y6 F2 I) }0 E/ `
  73.         count = 0;4 q" d+ C  W9 _+ r  F( t
  74.         // 重开定时器0中断
    3 F# P& e# _1 y8 s3 j, M
  75.         ET0 = 1;
    $ Q# c8 }7 }0 ~. i2 k' h; j
  76. }
    5 T/ @( Y5 ]: q, T' ]6 H
  77. 6 |/ i# Z8 w0 ]) z4 m7 |
  78. static void Timer0_Isr() interrupt 1{+ G' n) U/ {" e4 O$ [
  79.         // 输出矩形波' Q+ I1 n9 n7 ^( v9 T
  80.         OUT = ~OUT;* W# u! R- I& F1 d/ T
  81.         // 累计矩形波次数
    " y; _0 z0 F0 H
  82.         count++;0 b" [# k6 Y& i$ m" [+ E2 B1 z
  83.         // 超过250个矩形波,准备停机& G! `. e5 j  N0 {: g& h! P6 z6 Z% N
  84.         if(count > 250){
    6 c, M+ T1 \( x6 W# G% x% q: f
  85.                 count = 0;
    : o' O" ~' z, ^- o5 O
  86.                 isReadyToHalt = 1;
    2 D& Z. n& t) t' g, f! e+ \( r
  87.         }
    $ X. t% M* r8 y/ r* G
  88. }+ f0 e* s8 |* ]8 ], R$ W
  89. 4 K5 J  e/ c( A/ \
  90. static void INT1_Isr() interrupt 2{: E8 d7 p8 `$ u" t2 c9 T- n
  91.         // 矩形波次数累计归零$ T8 A) l: h; y5 S! J' u( p
  92.         count = 0;7 W& c. ^. |5 J" R$ ?, x& r
  93.         // 重开定时器0中断
    ' A& G  f2 A# }4 p" g1 k, i
  94.         ET0 = 1;9 X0 I. T8 k, y" V
  95. }
    0 P: a/ O; R/ x% X
  96. ) a- j3 F) ]7 s; b2 y6 Z5 S

  97. * {) l- Y, a; h- U. K1 c9 M
  98. void main(){
    0 ?0 P4 b$ B. h$ g( ~2 Z' G
  99.         // 初始化P3和P5口
    * @8 {, J+ [' x6 j" t
  100.         GPIO_Init();& [  z, H* a$ T( v% _8 f3 I+ k; A
  101.         // 初始化定时器02 C) A/ O! p4 Z4 ^  W, {% M
  102.         Timer0_Init();. O6 m4 m6 L) Q& M3 {5 H
  103.         // 初始化中断
    " {8 ?% g' c( [
  104.         Interrupt_Init();1 Y) C( i) _3 P  f' l' f
  105.        
    ' D8 [1 b) d# m+ g; d
  106.         while(1){
    . W- O1 L) d7 Y- a6 S8 i) J
  107.                 // 检测电量, \' T5 E. c4 K
  108.                 if(PCON & (1 << 5)){
    ' [/ Y4 F, L9 [3 d0 ]( o
  109.                         // 如果电量低,低压指示灯亮
    : A  P* ]' G$ s+ N, K! c3 e2 ~$ N
  110.                         LED = 0;. ]0 J6 ?% a8 ~) X& b3 e& ^
  111.                         // 清电量检测硬件标志位
      {/ @6 T6 n1 q2 }
  112.                         PCON &= ~(1 << 5);/ j4 ]& g: r; P
  113.                 }else{+ m' g& M! W" R, ], E
  114.                         // 电量正常,低压指示灯灭
    - `, y' A0 Q) J( m6 e4 l! T
  115.                         LED = 1;+ X. o+ |# ?- U1 A' ]: J; h
  116.                 }9 l# ?3 W% b9 T, u; r# {' Y6 ^0 c
  117. ' o. H; S1 `2 U" u, I) b- K
  118.                 // 检测到停机标志2 A3 [- h" x5 ?3 H
  119.                 if(isReadyToHalt == 1){
    ; ~9 X8 L8 X* F. l% `$ E: ~
  120.                         // 暂时关闭定时器0中断
    2 W5 h& S9 D6 d6 L
  121.                         ET0 = 0;# }* l9 ?8 H5 l' R4 d
  122.                         // 停机之前先把矩形波输出脚置低电平,以方便INT0和INT1唤醒CPU
    " N3 C* X, X3 n9 I( V; k: n% x
  123.                         OUT = 0;8 J+ I/ ^. I  R, R
  124.                         // 停机之前先把低压指示灯灭掉,以省电
    # g; N$ ]5 L8 o" \; ]; K
  125.                         LED = 1;
    + ?( [/ D5 Y/ ?* h
  126.                         // 进入停机模式- R3 q2 y: ?3 g- s
  127.                         PCON |= 0x02;
    & r" z5 a6 m  Q1 d! C" b! j1 P
  128.                         _nop_();; b5 M7 N( M+ g  g7 s4 G
  129.                         _nop_();8 M. e4 W9 e& h" Y
  130.                         _nop_();
    6 W( }, v& o& \! q, b9 m
  131.                         _nop_();7 C4 {- j6 t5 k# s# U+ b6 q- O
  132.                         // 唤醒,清标志位( K+ ~- ]9 W. ]( z/ U7 _$ q
  133.                         isReadyToHalt = 0;* R0 v0 q7 s* F2 k/ N/ S
  134.                         // 重开定时器0中断
    ' B7 t% o! _4 \/ C/ v
  135.                         ET0 = 1;/ D  R# |7 S5 z0 f
  136.                 }% o/ z9 N: A; r% k: U; q  A- _
  137.         }
    # ]8 Q0 c2 g( B' \
  138. }
    * k! l0 w0 \# l4 d& U
复制代码

1 s( o" p& S: Z0 S0 t硬件参数配置:
7 M) X/ y9 s9 Z" G+ r
5 _" [" U& o3 e2 y1 W0 t* `/ d- h& U/ j" \3 J
接收端:
& Z' d  {5 z- Q; i  e1 K
  1. #include <INTRINS.H>! {& S+ H+ K; I8 t6 e/ C
  2. #include "STC15W.h"
    : H, H- k! M7 g( |8 |' x4 K0 m

  3. 5 \5 j5 V2 W" o0 O# X; |$ k; G
  4. 1 u  D5 U9 e6 o: W# `! s# R: V: v; D
  5. /*0 i/ Y% h+ t% i/ {! T$ A/ S% c
  6. 4 N# D- _7 B! \8 e- t$ Z4 p
  7. *---------------------------*
    6 e7 D! X$ v5 Q; O
  8. |1 (GPIO2)         \__/  (GPIO1)16|
    , c* N1 P  R4 O- v; U
  9. |                                                        |
    4 X5 v& A& b2 R
  10. |2 (GPIO3)                   (GPIO0)15|  J" A  V! F. Y) J) H( h* r9 j( c
  11. |                                                        |5 G) u$ }) i, n6 a4 t& W6 i, x
  12. |3 (GPIO4)                                  14|& \* W4 M- p9 p$ b/ @5 t
  13. |                                                        |
    # Z! P" z% K' d1 ]5 a* X3 H- x3 B
  14. |4 (GPIO5)                        (DATA)13|
    : K0 ?2 e9 W6 z4 i
  15. |                  STC15W204S                |# W' r- {; Y) W* E4 B! o
  16. |5 (GPIO6)                   (LATCH)12|% F+ ^0 A. c: t
  17. |                                                        |
    # I. D$ C. X' n, W' K% f, U
  18. |6 (VCC)                         (CLK)11|
    8 k. P7 _$ y) R0 p$ w* w
  19. |                                                          |
    2 R5 [) ]9 C7 h( s+ C7 x' u
  20. |7 (GPIO7)                         (TXD)10|
    : H) F( k5 ]0 F1 I2 u
  21. |                                                        |
    , A! j: {5 Y1 `( r
  22. |8 (GND)                         (RXD) 9|
    ' \/ B0 ]" T) F6 H; r
  23. *---------------------------*4 @# W/ t9 h/ g) a$ ?1 w8 O
  24. Fosc = 12MHz0 v# L8 @; f5 l2 b

  25. 7 B' m% g/ m" t: g
  26. P1.0 -> 上" i$ T+ ?' v- K! @: v- O
  27. P1.1 -> 左
    0 E- d5 H5 I- I. K
  28. P1.2 -> 下! W$ e( C: H- z( F
  29. P1.3 -> 右
    ; x* i( h0 x8 v% o9 j$ p: k
  30. P1.4 -> SEL" j2 T6 [! I4 b1 c
  31. P1.5 -> STA
    ) S$ f  z- e# S) g5 K* W
  32. P5.4 -> B9 P. m. {' R. k/ X; x% E
  33. P5.5 -> A
    8 R5 T6 |7 I% p' b
  34. ! `/ p% T# l% \" V9 |
  35. */
    ; S7 b- h  K0 [3 S$ g# R+ U
  36.   k/ y! }: r$ m2 d- s0 z& Q
  37. ! f1 D5 W: ?, B- S+ Q% P) j  j5 a+ f
  38. sbit CLK        = P3^2;: T: X5 d5 ~8 w2 l! T8 k
  39. sbit LATCH        = P3^3;& Y' ?7 b% u& j2 A( ]" q0 M
  40. sbit DATA        = P3^6;
    , {; B/ H9 G" Z  ^. T1 g

  41. 4 Z$ k) t. e; ^% r/ S
  42. bit isReady = 0;
    + w  `% q  n/ {/ J1 P- I
  43. static unsigned char key = 0;
    6 Q6 J  @  @! Y+ j" U% l
  44. static unsigned char buf = 0;        // 双缓冲。这个缓冲区保存从P1和P5组合而来的键值! I1 B9 H$ I# a3 e) |, A! F5 ?' ^
  45. static unsigned char bufReady = 0;        // 双缓冲。这个缓冲区保存上面那个缓冲区的备份: n" O) h6 H) u8 I# o
  46. static const unsigned char data mask[] = {0x80, 0x40, 0x10, 0x20, 0x01, 0x04, 0x02, 0x08};        // A B SELECT START UP DOWN LEFT RIGHT。为提升速度,这个表放到RAM中
    # h& B. y/ d6 ]. c- i: y
  47. static unsigned char idx = 0;6 i$ ?5 x, w6 P9 z8 J

  48. 2 t+ u# z  _  Q) z% z
  49. * l" ^4 |( K2 @- ]" m/ L( V5 X; D
  50. static void GPIO_Init(){
    $ e- i. t' ?5 U- N, ?3 L& {  w8 N
  51.         // P1口和P5口用于接收并行信号,全部初始化为准双向,依靠内部弱上拉输出高电平' E8 M+ ]5 h4 h! V. \
  52.         P1M0 = 0;
    & z8 r" J6 j6 O  {: |' G
  53.         P1M1 = 0;# E" [3 k- L0 a4 ?4 T2 l3 g! A& r
  54.         P1= 0xFF;
    , g, |8 t3 u1 c: h' q) V( f
  55.         P5M0 = 0;
    # \* U  ^; K, R5 J. s9 |2 Q
  56.         P5M1 = 0;( k; y* ]2 c& \7 d* Q7 ^4 n
  57.         P5= 0xFF;. ^  [- e: r  I2 Z3 ^7 H  s
  58.         // P3口初始化为准双向! V. C, W. X" c$ p$ q
  59.         P3M0 = 0;
    + f- u9 y& i% S8 S) L) q  u
  60.         P3M1 = 0;# X  S0 N$ C1 u( ~  d1 D
  61.         P3 = 0xFF;  r3 d# n- E) ]6 w
  62. }* H+ w" }4 l: k, a$ i0 w, |$ l' @

  63. 6 [( O6 q$ S: Z8 L& ~, D; g
  64. static void Interrupt_Init(){
    . p3 k  L* P! Z' [
  65.         // INT0中断(CLK)触发类型为上升沿+下降沿. e" b7 R8 |9 W/ l/ ?/ h+ x+ `
  66.         IT0 = 0;! g& A+ R: D( {- Y* B( ^  `4 G# k9 m% p
  67.         // 允许INT0中断
    ! T! k7 `0 m' }3 d; I
  68.         EX0 = 1;6 ]4 B2 E- K$ D) t) a& }
  69.         // INT1中断(LATCH)触发类型为上升沿+下降沿# N0 }) |) c' ~) _
  70.         IT1 = 0;
    6 ~6 E5 r+ ?$ G# p) o) x
  71.         // 允许INT1中断
    5 i8 k5 ?4 ^8 g  |  ]% U. x( B+ ?3 [
  72.         EX1 = 1;+ K# `8 Q2 P" M$ Q7 ^
  73.         // 开启全局中断
    6 B* U9 |* `) c. ?. U& B3 I
  74.         EA = 1;
    5 d: ~" O" q; @$ i1 b8 K
  75. }7 r* D' W) T  Q! y# W5 i
  76. - q( }( F2 I( A" I4 z
  77. static void INT0_Isr() interrupt 0{
    * X8 z# Z2 v: n4 r
  78.         // 只有已经成功锁存才允许CLK移位
    + A2 O3 ?1 c5 K! h, B" N# B7 q
  79.         if(isReady == 0)
    , \6 L8 I6 m- e! x9 y' D1 S$ I; W7 P
  80.                 return;: t8 ~: Z8 k* b
  81.         // 读当前引脚电平,如果是低电平则说明是下降沿,此时直接忽略该中断* _, V4 q( i8 B, f% I3 D! S! \$ D
  82.         if(CLK == 0); I) S1 ?  P6 ~" R1 b% X4 M- [
  83.                 return;
      l6 w2 W0 c% @- P* S
  84.         // CLK上升沿到来的时候,取锁存值的下一位输出
    $ p+ K6 n5 s1 |- c4 y; r
  85.         idx++;
    * B- ]; r) X3 P6 _! ]! _! q
  86.         DATA = key & mask[idx];
    3 }4 U9 ~" w" p
  87.         // 如果已经完成7次移位,则一轮读取完成
    " J( z; o% N7 V8 L9 p* T. t# E
  88.         if(idx >= 7)! V8 H6 f1 W. _+ M9 V1 ]
  89.                 isReady = 0;
    7 m- m8 v1 P" x0 O" C  x% g
  90. }
    . x) [$ q3 v! T

  91. ; Y- G6 g" c. ?+ y# M4 P
  92. static void INT1_Isr() interrupt 2{$ s5 B, ^9 @1 W7 v
  93.         // 读当前引脚电平,如果是低电平则说明是下降沿,此时直接忽略该中断( [( {, Z4 s6 H; D0 Z3 H. @
  94.         if(LATCH == 0)( O& p/ r( e& {& C  x+ Y
  95.                 return;' @. f9 r8 d0 S, l
  96.         // 当LATCH上升沿到来的时候,锁存所有按键状态,同时把键值A输出到DATA! d3 X% e3 G0 I
  97.         key = bufReady;
    " o4 u, \( @; O0 r& j
  98.         DATA = key & 0x80;//mask[0];        // 为了加速运算,直接取表中的值而不是读表
    " z, s: c1 h$ L
  99.         idx = 0;# c+ a, k. Q9 w0 j
  100.         // 允许CLK进行移位4 J3 l0 ]$ u! w+ j3 _
  101.         isReady = 1;: b8 i& H0 W8 F9 e" n8 b+ u
  102. }
    4 i* U5 w9 p0 q2 s& \6 y4 v/ i  M$ Y

  103. ' y9 ^) v% D, G0 C; Q. E8 {9 Y4 t: c
  104. void main(){! F2 _8 s0 v! W8 I5 W. y* n
  105.         GPIO_Init();" I" y6 [; t$ @' H6 [
  106.         Interrupt_Init();
    " d& ~7 U- G3 N7 O" A! S. d; K
  107.        
    - X1 {( z9 d! u* f
  108.         while(1){
    8 C/ I; j& H( ]3 x: _4 D
  109.                 //PCON |= 0x01;        // 进入省电模式
    ' @, S% Z3 N5 C( F
  110.                 //_nop_();; m- m/ ?/ C8 l* R* u
  111.                 //_nop_();
    2 L# L$ M; O2 M  e. m2 l
  112.                 //_nop_();8 ?; M/ b1 M4 o5 Q2 j/ ~
  113.                 //_nop_();
    # Y0 g3 x) \3 P( \
  114.                 buf = ~((P1 & 0x3F) | ((P5 << 2) & 0xC0));5 c' N$ s: C$ s% p: U% a
  115.                 bufReady = buf;
    2 q1 A  R+ M. v5 V/ ]
  116.         }
    + I% ~7 f2 u8 c) d9 J. r
  117. }- H# m8 F0 V% _' P/ V: k& E+ _
复制代码
) J/ U- T+ |. H
硬件参数配置无特殊要求,晶振频率选择12M即可。, m' V4 E2 X- i0 D$ |

7 ^; S3 N9 p, b这是编译好的固件。

本帖子中包含更多资源

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

x

评分

参与人数 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
; Y2 y. U( p0 _4 V$ m不错的设计,想问一下楼主,FC的15针公头怎么解决?普通的公头太短了,插不进去FC的扩展接口。 ...

3 C  X; g' S  P# u0 t坛友的改造方案
回复

使用道具 举报

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

使用道具 举报

发表于 2019-5-25 12:07:18 | 显示全部楼层
精彩,楼主动手强,也写得很详细。$ A7 t* e; l0 u2 i
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
. J* H9 Y3 S5 e# n0 D; H2 l+ b" }1 g精彩,楼主动手强,也写得很详细。
" r7 l' r) k! {9 a2.4G方案是目前无线的最低延迟吗?

8 u: H+ V7 ~" s# s% L' S我没用过其他无线手柄,所以实在不知道我自己做的这个手柄到底是不是最低延迟。: \8 A/ p8 r: p1 E. [8 q, f+ \
不过根据网上的说法,延迟高低主要是由通信协议的复杂程度,以及数据传输速率决定的。这个模块虽然是2.4G无线模块,但由于协议很简单,所以延迟比较低。' |% D: j' s0 J) ~+ ]5 v
我用这个手柄玩一些ACT游戏,比如超级马里奥、忍者龙剑传、热血系列,完全感觉不到延迟,和游戏机自带的手柄没有任何区别。唯一的区别就是这个手柄是用火花山寨手柄改造的,外壳是垃圾回收塑料,粗糙+脆弱,导电橡胶弹性不佳,手感不是一般的差。+ c; o* p; X  F# ?7 z$ k$ o
我手里还有十几张板子,等我有空了我再做一套,到时候买一个好一点的手柄改造。
回复

使用道具 举报

 楼主| 发表于 2019-5-29 16:56:14 | 显示全部楼层
ppad 发表于 2019-5-28 17:27; p# ~* h6 Q5 g/ h; k4 T; j
给技术帝赞一个,有半成品发布吗,自己焊接改造就可以,编程实在不会啊 ...

3 z/ Y& u6 d  V3 m+ l5 E* F! P, B很可惜,我手里没有多余的单片机了,LDO也找不到了,锂电池以及充电模块更是没有了。反正就是该用到的元件基本都没了,所以没法发布半成品。
& G( Y4 V; w" A% o两个板子倒是有十几张剩余。
  l3 w# b8 D6 T" v  a! V+ T6 F7 ^7 ]你要是有USB转TTL串口板,完全可以自己买这两种单片机,然后我给你编译好的固件,你自己用串口板下载到单片机里面就行了。两个2.4G无线模块也得通过串口板用AT命令设置参数,不过好在我在设计电路的时候就已经预留好了串口,可以直接在线下载和在线设置参数。总的来说并不麻烦。
回复

使用道具 举报

 楼主| 发表于 2019-5-29 17:00:34 | 显示全部楼层
孙大师 发表于 2019-5-28 18:55
" k* g/ u  q+ V非常好,楼主是技术帝,到目前我都还没开发fc的无线套件,等空了,开发一套套件,等玩家自己组装。 ...
) g" g7 s8 _2 p* a9 A/ f
能得到孙大师的赞誉,不胜荣幸!* [0 r0 M3 ?+ _
不如开发一个多功能手柄,比如用SFC手柄改造,L/R键配合其他组合键可以用来切换2P~4P、调节连发速度、软重启等各种功能。接收端插到15PIN扩展口。
回复

使用道具 举报

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

本版积分规则

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

GMT+8, 2024-4-27 01:15 , Processed in 0.071201 second(s), 14 queries .

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

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