找回密码
 注册

QQ登录

只需一步,快速开始

查看: 26023|回复: 32

自制FC无线手柄

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

2 Z8 \& \" `- M1 p9 R5 m% K# a9 _" k* ^
+ u! G: r/ G1 |; G& s$ u
最后把按键、导电橡胶和电路板装上去。
" o+ E* }) t. l  w精心裁剪了电路板,正好扣上,不会阻碍其他元件,也不会影响后盖和拧螺丝。* g# ~' e7 ]' p6 B, j6 s

, E* z  ], P' c! H9 B
" b& J8 b3 V6 Q" T* o$ j6 K8 q完工!
+ \2 O! c: Z  e* T4 _& |( c) A
  |% A) H; Z3 C! s4 i* ?3 v4 E4 d5 l& v6 J2 U
这是充电的MicroUSB插座。旁边的小孔用于透出低压报警LED的光线。
% ^( s7 Z, V8 d+ p0 U) A- B' @: ^$ |# O+ o
9 a: y6 t4 a* j: i- s
接收端用一片DIP16封装的STC单片机模拟CD4021。为啥要用单片机模拟而不是直接用CD4021?因为jdy-40模块接收端在有按键按下的时候输出高电平,无按键按下输出低电平,和普通手柄正好相反。当然我也可以用两片74HC00或者74HC04之类的逻辑门进行反相,但那就增加了芯片的数量。对于FC手柄这种工作频率并不高的设备来说,STC单片机完全可以胜任模拟工作。
0 A  j5 _! u, F1 v9 M7 c: s6 l4 s3 [5 b6 g% k1 x3 z" E( u, Q1 m. t+ Q

; w; X0 o+ n6 Y6 I4 v- H3 R% R  m' I' e. E
# R; O. \9 l  h/ c2 |& H7 }电路设计有点小小的错误,所以有几根飞线。原本设计使用低压差LDO是XC6206,结果在做这个接收模块的时候,买的LDO居然找不到了!无奈只好用了AMS1117。幸好对于接收模块来说是5V降到3.3V,1117可以胜任。要是发射端手柄的话,3.7V降到3.3V,那就非得用6206不可了。
6 y5 n) A' k. u# K/ i+ _& D; s9 b; r9 M' \: y1 J4 w
实测十分灵敏,延迟极小几乎感觉不出来。可惜这山寨手柄的手感并不佳,尤其是方向键,软塌塌的。看来我得买个剪线手柄改装。) m* U1 D$ j! C; ^) C
, [( J% Q+ {% \6 ^) ^  g
这是电路图,有兴趣的朋友可以参考。
5 z& w& w- w- S4 t7 `* V0 K( Y) r# m( ], Q: }* F& }, p; E6 D
! U3 t3 O, t4 J& y# h& d0 b
我信奉开源主义,十分痛恨把技术藏着掖着。好东西大家分享嘛!所以两个单片机的源代码大公开!2 s  D3 y2 t4 r
编译器:Keil 51。& B8 j4 n) M" k+ M* X; O# A4 h. D0 @

) L3 S* v' g6 |8 r1 M发射端:% Q9 c: Z- d$ z( c
  1. #include <INTRINS.H>
    ; q9 O7 H7 f( \: i. j2 h
  2. #include "STC15W.h"
    : I4 l) [( B( L4 W5 r6 U/ @

  3. 9 l' _5 }* p8 a; x" ?
  4. 7 h% b4 J1 r4 U0 p4 q, V
  5. /*
      C8 \( I, Z- S" A! P0 Q2 M6 @
  6. --------------------------
    + U' p3 P) X- M+ H
  7. |1 (OUT)        \__/   (INT1) 8|
      b" U2 U  x, G5 P" P: Z
  8. |                                                   |
    / ^! O8 x3 n: @5 y
  9. |2 (VCC)                   (INT0) 7|! Z% J+ h6 h+ a  N9 G
  10. |                 STC15W204S                   |
    ( ^5 x, w; N* a( _
  11. |3 (LED)                         (TXD) 6|
    ( ~- a3 I! x; G4 G3 Z
  12. |                                                   |
    5 i' _  x* Z- o8 L* f
  13. |4 (GND)                         (RXD) 5|3 V, e0 D5 |% N9 G; J1 ^* H
  14. --------------------------! L) B5 \+ I4 L

  15. ' h- r! [' ~- \$ C- h# p
  16. LED ---|<|---[===]--- VCC
    7 ^/ r1 ?3 f8 O2 S
  17.            Red          330
    , j! q8 |+ Y( }+ w3 B8 ~) x0 x
  18. ) r, `2 f2 H3 k' ~0 f
  19. Fosc = 6MHz
    0 N$ @8 d) G2 k% Z
  20. */* N; _1 K; o6 A

  21. ( N& m8 B7 [+ D# M- _5 f. `
  22. 0 b' t" g, T6 g" [/ @- o2 B
  23. // 矩形波输出脚0 D! _1 {# I( E
  24. sbit OUT = P5^4;: J; v3 V' e5 e8 t
  25. // 低压指示灯引脚$ t% I  I7 a3 Q- T$ c
  26. sbit LED = P5^5;
    - {5 ?' L  v; [7 V4 n0 P9 `
  27. , b* s; \3 Z( z
  28. // 停机标志位$ T6 L- m& Z3 w+ f; D
  29. bit isReadyToHalt = 0;
    3 J! w% y; C2 V6 [- u1 I
  30. # z) y5 v) J- l' ]
  31. // 矩形波次数累计
    1 O5 w  \; t6 b6 r& r" G0 M
  32. static volatile unsigned char count = 0;9 p3 ^' t; E9 a# H: t- d
  33. 9 L& [& l5 S' D/ a' n2 \4 U
  34. . ~3 X( b2 A4 N. K, c
  35. static void GPIO_Init(){% |; q9 b& ~$ ?* e  k8 I9 s
  36.         // P3口设置为准双向,默认靠内部弱上拉输出高电平8 s, ]0 t$ a0 k7 N$ p$ @5 J
  37.         P3M0 = 0;. R" p( j  s$ S6 v
  38.         P3M1 = 0;7 l: A0 M0 f3 i8 @& i6 ^8 f
  39.         P3 = 0xFF;
    $ F% a( q2 _0 z+ F" V! i) x
  40.         // P5口设置为准双向,默认靠内部弱上拉输出高电平
    1 d% B8 r$ W* t* L! H5 O3 K* m
  41.         P5M0 = 0;# F, p8 w* x4 z+ W
  42.         P5M1 = 0;  D( h9 U: ^5 N# v* X
  43.         P5 = 0xFF;+ a$ T* _& z0 n! U2 z
  44. }
    . j" R8 }% x: s9 y& h
  45. ( I: k1 v% e1 y% l3 B! t3 K
  46. static void Timer0_Init(){
    # W$ q0 \+ }- ?, O6 k8 [
  47.         // 16毫秒@6.000MHz+ |2 x' N0 f- T1 R2 z4 h4 @8 {
  48.         AUXR &= 0x7F;        // 定时器时钟12T模式$ m; I# a7 L& V. I$ {* q& V8 q' a
  49.         TMOD &= 0xF0;        // 设置定时器模式4 a* ?! w) C; g
  50.         TL0 = 0xC0;                // 设置定时初值
    - ?* @: ~8 n) @5 u# m( m
  51.         TH0 = 0xE0;                // 设置定时初值+ C+ B; X8 u4 U' e
  52.         TF0 = 0;                // 清除TF0标志
    " D$ R5 G5 ]  Y. Y
  53.         TR0 = 1;                // 定时器0开始计时6 r/ g) q7 o) }! C  x* X
  54. }1 k8 L2 Q* A1 J( x. X5 m) q
  55. - H/ d, M: d! O# l3 C9 E! V
  56. static void Interrupt_Init(){
    ; \: j5 [" o# X3 A
  57.         // INT0中断触发类型为下降沿触发6 C6 H; d3 R8 E+ O0 X
  58.         IT0 = 1;. Y; J) e+ Z4 p; [6 d, L
  59.         // 允许INT0中断
    2 o; Y1 ?2 g/ ~1 K
  60.         EX0 = 1;
    8 J6 ^; s$ ]; @% I% b7 c; H
  61.         // INT1中断触发类型为下降沿触发" y4 k! Y/ V/ b; p
  62.         IT1 = 1;+ ?; ^  A9 i" z+ f
  63.         // 允许INT1中断4 y3 u% p5 L! ?4 s& d, g9 r
  64.         EX1 = 1;9 k7 v! Y# f% K
  65.         // 允许定时器0中断
    3 @& y. \; C( a. w0 i; S: ^
  66.         ET0 = 1;* Y9 z0 n/ A8 h9 t6 W* K* a
  67.         // 允许全局中断0 \- [3 d' R0 m8 t/ Y- f6 e4 V
  68.         EA = 1;) c) m' T& r5 P3 o) t
  69. }
    9 Z' u& ?- j, ]7 C0 S
  70. 5 W8 H% {# q  Y* _
  71. static void INT0_Isr() interrupt 0{
      T( {4 r% r4 O7 _
  72.         // 矩形波次数累计归零+ K6 z% ^% M7 S# X' l8 F. e
  73.         count = 0;
    ) l9 G. i; f8 f* Y
  74.         // 重开定时器0中断+ J1 o! n4 k6 q  D4 I3 |% T& _" b
  75.         ET0 = 1;3 m0 M% s8 Y. ~% i; }6 x* E
  76. }5 f5 \3 h. E8 N# d
  77. % [( H! l; m6 u
  78. static void Timer0_Isr() interrupt 1{% J1 J9 K6 m/ z) D1 O. ^) p
  79.         // 输出矩形波: ^' a8 `1 ^) j) E  s4 C, E& n; q
  80.         OUT = ~OUT;( d& W3 O  J; R( |1 r/ H( u
  81.         // 累计矩形波次数3 r9 D, ]2 u  {0 l* R
  82.         count++;
    . L4 @/ M* C2 t
  83.         // 超过250个矩形波,准备停机
    ) ^0 t9 N+ U  ], r& `
  84.         if(count > 250){- n' P% o% x. T5 r/ g# ]$ ^3 W
  85.                 count = 0;5 h. ^3 V; d) r4 _, \* k3 B
  86.                 isReadyToHalt = 1;! @" ]- F: o% ^! T5 V
  87.         }
    ; \: `" {$ t* V% P2 @: v( i! Z
  88. }
    4 W3 T+ K; B5 m; L

  89. ! [" f3 w- e( Q7 P2 u7 n3 Y
  90. static void INT1_Isr() interrupt 2{
    2 d9 p0 \# I0 D9 p; |/ s, Q
  91.         // 矩形波次数累计归零
    * [7 V9 C- E2 c  F# P- G2 U. q1 c  a
  92.         count = 0;
    & y8 o- g: P' s! J6 w: E, B
  93.         // 重开定时器0中断: q% V# z8 E8 A! G- {
  94.         ET0 = 1;
    % i; m8 }& r1 M3 }3 R, H
  95. }
    " K4 V# N% w0 {) p# g, L
  96. ' D  O( O8 Z, Q% O: t- G8 D; A

  97. $ W, a  u& w3 }$ u; S/ z, f
  98. void main(){
    9 N7 ~4 b9 I! f6 i7 p) F' ^
  99.         // 初始化P3和P5口$ i  w! |2 X, D* I3 n
  100.         GPIO_Init();9 H* K# R7 g! Z, r, @7 v) O6 \
  101.         // 初始化定时器06 A. x" ?! ]. g
  102.         Timer0_Init();
    3 @4 x6 v; `( L; G" U4 H
  103.         // 初始化中断
    " p$ G3 B9 P2 z, o$ u9 K7 k7 ~
  104.         Interrupt_Init();) f+ X/ [* d  r
  105.        
    & m6 X" k. M1 F( b( ^3 N
  106.         while(1){- s; U) A/ N2 f& w
  107.                 // 检测电量
    7 _5 u9 m4 q8 G
  108.                 if(PCON & (1 << 5)){4 R9 _! R3 [+ E
  109.                         // 如果电量低,低压指示灯亮
    & C9 k# z* k& n& U
  110.                         LED = 0;9 C/ ]3 V, o4 h4 M  s8 Q% r
  111.                         // 清电量检测硬件标志位
    , f  N/ g) R/ B
  112.                         PCON &= ~(1 << 5);/ u5 p: h' U2 Y0 R. ~3 O9 i8 A" U
  113.                 }else{
      O% r9 C9 c( ?
  114.                         // 电量正常,低压指示灯灭
    2 \7 V5 S3 H" k. @& W
  115.                         LED = 1;: n3 z& a2 I) i2 Q9 S
  116.                 }
    ; J' z$ u1 c+ D: x" T, m6 g
  117. 6 W; k; }3 B. a$ E3 s9 [4 E
  118.                 // 检测到停机标志
    / C7 `; V( A( O
  119.                 if(isReadyToHalt == 1){9 E0 b# p8 `( o* u* k$ c/ Z# k
  120.                         // 暂时关闭定时器0中断+ M+ G' x. s* h! k$ g
  121.                         ET0 = 0;, E( u. ^# t# e
  122.                         // 停机之前先把矩形波输出脚置低电平,以方便INT0和INT1唤醒CPU
    / f$ S: b+ t1 R5 `7 `
  123.                         OUT = 0;
    ! p4 u$ U3 y( G0 Y1 K5 d- y' ?3 R
  124.                         // 停机之前先把低压指示灯灭掉,以省电
    / i# L' V" x. P$ |" W
  125.                         LED = 1;0 r% g6 W' }/ A! {' A1 Y2 u: \" |
  126.                         // 进入停机模式
    7 [3 T; j( V3 e9 |. T: R% B2 A- ?
  127.                         PCON |= 0x02;6 i5 k3 b2 B. J2 T( u: @+ ]
  128.                         _nop_();
    ' l9 V* s0 M+ M8 e; d: m
  129.                         _nop_();9 k  k1 E& q2 m* U& Q; `
  130.                         _nop_();4 j% O4 W: n# h5 s6 F
  131.                         _nop_();
    8 h' c5 N% X4 Y% C
  132.                         // 唤醒,清标志位
    ' r/ g% F7 p" X: g8 {
  133.                         isReadyToHalt = 0;
    / u7 |# T6 J5 v
  134.                         // 重开定时器0中断7 q# _, g) j5 @+ t: Z1 w  E
  135.                         ET0 = 1;0 B; ^1 Z  r+ U* [$ [; }
  136.                 }3 L& X, i' |% Y8 h- F- X
  137.         }
    ) P9 [7 K; x2 W
  138. }8 V$ q# G. g1 W
复制代码

, V6 h8 l/ b! u, A) [5 l硬件参数配置:- }' K5 d' |9 T% s2 O" W% t

6 T: O5 B2 A) F
7 K/ D' \" f* b5 @; @" G接收端:
7 V7 u( i( r9 ]2 N5 R
  1. #include <INTRINS.H>0 K$ I3 s  y* m9 K+ k
  2. #include "STC15W.h"9 @& }2 \; C1 u5 O/ q" T+ s7 @

  3.   L5 i! |# z8 P

  4. ' w/ s; m% @* V. B- r
  5. /*
    8 D9 X$ f! d8 T) E: d4 s
  6. 2 |* a: R. W3 |5 ?6 K
  7. *---------------------------*
    $ O4 ^/ {- u3 \' |+ ], t' T
  8. |1 (GPIO2)         \__/  (GPIO1)16|
    & D& u; w$ R8 c' N8 e1 C8 g' ?: e
  9. |                                                        |
    ) A- Q- V! F, r/ n
  10. |2 (GPIO3)                   (GPIO0)15|
    6 n7 L, K: D" ~4 u! R
  11. |                                                        |
    8 t2 ?( Q1 j+ q$ E+ M( A- n
  12. |3 (GPIO4)                                  14|+ h- ~0 J& H6 n2 A# Z$ n/ }2 u; X
  13. |                                                        |
    6 C. ^) l3 s4 i% @. k. {% N6 X
  14. |4 (GPIO5)                        (DATA)13|. Z2 C) B/ X$ `, q1 D) c
  15. |                  STC15W204S                |# r3 h- N/ M" a3 s
  16. |5 (GPIO6)                   (LATCH)12|7 k3 v; ?% Q4 [: }$ o* C
  17. |                                                        |% ^$ x2 R: e: U. m
  18. |6 (VCC)                         (CLK)11|+ g! W1 B% e2 |! B" k
  19. |                                                          |9 q8 o1 r3 z" z- L0 y
  20. |7 (GPIO7)                         (TXD)10|
    ; b" a4 M/ e  [3 ]1 j, q4 |& s: u
  21. |                                                        |
    1 ^8 k' e2 _5 W# c4 B+ Y$ H8 R8 L
  22. |8 (GND)                         (RXD) 9|
    % O( m4 ~- M+ o4 o$ C, ]
  23. *---------------------------*9 _. P8 u# l) I4 }1 Z( d
  24. Fosc = 12MHz
      L1 A) U8 G5 A- A7 w) G. b
  25. 0 i) `3 y: r' X- H9 j; U: c
  26. P1.0 -> 上
    , \( P9 S! U/ [. k/ x' d& E
  27. P1.1 -> 左( T& J' h7 Y8 \8 M" E# I
  28. P1.2 -> 下
    / k- |, R/ t0 d5 j' G! s& \
  29. P1.3 -> 右
    " S5 `7 @4 h- K8 u1 m5 O
  30. P1.4 -> SEL
    1 R: ]0 y. \" A0 D% D# `" l/ Y1 T
  31. P1.5 -> STA
    5 q) G1 q# y) Z( @, N! M0 d  e
  32. P5.4 -> B
    % H$ B- f* s" c
  33. P5.5 -> A
    / M  G! o$ C5 f2 E' V- r5 ?
  34. 9 R. H# w. j  \8 W' P/ s3 k
  35. *// F% T7 r8 G, t& T- }8 g4 P5 F
  36. 2 V+ v: _9 T5 z
  37.   \! F- D- E# y& z+ ]! h( Z+ b
  38. sbit CLK        = P3^2;5 M; E! F3 J: X' G. o
  39. sbit LATCH        = P3^3;
    / H1 Z. t0 _& \( v; H
  40. sbit DATA        = P3^6;
    / s) E6 c0 H& _9 u9 F# ^2 q
  41.   ~7 a, w+ X8 e1 [, V6 Y
  42. bit isReady = 0;2 L% ^- X# v3 n- V
  43. static unsigned char key = 0;. `5 F& j  q! }. y! Y
  44. static unsigned char buf = 0;        // 双缓冲。这个缓冲区保存从P1和P5组合而来的键值
    5 J1 V7 s5 J$ l: o: \6 J8 |
  45. static unsigned char bufReady = 0;        // 双缓冲。这个缓冲区保存上面那个缓冲区的备份' Q* W# ^6 R9 ]: w: Y0 ~( 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中
    & ]0 \* ~, ^- `
  47. static unsigned char idx = 0;/ n6 k( a  R0 J( W7 q1 g6 {) U

  48. 4 E4 l+ ?2 \  U# V
  49. 6 |! i7 U. w, H3 B, {  h
  50. static void GPIO_Init(){" |9 P9 M& {+ X$ W
  51.         // P1口和P5口用于接收并行信号,全部初始化为准双向,依靠内部弱上拉输出高电平
    - a+ D  T+ I7 W6 b( F
  52.         P1M0 = 0;/ A% f: f  c/ K
  53.         P1M1 = 0;  u2 v0 w3 V+ |) N6 Q
  54.         P1= 0xFF;% F! u' f5 u8 W1 [: T8 z
  55.         P5M0 = 0;
    : C+ C2 _0 N/ Q( H7 w5 j
  56.         P5M1 = 0;
    % N) z# w+ {, n, i2 e
  57.         P5= 0xFF;
    0 T7 J( l- {4 \" W! m5 H
  58.         // P3口初始化为准双向0 Q3 w3 W; k6 G8 ?
  59.         P3M0 = 0;
    8 w" s  l: l( H6 H
  60.         P3M1 = 0;" p' U* U! I3 M0 W' q0 l
  61.         P3 = 0xFF;* |: B7 n7 g0 ~2 S) P
  62. }
    2 G  T2 T& i4 c: f9 h  d# f
  63. , v- L( K1 C' ]$ |: V
  64. static void Interrupt_Init(){2 [! ?# |  E' R% Y
  65.         // INT0中断(CLK)触发类型为上升沿+下降沿% m. j5 a& D3 s# R2 S- I2 k: U1 v) ]
  66.         IT0 = 0;, M6 b9 i9 S" ^  N8 b; ~
  67.         // 允许INT0中断' a7 W5 c$ G8 D3 |" ^
  68.         EX0 = 1;. |0 J: Z7 A3 G3 [1 V+ _
  69.         // INT1中断(LATCH)触发类型为上升沿+下降沿
    ! Y& Y# m5 w9 o2 A
  70.         IT1 = 0;
    " I7 [  z# G1 x6 ]# M$ X7 K, ~
  71.         // 允许INT1中断9 z7 f: {7 A4 Z. x- l; A' f, O
  72.         EX1 = 1;) E9 @  b+ [+ N3 @6 [1 }5 j% x& y
  73.         // 开启全局中断0 v: l& _2 A; L7 `
  74.         EA = 1;- u; S0 p- e4 o2 ?( b. I- Z/ w
  75. }
    / x# y" m# D& H

  76. 2 f$ ]0 u* z' y& @2 ]% l/ N7 r
  77. static void INT0_Isr() interrupt 0{- e( S% R$ e0 r* I) j
  78.         // 只有已经成功锁存才允许CLK移位2 n' l: t: a7 T8 T% C. K7 h
  79.         if(isReady == 0)7 y+ A  o  t# }1 `
  80.                 return;3 s8 L( W. W- T  R( r+ f
  81.         // 读当前引脚电平,如果是低电平则说明是下降沿,此时直接忽略该中断
    : I7 a( L! ^% R7 y
  82.         if(CLK == 0)% ]% n2 F9 k# t" F, v
  83.                 return;
    , M4 X. Z5 H. P5 A2 j) _2 l
  84.         // CLK上升沿到来的时候,取锁存值的下一位输出
    5 K% b( \, R7 _3 l7 x$ t
  85.         idx++;
    . J  m1 l1 _( o3 S7 H
  86.         DATA = key & mask[idx];
    6 }  S& X0 P0 v+ Q' M
  87.         // 如果已经完成7次移位,则一轮读取完成
    : I& m; G- @5 I/ f) E
  88.         if(idx >= 7)4 q. c  s# C* p4 z& r' a% r! G
  89.                 isReady = 0;
    2 e8 a# U1 `9 i. l* G% w' @
  90. }
    1 B* \3 p% a. |& V& n' j6 H2 I

  91.   n0 e0 k; w; _( L
  92. static void INT1_Isr() interrupt 2{
    % Y* R8 A5 O: w8 B/ K9 S' |9 F
  93.         // 读当前引脚电平,如果是低电平则说明是下降沿,此时直接忽略该中断. g) I5 A' n  ~0 k4 K
  94.         if(LATCH == 0)0 d9 }2 K# C+ |. E2 d; W/ W
  95.                 return;
    $ L2 G9 {+ ?: y  Z% z. K
  96.         // 当LATCH上升沿到来的时候,锁存所有按键状态,同时把键值A输出到DATA# l  Z5 n' U# j& ~2 H# e& n% S
  97.         key = bufReady;
    ) K/ \" W3 D* U8 g
  98.         DATA = key & 0x80;//mask[0];        // 为了加速运算,直接取表中的值而不是读表
    3 i( J- j6 B8 w* b0 o8 y; W
  99.         idx = 0;
    4 z) k1 B8 o/ i% w' e: y$ D
  100.         // 允许CLK进行移位
    4 s  D0 U9 {2 [' e8 G9 P5 v
  101.         isReady = 1;7 ~/ g% i  j# l  y
  102. }# A% M3 j8 X. g& S0 e; u: F
  103. 3 U5 e4 p% y3 F5 `/ }
  104. void main(){, o+ ^5 J1 B2 q7 A; J4 n
  105.         GPIO_Init();: h0 R7 M$ i9 g! h( I9 z9 n
  106.         Interrupt_Init();3 U, k5 l. r# b) X+ j) M
  107.         5 q) `! L( m4 T  [
  108.         while(1){
    " o  r0 u( |$ g. Y5 S
  109.                 //PCON |= 0x01;        // 进入省电模式
    4 m" G; O9 X, H$ F
  110.                 //_nop_();5 M  T9 `; c" l* S- p; A
  111.                 //_nop_();: \" E9 b9 T' ]( R; d( H
  112.                 //_nop_();
    ( v! h7 \4 S6 ~  D
  113.                 //_nop_();
    ! b9 P4 @# R- T7 H: r9 P7 I6 R
  114.                 buf = ~((P1 & 0x3F) | ((P5 << 2) & 0xC0));  R5 b0 R- c, ]$ d* U, g
  115.                 bufReady = buf;
    5 m: w( W7 C9 G& Q# P! O
  116.         }, E- A4 }4 L+ O; I; W- d$ |* Z# O* I
  117. }
    + Q9 Q3 Y" N2 M
复制代码

. C- q+ x  X" M3 o7 [; \) @硬件参数配置无特殊要求,晶振频率选择12M即可。
/ d! O) ~  O0 c
  Y4 Y& ?) }7 ?9 |, x6 p这是编译好的固件。

本帖子中包含更多资源

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

×

评分

参与人数 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, r; a) @: q2 K4 b0 ?. _9 f
不错的设计,想问一下楼主,FC的15针公头怎么解决?普通的公头太短了,插不进去FC的扩展接口。 ...

7 `0 q) R! u9 X6 A1 y- ^* i坛友的改造方案
回复

使用道具 举报

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

使用道具 举报

发表于 2019-5-25 12:07:18 | 显示全部楼层
精彩,楼主动手强,也写得很详细。
' I9 B; l4 s9 L$ D/ }; o. ?- 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# N- z8 _9 O0 E
精彩,楼主动手强,也写得很详细。# ?1 |4 g: W/ f# D2 x
2.4G方案是目前无线的最低延迟吗?
2 D, w* \# _  L8 V6 H  Q
我没用过其他无线手柄,所以实在不知道我自己做的这个手柄到底是不是最低延迟。1 o  V& U5 R; f
不过根据网上的说法,延迟高低主要是由通信协议的复杂程度,以及数据传输速率决定的。这个模块虽然是2.4G无线模块,但由于协议很简单,所以延迟比较低。
3 ^8 g% ~2 _4 z3 l3 {: A5 Q9 i' F我用这个手柄玩一些ACT游戏,比如超级马里奥、忍者龙剑传、热血系列,完全感觉不到延迟,和游戏机自带的手柄没有任何区别。唯一的区别就是这个手柄是用火花山寨手柄改造的,外壳是垃圾回收塑料,粗糙+脆弱,导电橡胶弹性不佳,手感不是一般的差。
; N% L6 g- V$ P我手里还有十几张板子,等我有空了我再做一套,到时候买一个好一点的手柄改造。
回复

使用道具 举报

 楼主| 发表于 2019-5-29 16:56:14 | 显示全部楼层
ppad 发表于 2019-5-28 17:27$ G" P6 n+ v& ]" I* w4 F, y8 J) _7 g
给技术帝赞一个,有半成品发布吗,自己焊接改造就可以,编程实在不会啊 ...
$ \1 ~* t4 @! l  s/ |
很可惜,我手里没有多余的单片机了,LDO也找不到了,锂电池以及充电模块更是没有了。反正就是该用到的元件基本都没了,所以没法发布半成品。
: Z* M7 k# l( E  V两个板子倒是有十几张剩余。
, g1 [1 W, M, S( h: l2 x" F$ J你要是有USB转TTL串口板,完全可以自己买这两种单片机,然后我给你编译好的固件,你自己用串口板下载到单片机里面就行了。两个2.4G无线模块也得通过串口板用AT命令设置参数,不过好在我在设计电路的时候就已经预留好了串口,可以直接在线下载和在线设置参数。总的来说并不麻烦。
回复

使用道具 举报

 楼主| 发表于 2019-5-29 17:00:34 | 显示全部楼层
孙大师 发表于 2019-5-28 18:55
0 b) f9 o! S1 L4 O+ J: K$ `- c* k非常好,楼主是技术帝,到目前我都还没开发fc的无线套件,等空了,开发一套套件,等玩家自己组装。 ...

9 U$ e) K7 x3 F: T1 |( R$ a能得到孙大师的赞誉,不胜荣幸!  b2 x/ l- W! X
不如开发一个多功能手柄,比如用SFC手柄改造,L/R键配合其他组合键可以用来切换2P~4P、调节连发速度、软重启等各种功能。接收端插到15PIN扩展口。
回复

使用道具 举报

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

本版积分规则

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

GMT+8, 2026-7-22 15:01 , Processed in 0.642028 second(s), 14 queries .

Powered by Discuz! X3.5

© 2001-2025 Discuz! Team.

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