找回密码
 注册

QQ登录

只需一步,快速开始

查看: 24226|回复: 29

自制FC无线手柄

  [复制链接]
发表于 2019-5-22 14:16:45 | 显示全部楼层 |阅读模式
本帖最后由 雷精灵2046 于 2019-6-14 09:28 编辑 ; w1 a* w" ?; \& z

/ n9 |. P; D3 H/ t没有用复杂的分立元件搭建发射接收电路,直接用的现成的2.4G无线模块jdy-40。
" m5 \! v8 k9 e6 R( W  X# y9 C7 `
! q  D# H: Q* ?) |( Q0 K/ c: d6 g: e% f) L0 s' y* L, w
发射端靠3.7V锂电池供电,用了一片SOP8封装的STC单片机,负责产生连发脉冲,同时负责检测电池电量,电压低于3V左右的时候触发低压中断,低压指示LED就会亮起来告知该充电了。平时发射模块和单片机均处于睡眠状态,有按键按下才会唤醒,从而实现省电。实测睡眠状态下整机电流约1~2uA。板子洗了一下稍微干净了一点。因为对于微功耗设备来说,焊接残余的助焊剂可能会增加漏电流。( b' D6 z& K) u" b; g0 ?# ]

* ~' J+ i/ C. A! H8 k! I6 P' b买了一个火花的FC山寨手柄,去掉里面的牛屎板子,并修正一下塑料挡板,把锂电池和充电模块装进去。% Y; ~  I- M: o# _9 |# K8 g% y
为了减少体积,充电模块裁剪得十分小,并且更换了充电电阻使之适应这个小小的锂电池。这么小容量的电池,也不需要多么大的充电电流是吧?( e- S1 I+ \4 n# W9 Y' H: V$ U
然后统统用热熔胶粘上。充电电流比较小,所以发热很少,不会熔化热熔胶。
7 t# T, _$ ?- e! c5 \& B: [7 g4 c! m, D: V. N# b

: u; K( v$ k# o
( L! J( v, N5 O. _最后把按键、导电橡胶和电路板装上去。
! ~, m2 [- ~2 ~% k3 Y精心裁剪了电路板,正好扣上,不会阻碍其他元件,也不会影响后盖和拧螺丝。
5 w% o" o& }, c1 b5 ^+ S& C$ `% o, T. E

3 R$ K2 J, N. F! v" z完工!8 }3 l& l* }) I  B

/ ^6 r7 J2 ^* s' G4 A$ d; F0 `) F0 m% G! _
这是充电的MicroUSB插座。旁边的小孔用于透出低压报警LED的光线。
* G, R$ ~! c" G- X4 v/ ]+ l
! d: r  u; P% Y3 m5 P* B0 m  d, G$ v" n$ G) U6 I0 p" z6 ?$ {' v2 p
接收端用一片DIP16封装的STC单片机模拟CD4021。为啥要用单片机模拟而不是直接用CD4021?因为jdy-40模块接收端在有按键按下的时候输出高电平,无按键按下输出低电平,和普通手柄正好相反。当然我也可以用两片74HC00或者74HC04之类的逻辑门进行反相,但那就增加了芯片的数量。对于FC手柄这种工作频率并不高的设备来说,STC单片机完全可以胜任模拟工作。% {( M& H4 i% _# v3 ^
3 E. v1 d. e6 d- i! {

1 y' ]; v2 n1 ^8 l! \+ }/ W& k3 o! m* \( s
电路设计有点小小的错误,所以有几根飞线。原本设计使用低压差LDO是XC6206,结果在做这个接收模块的时候,买的LDO居然找不到了!无奈只好用了AMS1117。幸好对于接收模块来说是5V降到3.3V,1117可以胜任。要是发射端手柄的话,3.7V降到3.3V,那就非得用6206不可了。
6 r' k8 G: E0 W! w
" Z+ w! L4 X+ B4 j; |实测十分灵敏,延迟极小几乎感觉不出来。可惜这山寨手柄的手感并不佳,尤其是方向键,软塌塌的。看来我得买个剪线手柄改装。
# }7 L1 u! e( H' S2 ~$ M
% O1 d2 b$ ~" Q: J2 X这是电路图,有兴趣的朋友可以参考。7 z7 P( B: L, a
  w4 R, A* ?: r* S6 ~
& w$ _4 k, S( |1 K0 y) q3 W
我信奉开源主义,十分痛恨把技术藏着掖着。好东西大家分享嘛!所以两个单片机的源代码大公开!
% u: f4 B7 h6 r编译器:Keil 51。
5 |( |' H$ C4 T" g  z, p3 i/ L# n( {' e: f1 b* ^0 f
发射端:5 j+ P& Y7 O* |) }" c  B
  1. #include <INTRINS.H>" R4 m0 u( ?3 W% H8 Q
  2. #include "STC15W.h"
    / ^! D8 |+ \% v! u# J4 D

  3. 6 R# S! ]3 v" Y0 G% q' E) }
  4. 2 p8 |% A: W4 \! K) l
  5. /*
    # N9 B+ u1 A5 j& g$ ]
  6. --------------------------
    2 Z8 m# \/ D8 I
  7. |1 (OUT)        \__/   (INT1) 8|
    + H0 h# z7 b- j/ @& A5 n& o
  8. |                                                   |
    7 n% s- {( g, ^, h; d: R) M4 B
  9. |2 (VCC)                   (INT0) 7|
    ! y7 M0 G& i" I" u; H6 s% j. b
  10. |                 STC15W204S                   |$ Q3 z, i3 l& a4 l. L. K
  11. |3 (LED)                         (TXD) 6|- o5 P. i0 Z/ f, C' `0 W3 U
  12. |                                                   |% u' ?5 R9 P5 u3 ~* I2 p+ s
  13. |4 (GND)                         (RXD) 5|' I- E8 i# ~5 H1 J" H' T
  14. --------------------------
    8 m+ i9 t: V* \& j& O9 i
  15. 2 Z9 {, u. T' Q
  16. LED ---|<|---[===]--- VCC
    + x, Q  _* I, Q' }  b
  17.            Red          330( Z# i2 ~  a7 j
  18. 8 M# Q1 ~2 H( u$ o
  19. Fosc = 6MHz
    / V' Z( \. G& o$ @: s! j1 C
  20. */! \3 J  \; E. R( f9 @, {. [
  21. + b) T( j; g, L

  22. - {- q! d" I( B) ]  v7 `! u
  23. // 矩形波输出脚
    4 l. D7 c$ M; V/ b! R; N
  24. sbit OUT = P5^4;1 [# W8 w# J0 p: b
  25. // 低压指示灯引脚# Q7 k2 H' w4 M; Y6 l0 P
  26. sbit LED = P5^5;' a& {! n5 I1 e& f* y9 X; h! z. }& E

  27. 3 r. s0 `# f/ V8 R6 e) i8 l) N0 [
  28. // 停机标志位
    + y2 q5 n( X0 D( v
  29. bit isReadyToHalt = 0;+ `2 k& b0 D1 z, x3 z9 P: P; ~

  30. + Q0 e+ D/ R- D, q) R3 n
  31. // 矩形波次数累计
    # S- k# O0 x: ^, f2 S. B
  32. static volatile unsigned char count = 0;
    , k$ {9 i" u  h6 H4 ?  V# @
  33. . G5 a) b1 w! s' v( l# S) h3 b/ E6 Q
  34. # w4 p1 t" k8 }) p
  35. static void GPIO_Init(){& {; [. i- p) H1 l2 n1 O
  36.         // P3口设置为准双向,默认靠内部弱上拉输出高电平
    ( O9 C: p7 o, o
  37.         P3M0 = 0;) Z" n5 O" H6 x& b
  38.         P3M1 = 0;
    4 @1 r) T# U# `" H3 [$ A5 v8 m- ^
  39.         P3 = 0xFF;
    1 H0 a! \8 J4 B/ V
  40.         // P5口设置为准双向,默认靠内部弱上拉输出高电平1 p. m- G% e  n
  41.         P5M0 = 0;
    9 S6 d6 N. I% |
  42.         P5M1 = 0;# C  w7 p, z: l  F2 H* y  S
  43.         P5 = 0xFF;6 ?8 `( {9 f/ C
  44. }
    5 T5 w* k* z3 W: w
  45. # @" U6 Z; O* o$ k  |' p$ n
  46. static void Timer0_Init(){2 e$ L  j+ j3 ?7 V) G: q2 j1 V
  47.         // 16毫秒@6.000MHz* y! D( d5 Q& U) t6 I
  48.         AUXR &= 0x7F;        // 定时器时钟12T模式
    4 P  a; m& ~7 S% X& g
  49.         TMOD &= 0xF0;        // 设置定时器模式. g& f2 g# r* ?0 h
  50.         TL0 = 0xC0;                // 设置定时初值
    6 V! m* d+ S, N7 e( B
  51.         TH0 = 0xE0;                // 设置定时初值
    5 @1 }8 j! A- R% z
  52.         TF0 = 0;                // 清除TF0标志# b  m9 ~0 U! ]3 G/ K' X& N
  53.         TR0 = 1;                // 定时器0开始计时1 M- [7 _6 m7 Z+ m. x
  54. }
    0 j# X1 I  W: R/ G

  55. ) X. f/ p' [0 B$ S; X4 c1 h# Y; R
  56. static void Interrupt_Init(){
    ) A( Z! f" S, S: r6 R4 U; [
  57.         // INT0中断触发类型为下降沿触发& E% N2 R% C9 h" Q" |7 |
  58.         IT0 = 1;
    4 k) ~. Y+ _4 P1 i! z; c6 i
  59.         // 允许INT0中断; r" E4 V. r% ~: ?! b8 l& y9 L5 \
  60.         EX0 = 1;3 z2 V9 c- a& L" x* m8 f- I) F
  61.         // INT1中断触发类型为下降沿触发
    . `/ a4 t+ k' d8 x8 x
  62.         IT1 = 1;( V  ^3 L1 t# I8 U
  63.         // 允许INT1中断; n# S. _# m& c' Z6 J
  64.         EX1 = 1;
    ( }7 ]. L+ Z- |! \
  65.         // 允许定时器0中断5 q+ c2 C1 q7 ~. L. l6 y% a/ K) _
  66.         ET0 = 1;5 }1 ^& j2 A6 B
  67.         // 允许全局中断
    7 C: c" G8 v9 O2 C2 O, \! @
  68.         EA = 1;4 V+ I& o: z1 Z! M4 g; a
  69. }3 \- G9 e  U5 r7 E. G2 ]* |0 x& \

  70. 4 B" e' k! }  Q3 s
  71. static void INT0_Isr() interrupt 0{( |; d, [1 A! K2 @7 \" J6 b+ u' V' A
  72.         // 矩形波次数累计归零
    4 z8 C. o! y8 @
  73.         count = 0;; V  V( E( ?2 W' ]) }
  74.         // 重开定时器0中断. C7 ]. F* d& M5 ^/ k
  75.         ET0 = 1;
    ; z1 {5 E9 d4 ]# z* K' p
  76. }
    + K- E4 f! j: u
  77. . w. w; u! v: H0 ^
  78. static void Timer0_Isr() interrupt 1{$ o0 l- t! M, z7 H$ c$ e9 k
  79.         // 输出矩形波) Z3 J* Y) y' x+ o9 U
  80.         OUT = ~OUT;  s+ H# P+ ^9 F, V$ \- c' }
  81.         // 累计矩形波次数
    . y3 X6 i6 u& }! w
  82.         count++;
    % t. B3 J- H9 ]
  83.         // 超过250个矩形波,准备停机
    * Z% W2 I3 r- N
  84.         if(count > 250){- H  W9 O) f4 U3 F+ m- A
  85.                 count = 0;
    6 w$ m' H# `0 ?3 @
  86.                 isReadyToHalt = 1;
    : y3 [, r$ e# e
  87.         }+ c% r9 G3 k. D) w7 |1 s0 J
  88. }
    4 D# I6 ~& N8 c8 a: a5 S; h
  89. # w, [0 |4 A3 l8 e2 n6 q
  90. static void INT1_Isr() interrupt 2{$ o3 ]. \9 f; p# x0 A
  91.         // 矩形波次数累计归零3 x' a* _) q0 }0 T1 k
  92.         count = 0;8 q" C' {) d2 O5 J$ b7 Z9 Y
  93.         // 重开定时器0中断
    , m5 y- {0 r2 q
  94.         ET0 = 1;
    7 u) y: x. W7 [1 ^
  95. }+ l. w% L  D9 }" E
  96. # n# O% L6 A' G) |. J
  97. + F$ T4 F! d" I- d. U8 s
  98. void main(){
    # W9 v: k. ]" p! _! E3 ?2 X
  99.         // 初始化P3和P5口
    7 W! u7 M9 t6 E4 ?$ i
  100.         GPIO_Init();: D+ L2 N' q7 {2 `( f# u
  101.         // 初始化定时器07 j7 O) K8 A7 @8 R
  102.         Timer0_Init();: }; U3 c, N' i# E, }1 d# H
  103.         // 初始化中断
    . R! s( u4 a& C& c3 s* U
  104.         Interrupt_Init();
    ; d* w- `; c/ p9 K
  105.        
    1 n6 G' O1 [- ?5 Q& m; @
  106.         while(1){
    ; a) U& T, P) S% d1 I% S
  107.                 // 检测电量5 n+ j; \4 }4 P+ p
  108.                 if(PCON & (1 << 5)){
    , t8 Y3 x$ g: [9 \) x! t  I1 R/ C" A! D
  109.                         // 如果电量低,低压指示灯亮
      t- e, @" l0 a. p0 b7 d/ b/ \% D
  110.                         LED = 0;0 R2 b1 ^+ W% H  b% v
  111.                         // 清电量检测硬件标志位
    9 P# ~' o$ c. V% X2 Q
  112.                         PCON &= ~(1 << 5);
      Y; f" H" B# c
  113.                 }else{
    3 `. X: |8 b3 y4 U
  114.                         // 电量正常,低压指示灯灭6 W# @, @. r/ F: J$ h
  115.                         LED = 1;+ ?  F0 ~1 _0 I
  116.                 }
    8 p. [6 M' d6 k" [' c3 G: W: ^

  117. . Q6 l9 a( f. B5 h3 A1 j% G8 }
  118.                 // 检测到停机标志+ c& P" Y0 j. X% O, f8 \! e( f8 K
  119.                 if(isReadyToHalt == 1){+ L$ Z% B! ~# a, V' I
  120.                         // 暂时关闭定时器0中断  H# d8 p7 ?7 n; k' B% N
  121.                         ET0 = 0;
    9 q4 C6 B  j, Q6 }. u! |8 p5 n7 H
  122.                         // 停机之前先把矩形波输出脚置低电平,以方便INT0和INT1唤醒CPU% w9 n; X2 I3 M( w% z
  123.                         OUT = 0;
    * l4 G$ p( \! e" H3 x  F
  124.                         // 停机之前先把低压指示灯灭掉,以省电
    : M( h# k+ i; G7 Y( ?. H$ P1 N
  125.                         LED = 1;- i9 \7 ~# u- ~; J; M+ b
  126.                         // 进入停机模式" ^$ b  ]1 N. f8 {8 h* ?# @2 W7 V
  127.                         PCON |= 0x02;
    ) s; s. k$ _9 ?/ @
  128.                         _nop_();2 N3 k- s0 t$ K, f; }! f
  129.                         _nop_();
    + F! T  O! R# B/ a; G
  130.                         _nop_();4 t2 X( f; s9 R9 Y( Q
  131.                         _nop_();
    5 e1 P% _' W! p3 E& E8 E1 O
  132.                         // 唤醒,清标志位& h; n7 k) `+ g& A
  133.                         isReadyToHalt = 0;+ |! _3 c; v, W8 \* m) t6 O& h
  134.                         // 重开定时器0中断
    ' ^3 k" w' }# b9 L
  135.                         ET0 = 1;7 q% a% f5 Q5 a4 ^1 v
  136.                 }
    % P, @9 E3 r5 U% k8 D5 M* J
  137.         }* X, ?' J+ h- n4 e3 F7 S+ Y
  138. }
    8 ~6 }  h. m8 R6 ~0 Q( B
复制代码
7 \& d5 p6 t) o4 k- y: ~- c  g
硬件参数配置:. c% s7 f1 P8 @! R! H

/ I, e4 g/ |1 s' s3 n1 D% `0 ^! \5 N8 v& a1 `6 {
接收端:8 P9 M4 F1 S7 q6 {( e
  1. #include <INTRINS.H>6 }6 b! J3 c2 x5 T0 M5 j- a
  2. #include "STC15W.h"
    8 u$ l( x; C9 m6 }- Y. H; i
  3. ( r: N# h7 ?/ @2 {& c2 E% c
  4. 2 w/ v3 q3 N# B
  5. /*1 v! A4 s! s( |3 \3 x; [8 E# b7 _" [& v
  6. " o! r  i% U( I- `! f- Y
  7. *---------------------------*
    2 }+ q- g. ^. n% X
  8. |1 (GPIO2)         \__/  (GPIO1)16|
    5 k6 q3 t7 t( g4 c$ O- D2 V% I3 V
  9. |                                                        |
      k- X# q2 B! b$ h4 g" E8 S0 Y
  10. |2 (GPIO3)                   (GPIO0)15|5 a& ^2 I7 t7 R7 D6 C
  11. |                                                        |! c3 `- [9 w3 b: w/ V9 x
  12. |3 (GPIO4)                                  14|
    : o& Z1 C2 n; ~+ _
  13. |                                                        |
    ) u1 l& D2 e$ T" U# {2 t
  14. |4 (GPIO5)                        (DATA)13|: `- V7 Q( `8 S! w1 u& H
  15. |                  STC15W204S                |6 }2 w# Y% w; u4 _5 ^( _; _+ }$ `
  16. |5 (GPIO6)                   (LATCH)12|
    3 o4 n. c8 k  S" p. p+ z9 j
  17. |                                                        |
    + P! j' a( D0 {! N
  18. |6 (VCC)                         (CLK)11|* T, @; N. }8 ~: W1 {
  19. |                                                          |
    ' [0 z2 F, U% `" l# J& p
  20. |7 (GPIO7)                         (TXD)10|
    , \+ `; ^8 |5 _5 T2 M
  21. |                                                        |$ U5 \" f3 ?( ?; u9 ~3 f
  22. |8 (GND)                         (RXD) 9|8 h1 _: o# V/ C0 I
  23. *---------------------------*
    - v! b* s4 s  Y8 `" j0 y+ y* N
  24. Fosc = 12MHz
    1 M( N) Y, }, U' G
  25. - I5 w( q# l9 C1 D4 i
  26. P1.0 -> 上
    / u, W0 D3 d# F/ |* f$ O+ {0 y
  27. P1.1 -> 左
    , d4 O- u6 P, K# u: m. o
  28. P1.2 -> 下" w' O' ~" t) g* n$ Q
  29. P1.3 -> 右
    $ {6 k( z, c, d$ o4 M1 B
  30. P1.4 -> SEL+ k" c( b1 _+ K# l1 a" ^
  31. P1.5 -> STA  @6 Y4 n9 j! y# H# S) @0 Y  u
  32. P5.4 -> B! h: H- ~  l$ u) y) Q8 l% R3 H& G
  33. P5.5 -> A
    1 `! R4 f0 J5 I" {! v9 _/ p6 k

  34. ' b5 d* a7 W6 \, R/ {' ^
  35. */
    ; r4 R) |: m# n4 [. l- y0 C+ _
  36. ! n+ |5 h  u' H) F
  37. , K2 F. u8 {" X/ J9 z7 o6 B  a  E
  38. sbit CLK        = P3^2;) H4 u( U1 y% k  @/ p) z# A
  39. sbit LATCH        = P3^3;
    " \8 N5 Y) B) n3 Y
  40. sbit DATA        = P3^6;& r% ~" g% `) l7 e: c' Y; v

  41. 2 S8 r/ x2 l$ U# M) \1 R2 Z9 ~
  42. bit isReady = 0;
    6 y  ]& S; N8 H( L/ A1 c& w/ Z& z
  43. static unsigned char key = 0;
    5 x' g2 c2 Y( c7 j" N9 i
  44. static unsigned char buf = 0;        // 双缓冲。这个缓冲区保存从P1和P5组合而来的键值9 W$ _& _6 H' I5 R% U5 H) S
  45. static unsigned char bufReady = 0;        // 双缓冲。这个缓冲区保存上面那个缓冲区的备份
    ) ~: T& P! R$ K* {" G0 i
  46. static const unsigned char data mask[] = {0x80, 0x40, 0x10, 0x20, 0x01, 0x04, 0x02, 0x08};        // A B SELECT START UP DOWN LEFT RIGHT。为提升速度,这个表放到RAM中# o! K% S$ l" P& ]0 D8 V8 l0 T3 m
  47. static unsigned char idx = 0;' X: \+ \9 }8 b1 m- }5 m

  48.   p) ]+ Q  Z1 Z% }; E! W2 I5 Q
  49. ( w, J. \% F+ s" c6 S
  50. static void GPIO_Init(){
    " r/ a6 T6 b7 C8 z4 J
  51.         // P1口和P5口用于接收并行信号,全部初始化为准双向,依靠内部弱上拉输出高电平8 G7 M8 n* Y2 U# f8 D+ ~
  52.         P1M0 = 0;
    ; S2 H1 P- F( i  ?+ o! w2 U
  53.         P1M1 = 0;
    3 Q; p. l8 `7 }7 Q( r( g& ~
  54.         P1= 0xFF;
    7 |3 r5 a& U+ q9 L& f* ~. i' ]
  55.         P5M0 = 0;
    . C* v$ O, ~- e. `) P0 [
  56.         P5M1 = 0;
    ; H& Y+ ?) w. _8 f4 c
  57.         P5= 0xFF;! a" K3 ?, y8 L( {
  58.         // P3口初始化为准双向
    6 }- x( X9 A$ M; [8 N, P
  59.         P3M0 = 0;
    0 K! `% O. E  v1 `
  60.         P3M1 = 0;
    ' N( k8 F' [' \2 |/ y, D
  61.         P3 = 0xFF;
    ! V; U( x+ i/ j9 f% E' B/ q
  62. }7 K: \- t+ k1 E( C/ [
  63. , [; x. E& _% i8 g
  64. static void Interrupt_Init(){
    6 U, A8 j4 i8 r# @, s, R1 p
  65.         // INT0中断(CLK)触发类型为上升沿+下降沿
    6 X9 r2 N' G" }4 O- R& g
  66.         IT0 = 0;! C4 ~. ]4 ^; z. d7 p
  67.         // 允许INT0中断3 c8 ]& y0 g' d: ~$ D0 Q/ z
  68.         EX0 = 1;
    , H( P5 P( b4 [4 a/ D* j$ L: X/ s  T
  69.         // INT1中断(LATCH)触发类型为上升沿+下降沿
    1 l6 P' [, t9 L( d
  70.         IT1 = 0;* A. G7 w0 i8 |
  71.         // 允许INT1中断
    / v' M: ~% \2 r: ]) S0 ]
  72.         EX1 = 1;9 i; \7 x9 `! T3 m7 d
  73.         // 开启全局中断
    : B$ j0 S4 l8 {. h9 Y! ]6 S
  74.         EA = 1;1 o1 y# t! c8 [, b, E: S: O
  75. }* a6 J0 b: @; C# B" L0 ]! C
  76. 1 D* \( b* z  x' \
  77. static void INT0_Isr() interrupt 0{
    8 X. ^; m3 Q$ G! E2 r, {9 O
  78.         // 只有已经成功锁存才允许CLK移位
    3 U" T1 s$ k6 H! V0 V9 I8 O7 I. m
  79.         if(isReady == 0)$ y0 ]# f; j' F4 _, T, U0 @; E
  80.                 return;
    , s. e6 c+ h( g' P9 a7 E
  81.         // 读当前引脚电平,如果是低电平则说明是下降沿,此时直接忽略该中断
    & K% \' @% u5 R
  82.         if(CLK == 0)$ J: V5 L4 l8 Z9 w/ a; N2 U7 m1 f
  83.                 return;+ M" N4 U* h3 T- e
  84.         // CLK上升沿到来的时候,取锁存值的下一位输出
    5 v; O( U5 D: u" T* k. A
  85.         idx++;+ C8 R: }/ h0 c) X5 }3 c
  86.         DATA = key & mask[idx];- {! b! R) x4 y1 \% p
  87.         // 如果已经完成7次移位,则一轮读取完成
    7 n' T6 E8 s6 z9 I/ w
  88.         if(idx >= 7)6 ]; v: h4 A6 `" Q, W
  89.                 isReady = 0;  W! R5 v6 L4 b0 c& C
  90. }" \" Z- B$ @) H2 x
  91. 7 p$ G4 G! u; c3 @  @1 }: B
  92. static void INT1_Isr() interrupt 2{1 x4 s+ T# H/ q0 d
  93.         // 读当前引脚电平,如果是低电平则说明是下降沿,此时直接忽略该中断
    * |: e% Z# G2 L- \7 W
  94.         if(LATCH == 0)
    , g5 O  E8 K5 \7 Y4 x# K1 b
  95.                 return;! i. x: C. c7 G0 F5 R  a, K* ]
  96.         // 当LATCH上升沿到来的时候,锁存所有按键状态,同时把键值A输出到DATA. m4 D- ?$ R8 q! i# I7 k  [: X
  97.         key = bufReady;7 \, q" w6 T+ O, f0 k
  98.         DATA = key & 0x80;//mask[0];        // 为了加速运算,直接取表中的值而不是读表2 v$ T2 n, C! i6 Q6 l" w
  99.         idx = 0;2 s2 V0 I) A. B$ @1 n- N, D
  100.         // 允许CLK进行移位6 \( m+ ]) c2 k1 v
  101.         isReady = 1;0 Z2 n, W: g& j/ J
  102. }6 A: J9 J% p1 N2 T4 }2 }/ G( G. {

  103. 1 k8 `& B# N5 |1 E& _9 X
  104. void main(){
    # b7 M' x. \+ ~" J
  105.         GPIO_Init();
    4 U. K6 G7 d/ ~$ S
  106.         Interrupt_Init();, t  @- f0 r& b( i
  107.         , N5 B& _4 t$ u% z" {1 P$ v" G
  108.         while(1){6 j) L+ f2 ?8 L6 T# o1 R
  109.                 //PCON |= 0x01;        // 进入省电模式
    ! B9 Q, o* q4 ?" y1 w8 W
  110.                 //_nop_();
    / z+ O% J8 A$ \) E1 Y) W
  111.                 //_nop_();
    " ^  i9 p* d, ?1 H
  112.                 //_nop_();
    9 t- c; O2 L6 p# }
  113.                 //_nop_();& x. c8 }. _5 {& e8 A5 H; S
  114.                 buf = ~((P1 & 0x3F) | ((P5 << 2) & 0xC0));
    * _: E. S- p: l& Z+ x4 [
  115.                 bufReady = buf;
    # r1 N2 T$ r6 F# @7 k- c
  116.         }
    6 G% j2 X! g. h6 z
  117. }) d: r+ w6 n$ Q3 y
复制代码
: P2 n3 _9 K& X8 B
硬件参数配置无特殊要求,晶振频率选择12M即可。
/ D( @2 X+ Q# X: z! K
3 T* ^3 r/ `. ~0 Y这是编译好的固件。

本帖子中包含更多资源

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

×

评分

参与人数 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
3 @3 {, C3 |3 k% D5 q不错的设计,想问一下楼主,FC的15针公头怎么解决?普通的公头太短了,插不进去FC的扩展接口。 ...

& s, o; }/ O1 W- A; ?$ I+ H0 @+ G坛友的改造方案
回复

使用道具 举报

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

使用道具 举报

发表于 2019-5-25 12:07:18 | 显示全部楼层
精彩,楼主动手强,也写得很详细。& e+ M# m$ q9 @5 k. w! J% J7 J
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
9 \/ c. H4 l- R+ ?- K精彩,楼主动手强,也写得很详细。
% m* t% D; u* ~' `- x# F* Z: p, p2.4G方案是目前无线的最低延迟吗?
; y' F" ~7 g2 _" q
我没用过其他无线手柄,所以实在不知道我自己做的这个手柄到底是不是最低延迟。
/ W: G% h4 D- x& F# x  Q不过根据网上的说法,延迟高低主要是由通信协议的复杂程度,以及数据传输速率决定的。这个模块虽然是2.4G无线模块,但由于协议很简单,所以延迟比较低。# W3 n. S. j2 R
我用这个手柄玩一些ACT游戏,比如超级马里奥、忍者龙剑传、热血系列,完全感觉不到延迟,和游戏机自带的手柄没有任何区别。唯一的区别就是这个手柄是用火花山寨手柄改造的,外壳是垃圾回收塑料,粗糙+脆弱,导电橡胶弹性不佳,手感不是一般的差。: `' x" m' y5 d' e+ O- G, v
我手里还有十几张板子,等我有空了我再做一套,到时候买一个好一点的手柄改造。
回复

使用道具 举报

 楼主| 发表于 2019-5-29 16:56:14 | 显示全部楼层
ppad 发表于 2019-5-28 17:27: E6 x2 b! d8 Y# p8 ^5 c/ H0 V3 c
给技术帝赞一个,有半成品发布吗,自己焊接改造就可以,编程实在不会啊 ...

5 \( N3 H. s! j) T2 J: g很可惜,我手里没有多余的单片机了,LDO也找不到了,锂电池以及充电模块更是没有了。反正就是该用到的元件基本都没了,所以没法发布半成品。
1 \, n" H( S( A' w4 U; [/ |两个板子倒是有十几张剩余。% h! K( p$ B& }# E! Z* e
你要是有USB转TTL串口板,完全可以自己买这两种单片机,然后我给你编译好的固件,你自己用串口板下载到单片机里面就行了。两个2.4G无线模块也得通过串口板用AT命令设置参数,不过好在我在设计电路的时候就已经预留好了串口,可以直接在线下载和在线设置参数。总的来说并不麻烦。
回复

使用道具 举报

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

0 E. a3 ]" }6 T# D能得到孙大师的赞誉,不胜荣幸!
/ y5 s8 S6 {# j$ E不如开发一个多功能手柄,比如用SFC手柄改造,L/R键配合其他组合键可以用来切换2P~4P、调节连发速度、软重启等各种功能。接收端插到15PIN扩展口。
回复

使用道具 举报

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

本版积分规则

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

GMT+8, 2026-3-22 12:36 , Processed in 0.110836 second(s), 15 queries .

Powered by Discuz! X3.5

© 2001-2025 Discuz! Team.

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