找回密码
 注册

QQ登录

只需一步,快速开始

查看: 24817|回复: 32

自制FC无线手柄

  [复制链接]
发表于 2019-5-22 14:16:45 | 显示全部楼层 |阅读模式
本帖最后由 雷精灵2046 于 2019-6-14 09:28 编辑 % k" z" v- C6 N% ]# U

8 S9 t$ g0 s" {1 a没有用复杂的分立元件搭建发射接收电路,直接用的现成的2.4G无线模块jdy-40。
% L" B# `+ T" y- [0 i$ E0 X& w: s) r. c

' k0 I/ M2 K& `7 l7 A' f' R* S+ P发射端靠3.7V锂电池供电,用了一片SOP8封装的STC单片机,负责产生连发脉冲,同时负责检测电池电量,电压低于3V左右的时候触发低压中断,低压指示LED就会亮起来告知该充电了。平时发射模块和单片机均处于睡眠状态,有按键按下才会唤醒,从而实现省电。实测睡眠状态下整机电流约1~2uA。板子洗了一下稍微干净了一点。因为对于微功耗设备来说,焊接残余的助焊剂可能会增加漏电流。
3 w2 q9 B# g8 K' j+ A1 y* Z4 q; w" I/ u3 U: m
买了一个火花的FC山寨手柄,去掉里面的牛屎板子,并修正一下塑料挡板,把锂电池和充电模块装进去。8 a7 ~- W$ H) ]  a3 r
为了减少体积,充电模块裁剪得十分小,并且更换了充电电阻使之适应这个小小的锂电池。这么小容量的电池,也不需要多么大的充电电流是吧?" a3 T8 p3 W& ?, S
然后统统用热熔胶粘上。充电电流比较小,所以发热很少,不会熔化热熔胶。" Y5 x7 D: ^1 P( z" z5 W, a3 ^

: c- p" s5 D) [# m1 V% D) L* u7 c; F
- ?3 e) s. M; b7 P; I- J( i
/ g# h' V% X( C# u# w- a+ \最后把按键、导电橡胶和电路板装上去。  u5 G& ~/ M: b2 o' U2 ]( ^) G9 m
精心裁剪了电路板,正好扣上,不会阻碍其他元件,也不会影响后盖和拧螺丝。
( O* I* Q% _7 J. A
& H* N2 f: a3 ^8 Z
8 R6 p" z5 N! P7 F9 a3 p完工!
' c! }, K4 [1 x+ C7 n( E" ]; m7 |
% K7 \6 Z  [+ e' x+ w
这是充电的MicroUSB插座。旁边的小孔用于透出低压报警LED的光线。
- q. r# H( [9 i8 M
* J: O7 A4 @0 B, X3 X, q1 m+ O
" p9 U1 @6 m8 b. [0 P& e" S7 R接收端用一片DIP16封装的STC单片机模拟CD4021。为啥要用单片机模拟而不是直接用CD4021?因为jdy-40模块接收端在有按键按下的时候输出高电平,无按键按下输出低电平,和普通手柄正好相反。当然我也可以用两片74HC00或者74HC04之类的逻辑门进行反相,但那就增加了芯片的数量。对于FC手柄这种工作频率并不高的设备来说,STC单片机完全可以胜任模拟工作。
# c2 Y/ x! u5 U( G* ^- ]% N2 G8 o* E9 c9 H% d* M# M

' m" M# S% R8 Z
/ a, q% m6 [. S6 x. i电路设计有点小小的错误,所以有几根飞线。原本设计使用低压差LDO是XC6206,结果在做这个接收模块的时候,买的LDO居然找不到了!无奈只好用了AMS1117。幸好对于接收模块来说是5V降到3.3V,1117可以胜任。要是发射端手柄的话,3.7V降到3.3V,那就非得用6206不可了。
/ |& B- |2 i6 u( S
" a  _' n& F; j7 K3 ?实测十分灵敏,延迟极小几乎感觉不出来。可惜这山寨手柄的手感并不佳,尤其是方向键,软塌塌的。看来我得买个剪线手柄改装。4 `9 h" @5 o) i: m# A$ q3 e' v

! y1 B% ~) f  o; F, z这是电路图,有兴趣的朋友可以参考。+ [/ |" y5 Z$ J; V4 V

2 q# N, j5 K! {6 M- o1 [& I( m8 r+ a- r( _1 H
我信奉开源主义,十分痛恨把技术藏着掖着。好东西大家分享嘛!所以两个单片机的源代码大公开!
9 C) t5 }9 q6 J- [/ S. ?8 x" O编译器:Keil 51。
* Q1 O, _3 x: _/ |  g* h
; S% g0 U$ O; ~; ~8 C发射端:
3 w# B# a- [& ]: U6 M
  1. #include <INTRINS.H>
    0 w* x: k6 V) X9 I8 g
  2. #include "STC15W.h"
    / I- F- y; ?! l5 W

  3. 2 C& J0 B- S7 K, {7 ^- g  z

  4. 8 F8 t0 }$ y- G; {( }$ Q  n0 n" \
  5. /*
    4 h; H" E! L: u. Y8 ^3 ?" }6 t3 |: m' a
  6. --------------------------
    ) [6 D0 T5 |# h5 m  k
  7. |1 (OUT)        \__/   (INT1) 8|8 H3 d9 d# C) N" Z
  8. |                                                   |
    ( H9 V& S+ q% ?( c1 O9 ~2 G, Y! _
  9. |2 (VCC)                   (INT0) 7|& d6 j9 c$ `& k0 n6 Z: m
  10. |                 STC15W204S                   |
    , E% H% |. c# D5 T6 ~
  11. |3 (LED)                         (TXD) 6|; Q1 d0 u" E9 T0 @! V
  12. |                                                   |
    / K5 T  ?& h9 s! m
  13. |4 (GND)                         (RXD) 5|
    ( e+ U$ S, c/ k! n: a
  14. --------------------------  A% X2 W9 `; a6 _

  15. ! B  o% ~9 J0 i6 ~' ?( d, d1 K% c7 r
  16. LED ---|<|---[===]--- VCC. R( Y* _! R: h1 h8 l$ N
  17.            Red          330$ f, }+ s5 c& A
  18. 5 o. X) B7 `* g+ k  J5 Y1 Y7 `+ w$ c
  19. Fosc = 6MHz! E1 [- F: w1 z+ [7 q  K; H
  20. */% ^: Z; |% N) s4 |

  21. ( ^' g' }% Q1 @! d5 N9 ?4 i

  22. ! P3 ~3 _9 O7 a. C+ j3 G
  23. // 矩形波输出脚
    3 y- Z, [. T+ M: B
  24. sbit OUT = P5^4;
    9 N5 k+ N) j* b' a( d
  25. // 低压指示灯引脚
    9 m6 a1 ~2 o% o/ T8 K0 \3 ?6 [; X
  26. sbit LED = P5^5;/ u1 X2 [$ c% i
  27. 1 Y  i- u- g$ D. T( i$ c
  28. // 停机标志位# X% n' y* @/ J; ]) E3 r( p
  29. bit isReadyToHalt = 0;7 R6 K4 G0 H2 ~! H, I9 B

  30. ' U# Q* m' O) u+ \3 K- z
  31. // 矩形波次数累计
    + J' e! r- T4 u' ]1 B$ A1 d
  32. static volatile unsigned char count = 0;
    5 {+ t, ?& k5 O% w; H. F

  33. 2 v( Q3 Y6 {8 a% p- V
  34. ) X! u8 ?% O: t( H
  35. static void GPIO_Init(){
    ; Z* V& G8 m0 U, W, }/ e3 J# W& G
  36.         // P3口设置为准双向,默认靠内部弱上拉输出高电平
    # y6 j0 Y, d8 N
  37.         P3M0 = 0;- l/ C  z6 R7 d( m
  38.         P3M1 = 0;
    - C/ u1 i. V9 l  J9 Q6 m; U
  39.         P3 = 0xFF;
    - J% z; A. t7 }6 l0 d
  40.         // P5口设置为准双向,默认靠内部弱上拉输出高电平/ A' N1 i9 F) ^4 v
  41.         P5M0 = 0;5 p2 A/ @: l) }* o, W; X
  42.         P5M1 = 0;3 H) m* s& i. `8 Q* S
  43.         P5 = 0xFF;
    3 }$ l# p2 G: {$ R, D# s
  44. }/ [( b. A  n2 {- }* r" o( E2 S
  45. & I0 ?7 |! s5 b2 p
  46. static void Timer0_Init(){  M3 F7 g. X3 x3 U' G
  47.         // 16毫秒@6.000MHz
    0 L- `- J5 r  `0 v, j( j, u
  48.         AUXR &= 0x7F;        // 定时器时钟12T模式' H, U8 `; q& K4 m; \6 b
  49.         TMOD &= 0xF0;        // 设置定时器模式$ M+ X/ g9 N. s/ A, y$ T
  50.         TL0 = 0xC0;                // 设置定时初值
    * z4 n/ ~1 D$ k. K' v( R
  51.         TH0 = 0xE0;                // 设置定时初值
    % P5 D; T* a& k* V  @: g/ ?
  52.         TF0 = 0;                // 清除TF0标志
    $ f7 d. g* O; ?3 }
  53.         TR0 = 1;                // 定时器0开始计时* R8 Q6 `  H4 f
  54. }3 I4 S# U0 r8 s, |$ p5 h

  55. 0 J5 Z9 q+ [+ o3 {
  56. static void Interrupt_Init(){
    1 i1 U+ ~5 v3 W( f/ o# s
  57.         // INT0中断触发类型为下降沿触发
    - }1 S) m# ~. h5 V- u0 X6 Q. \. P9 [
  58.         IT0 = 1;
    ; n! b8 k- [1 @3 {
  59.         // 允许INT0中断4 c) l" s( |1 ^. _/ o
  60.         EX0 = 1;" a. I- L7 s6 Z$ a) f
  61.         // INT1中断触发类型为下降沿触发( D  r/ R" R5 H- U; \1 L+ U) g6 F
  62.         IT1 = 1;% c; i& g0 w. L5 z1 b6 E! s. H0 W
  63.         // 允许INT1中断- B. e( U2 }7 t' [3 G* g8 [; H
  64.         EX1 = 1;
    : o* Y4 d0 ^4 l2 X8 |* [8 q+ p
  65.         // 允许定时器0中断
    ( v# }  h0 n& v- O4 N) x8 E$ \
  66.         ET0 = 1;
    * a/ o2 w- l3 r3 ^+ _: _
  67.         // 允许全局中断$ r; i! ?  X+ A
  68.         EA = 1;2 W8 y/ k8 L) a: X
  69. }
    7 |3 r! f1 X8 y0 ]* y) K: z9 _; B

  70. ' o$ T2 U6 N' s, K* G8 k
  71. static void INT0_Isr() interrupt 0{% B* S- T. O6 W# U, K% t
  72.         // 矩形波次数累计归零
    + V4 f& s, l9 J' t7 X
  73.         count = 0;
    + ~4 {, ?7 N8 B! I
  74.         // 重开定时器0中断
    $ V5 B7 p# e1 N$ @
  75.         ET0 = 1;5 h2 f5 \' r2 k# ]
  76. }8 ^* W) N, \7 A$ Y3 ?5 N! l9 C+ e

  77. ; S/ f5 s& C: }4 O3 {0 O
  78. static void Timer0_Isr() interrupt 1{, |* r' }' R3 @+ [- K
  79.         // 输出矩形波
    8 a6 J; v6 l5 ?& x
  80.         OUT = ~OUT;
    ' h- b: u: V0 p
  81.         // 累计矩形波次数  v( @* G4 j% I) ?  ~
  82.         count++;
    / S, v. F9 E$ A6 X7 [' E8 {9 o" z
  83.         // 超过250个矩形波,准备停机' o  u! D" y, h$ g+ w1 T
  84.         if(count > 250){
    , T% d7 K! ^% R4 b
  85.                 count = 0;
    + M) ~1 \. h& O* |$ o
  86.                 isReadyToHalt = 1;# b; K, s0 o- {: I3 y% B2 ~7 s
  87.         }
    * [1 a/ A2 o6 G* o! \6 I
  88. }# A: E. N* [  o8 I" R+ q

  89. $ X& p8 ~5 Y0 o) x" Z/ s
  90. static void INT1_Isr() interrupt 2{
    " I6 @, x( ~6 P/ W' R, K
  91.         // 矩形波次数累计归零
    , V' P3 R4 P# x
  92.         count = 0;
    9 @, ?- ~& Y! G# `+ j
  93.         // 重开定时器0中断( I( s+ R- V: H
  94.         ET0 = 1;0 j* h% r8 }$ @/ ]- ~/ u6 y6 `. q
  95. }
    4 h. A  b- I% t! S& z
  96. 0 ~( I! {9 F3 |. ]* W) k

  97. ' g, ?% d; H7 F; ^$ v
  98. void main(){3 \: b/ b0 s. ?3 p) f7 B/ V! K/ _
  99.         // 初始化P3和P5口
    3 Z2 @$ r1 B0 }. x, \0 q
  100.         GPIO_Init();2 p7 C4 r1 P9 J- q
  101.         // 初始化定时器0
    ( J, A7 S# w  J: }6 N  `% O% \. Z
  102.         Timer0_Init();8 X: @1 Z" v# f
  103.         // 初始化中断
    % k6 r; I# k% Z5 T
  104.         Interrupt_Init();
    6 D% A, z+ I. @1 ?. W
  105.        
    ) y2 P4 g9 k: a# V- Y/ y% l
  106.         while(1){
    & P; P8 D* r, Z: o' H2 A6 S
  107.                 // 检测电量
    ( f& l' v% L6 B( ^, w/ @4 q
  108.                 if(PCON & (1 << 5)){( Y* r. P1 i1 x8 `8 C5 L* m0 E
  109.                         // 如果电量低,低压指示灯亮! U! B4 I) l* h  }9 E  L2 Y
  110.                         LED = 0;
    / s- f# I6 b  r" \% _
  111.                         // 清电量检测硬件标志位
    1 X1 G/ _& }. l. B& H0 p
  112.                         PCON &= ~(1 << 5);9 F2 T- b- h* m5 X+ `2 c0 s
  113.                 }else{8 L; O# t* s5 w* _5 A1 i9 o1 i
  114.                         // 电量正常,低压指示灯灭3 i0 ^4 \) a1 q0 u
  115.                         LED = 1;" j4 g3 [- R( e" h" F& e4 V
  116.                 }
    + U, q- |9 _8 O
  117. % o  g) J% I; I- U
  118.                 // 检测到停机标志5 C, y" t/ b& C/ `0 V
  119.                 if(isReadyToHalt == 1){
    / g  T; V! Q* B1 C  J
  120.                         // 暂时关闭定时器0中断
    : d/ Z% n0 j- g/ V$ K. H; w5 h
  121.                         ET0 = 0;5 H, ^) O/ ]7 U" |
  122.                         // 停机之前先把矩形波输出脚置低电平,以方便INT0和INT1唤醒CPU8 e5 L3 ^3 @! P5 R6 \# j
  123.                         OUT = 0;. w* h: f  t# e2 g
  124.                         // 停机之前先把低压指示灯灭掉,以省电2 z1 r9 C( p! S" f6 u5 Y, E1 n
  125.                         LED = 1;
    # D- \, D  o0 [
  126.                         // 进入停机模式
    5 u; F3 x5 x: ]# d$ `3 Y
  127.                         PCON |= 0x02;
    . I& k0 F9 R% @1 ]
  128.                         _nop_();- g3 W, C: Z5 x
  129.                         _nop_();
    - r' x6 E9 x. _# f0 b
  130.                         _nop_();+ X6 \: ^6 U; D0 g# Z
  131.                         _nop_();: w- H+ M9 L2 |: c8 a$ F
  132.                         // 唤醒,清标志位
    ! l! I8 t6 k" G* D2 t3 X  X
  133.                         isReadyToHalt = 0;) x' f( h+ U/ H: [
  134.                         // 重开定时器0中断- Q; i" V5 U+ ?8 ]" p3 ^
  135.                         ET0 = 1;( b7 q) G0 B. ]4 q( V7 [
  136.                 }& X( h( ~8 R  D: k
  137.         }0 y* O5 d: k) B- y+ a' U
  138. }( V: X5 V1 z: O1 s/ L, |
复制代码

2 ]: e9 a: t0 f  s& A硬件参数配置:
3 I+ A6 o3 m$ J$ X4 ~$ k
+ W2 M5 U3 ^# J- V2 x; v9 ?! N' {4 ?  O$ L4 ]2 e
接收端:# E# I1 O* \( p  Z1 B" ^3 b8 p
  1. #include <INTRINS.H>
    9 q+ l0 d3 ]6 `) U: {. g, C4 F/ k
  2. #include "STC15W.h"! J+ B4 N1 Z- f5 [. s* G- ^

  3. ! `& z; M7 l6 V8 \

  4. / `; F1 a7 r& y! s) v4 @& p
  5. /*
    ! h7 O( X/ o% T. t4 ^5 _6 V
  6. + ]9 o5 X1 X0 R1 Z: L4 Z8 L. _
  7. *---------------------------*6 U' n  q* }! f# [2 g
  8. |1 (GPIO2)         \__/  (GPIO1)16|
    , i2 d+ g, x6 \: w5 O4 O
  9. |                                                        |
    " X4 F7 A% M+ A7 ]
  10. |2 (GPIO3)                   (GPIO0)15|2 t: F" X% U1 B5 [- k6 F
  11. |                                                        |
    5 ^7 U; _+ O+ b7 G
  12. |3 (GPIO4)                                  14|1 R( P8 i5 T# e
  13. |                                                        |
    5 d- q: d0 e% A5 ?# n! Q+ e+ D
  14. |4 (GPIO5)                        (DATA)13|
    & T# H- X- t: x) F& y
  15. |                  STC15W204S                |
    3 b1 P# @% i& C( k/ O' ]5 n5 n2 |* \
  16. |5 (GPIO6)                   (LATCH)12|) U) R4 f1 \( h6 S+ u. }' L
  17. |                                                        |, p4 m- d3 P! f0 B6 `
  18. |6 (VCC)                         (CLK)11|
    " u. ~+ R0 K3 b# U  \4 [
  19. |                                                          |
    5 d* H% j& x3 j6 J0 S
  20. |7 (GPIO7)                         (TXD)10|
    3 ?5 o( Y% ]  P( C' t' a8 r" A
  21. |                                                        |+ j+ j/ h% C% J( T9 Q9 N
  22. |8 (GND)                         (RXD) 9|+ Y6 O# u* Z$ M0 A! O3 u
  23. *---------------------------*
    . x% ?) `) R+ K% s5 \! C( u/ y( R
  24. Fosc = 12MHz
    ( a% I: c) ]9 r7 V# b$ w
  25. ; E7 M' @& y7 X0 u1 t7 V3 `- o8 e
  26. P1.0 -> 上
    + {5 t- C' V+ H' p, X: N0 `
  27. P1.1 -> 左+ K( c4 N1 |* A$ g9 ]
  28. P1.2 -> 下3 D  r; X( @3 E+ P3 M8 s6 w9 `
  29. P1.3 -> 右" q5 J$ @0 V3 }' }
  30. P1.4 -> SEL
    , h/ z/ E$ |, t; w
  31. P1.5 -> STA( [$ D& X0 K9 F/ s) N4 S6 E
  32. P5.4 -> B
    + m7 j$ a2 b. X- k8 C; X; b0 o
  33. P5.5 -> A' }; R* N5 o' H& T

  34. , s; [6 x; P; O) B
  35. */
    % H* |4 e9 g7 h* [# ~6 X

  36. - E, p0 i0 m, x* J) J% C0 o
  37. . L- l; y. w! \8 w' h  I
  38. sbit CLK        = P3^2;4 j* ^2 \! t8 v! z; H% h: h! ~
  39. sbit LATCH        = P3^3;4 ~. V  x4 |0 M
  40. sbit DATA        = P3^6;; U6 k! ~( \* R' K. P

  41. 1 B% L# v2 m' o& P
  42. bit isReady = 0;  m2 |$ W8 l, o8 g- E
  43. static unsigned char key = 0;9 r: R; s; ~0 |
  44. static unsigned char buf = 0;        // 双缓冲。这个缓冲区保存从P1和P5组合而来的键值, m! p2 M4 O( m2 S. I( h# a7 P! p5 E
  45. static unsigned char bufReady = 0;        // 双缓冲。这个缓冲区保存上面那个缓冲区的备份5 @2 O% R1 f& Q/ w" _
  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 k8 E! R% [2 Q6 d
  47. static unsigned char idx = 0;
    , v* p% p8 _( ?7 w8 H

  48. * p' C+ \# W+ I1 G: Y
  49. . p/ V6 ]& \# w! m3 g+ g
  50. static void GPIO_Init(){
    4 O7 x. C2 B0 b7 T
  51.         // P1口和P5口用于接收并行信号,全部初始化为准双向,依靠内部弱上拉输出高电平8 \0 y9 L$ W1 L, a. @6 t
  52.         P1M0 = 0;) L4 q1 F3 P! ?4 A5 O& g
  53.         P1M1 = 0;
    9 e! F& w5 a- C
  54.         P1= 0xFF;7 D# Z" `! K% M7 T) a7 _" ?
  55.         P5M0 = 0;
    5 {( W/ Q, v4 p5 n: p3 k4 [
  56.         P5M1 = 0;
    4 m# g% s5 K* r0 k. E( v5 ^
  57.         P5= 0xFF;
    6 F4 _+ ^; G: c$ r4 y/ n* f
  58.         // P3口初始化为准双向5 j; t8 z* @' r% e
  59.         P3M0 = 0;
    * w" Q( A/ {0 E3 _& v' ~
  60.         P3M1 = 0;6 {! \" L, N" z) Z
  61.         P3 = 0xFF;
    , |) f' S" [8 n* c8 U+ J
  62. }
    9 ?4 ?' r; ^" q4 U+ ~) B

  63. % [4 H3 R6 B9 j4 r! r# E9 c4 a
  64. static void Interrupt_Init(){5 l$ i4 N% T8 b# b3 U" N
  65.         // INT0中断(CLK)触发类型为上升沿+下降沿6 f) r8 B2 G- A* [% N
  66.         IT0 = 0;
    ' p/ e9 I! {1 p# a! L. q7 a
  67.         // 允许INT0中断# h$ ?& z4 l6 D- B6 M- k6 q$ o
  68.         EX0 = 1;2 i7 m+ q& s& s0 P9 W( \2 Q+ w( f5 m1 \
  69.         // INT1中断(LATCH)触发类型为上升沿+下降沿% p& G5 L: ?9 \
  70.         IT1 = 0;
    ( f# s' Y  t! F& i/ L3 x% r/ t
  71.         // 允许INT1中断" H- ]6 e3 H. i1 A3 e/ u6 ?
  72.         EX1 = 1;2 }0 @7 y. J- [5 I$ }' b( f( G# ]: m
  73.         // 开启全局中断
    3 q( f- K* x9 V" b. ?  b+ u
  74.         EA = 1;8 t' R0 p& B4 z4 ?
  75. }( q3 @0 V1 B+ n' D4 o/ m% e
  76. ) C! k: T$ e! S% {. X% u
  77. static void INT0_Isr() interrupt 0{! S# _0 B$ ^$ g( \
  78.         // 只有已经成功锁存才允许CLK移位
    . K. W* q2 \4 ]1 D0 {. [' Q* n
  79.         if(isReady == 0)
    9 |( Q! j/ s/ s# {
  80.                 return;
    ( }) J3 x. Z" l& N! `6 I9 ~4 ]
  81.         // 读当前引脚电平,如果是低电平则说明是下降沿,此时直接忽略该中断/ K$ h/ ]% y) e
  82.         if(CLK == 0)
      C7 t$ |1 N2 l* Z+ Y/ j
  83.                 return;
    ( p$ L4 K5 P' c0 U
  84.         // CLK上升沿到来的时候,取锁存值的下一位输出" x' Z8 z8 U% }) Q. s+ h2 f2 o
  85.         idx++;6 E0 j# o* y5 _1 f
  86.         DATA = key & mask[idx];0 i+ s3 Q, m( {( I# Y& i
  87.         // 如果已经完成7次移位,则一轮读取完成
    1 k( p; e5 _: a2 C6 O2 g9 p
  88.         if(idx >= 7)
    1 p: s9 ?: ~) z7 y3 e* V
  89.                 isReady = 0;
    ( S; Q8 e; p' M; U3 v) O  i2 S! p, J
  90. }/ D" h! q1 ?! w0 G1 O

  91. . z8 L2 M* v, j% [
  92. static void INT1_Isr() interrupt 2{$ K& r$ M9 D$ v2 [$ U& V9 R
  93.         // 读当前引脚电平,如果是低电平则说明是下降沿,此时直接忽略该中断
    : [0 f6 I" |  z- b
  94.         if(LATCH == 0)- r! G+ ]7 [9 K8 a- B: ]  g+ |: s
  95.                 return;
    ; h$ m! ^' L, R& w' T
  96.         // 当LATCH上升沿到来的时候,锁存所有按键状态,同时把键值A输出到DATA- N# T! T0 R9 r) a
  97.         key = bufReady;
    ! R$ {  n; ?5 j1 `
  98.         DATA = key & 0x80;//mask[0];        // 为了加速运算,直接取表中的值而不是读表: _/ q  M& ]# p' u* [
  99.         idx = 0;0 K& Z9 |6 t7 k
  100.         // 允许CLK进行移位
    ' i* e4 h2 _. G' W
  101.         isReady = 1;
    ! P$ ^- H4 ?+ u, n: Z) r
  102. }
    ' h+ M2 {7 ?) `. P( [6 K2 W

  103. & w9 \- B; ~% s' [
  104. void main(){
    7 u6 F3 V/ \+ z3 V( A; x
  105.         GPIO_Init();% C# g* H$ q6 k9 U5 e
  106.         Interrupt_Init();
    2 {0 X4 d2 m7 k: J' N6 H& F
  107.         . U$ O) T# r+ n% p" Y1 Q- }( K, H
  108.         while(1){
    & o1 \9 h* I' O1 H8 @
  109.                 //PCON |= 0x01;        // 进入省电模式! o5 z! `5 l. N" x2 U
  110.                 //_nop_();
    ' p# M) N! K0 D  }3 b" k
  111.                 //_nop_();* e+ ]1 o6 M+ L# ]  J6 {
  112.                 //_nop_();
    ' r8 G: E2 F! F- F& [0 w: D7 E- m
  113.                 //_nop_();
    & r5 a3 s7 h1 a  ?
  114.                 buf = ~((P1 & 0x3F) | ((P5 << 2) & 0xC0));
    4 \% ]; K7 a; e" E3 z! z/ P' v
  115.                 bufReady = buf;
    " T9 L' m, w+ P' _
  116.         }5 n  _5 I' |, R5 G* D. }
  117. }) n+ {* r4 F6 s
复制代码

2 Y( T4 y2 y% Y/ p' T0 h" z* Z硬件参数配置无特殊要求,晶振频率选择12M即可。
2 P9 d+ I7 D0 w- N' Q8 J/ P8 e! t! u% j. X7 Y: x# l" W
这是编译好的固件。

本帖子中包含更多资源

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

×

评分

参与人数 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:052 k, }' b+ f0 l
不错的设计,想问一下楼主,FC的15针公头怎么解决?普通的公头太短了,插不进去FC的扩展接口。 ...

' }1 r4 U( q, X坛友的改造方案
回复

使用道具 举报

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

使用道具 举报

发表于 2019-5-25 12:07:18 | 显示全部楼层
精彩,楼主动手强,也写得很详细。
3 r, j, t7 q% C  `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:072 g& D9 _2 l3 v  B; D. N+ X
精彩,楼主动手强,也写得很详细。$ A2 I9 c( G. w  }# A; O
2.4G方案是目前无线的最低延迟吗?
* o: v! t4 L: G) v8 v! J1 j
我没用过其他无线手柄,所以实在不知道我自己做的这个手柄到底是不是最低延迟。* ?' k" T9 K5 S# }" w" D; d
不过根据网上的说法,延迟高低主要是由通信协议的复杂程度,以及数据传输速率决定的。这个模块虽然是2.4G无线模块,但由于协议很简单,所以延迟比较低。
- J  x( ]# Y) M% H( P8 @- K我用这个手柄玩一些ACT游戏,比如超级马里奥、忍者龙剑传、热血系列,完全感觉不到延迟,和游戏机自带的手柄没有任何区别。唯一的区别就是这个手柄是用火花山寨手柄改造的,外壳是垃圾回收塑料,粗糙+脆弱,导电橡胶弹性不佳,手感不是一般的差。
1 t$ g, ~4 s6 M+ Y8 w& r我手里还有十几张板子,等我有空了我再做一套,到时候买一个好一点的手柄改造。
回复

使用道具 举报

 楼主| 发表于 2019-5-29 16:56:14 | 显示全部楼层
ppad 发表于 2019-5-28 17:27/ r# Z8 n* Y- F( t) }$ p
给技术帝赞一个,有半成品发布吗,自己焊接改造就可以,编程实在不会啊 ...

" u0 `* ^& U) c- O' T) _+ o1 e很可惜,我手里没有多余的单片机了,LDO也找不到了,锂电池以及充电模块更是没有了。反正就是该用到的元件基本都没了,所以没法发布半成品。
1 B$ Q, V/ n3 r7 g7 |+ j3 ~4 R两个板子倒是有十几张剩余。" k$ P; F+ t9 E% V+ |$ \& P) W
你要是有USB转TTL串口板,完全可以自己买这两种单片机,然后我给你编译好的固件,你自己用串口板下载到单片机里面就行了。两个2.4G无线模块也得通过串口板用AT命令设置参数,不过好在我在设计电路的时候就已经预留好了串口,可以直接在线下载和在线设置参数。总的来说并不麻烦。
回复

使用道具 举报

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

8 h1 h6 c5 p  }5 Z9 F能得到孙大师的赞誉,不胜荣幸!
0 W* D# l3 u* n0 }不如开发一个多功能手柄,比如用SFC手柄改造,L/R键配合其他组合键可以用来切换2P~4P、调节连发速度、软重启等各种功能。接收端插到15PIN扩展口。
回复

使用道具 举报

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

本版积分规则

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

GMT+8, 2026-5-1 17:36 , Processed in 0.103167 second(s), 14 queries .

Powered by Discuz! X3.5

© 2001-2025 Discuz! Team.

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