找回密码
 注册

QQ登录

只需一步,快速开始

查看: 24228|回复: 29

自制FC无线手柄

  [复制链接]
发表于 2019-5-22 14:16:45 | 显示全部楼层 |阅读模式
本帖最后由 雷精灵2046 于 2019-6-14 09:28 编辑 : W: w) {5 x# o9 ]( l
1 d, f0 l8 ?1 Q, l4 c; d- t3 M
没有用复杂的分立元件搭建发射接收电路,直接用的现成的2.4G无线模块jdy-40。
5 N8 b  I$ I/ O! x, p( M  G) [, Y( a  R2 f
4 W: o# R  R0 \  j! i, g
发射端靠3.7V锂电池供电,用了一片SOP8封装的STC单片机,负责产生连发脉冲,同时负责检测电池电量,电压低于3V左右的时候触发低压中断,低压指示LED就会亮起来告知该充电了。平时发射模块和单片机均处于睡眠状态,有按键按下才会唤醒,从而实现省电。实测睡眠状态下整机电流约1~2uA。板子洗了一下稍微干净了一点。因为对于微功耗设备来说,焊接残余的助焊剂可能会增加漏电流。
2 a& r1 y  d! g# p* {
2 |- _& `6 K; }5 J) @买了一个火花的FC山寨手柄,去掉里面的牛屎板子,并修正一下塑料挡板,把锂电池和充电模块装进去。; g7 M  _! M7 |4 ?" L$ e3 C
为了减少体积,充电模块裁剪得十分小,并且更换了充电电阻使之适应这个小小的锂电池。这么小容量的电池,也不需要多么大的充电电流是吧?
0 c$ t$ r' |! [' X3 c然后统统用热熔胶粘上。充电电流比较小,所以发热很少,不会熔化热熔胶。
, K4 Q5 M6 V6 j  x# d1 E0 O2 N/ l  z* p- B8 v0 b
3 \0 Q( K! P5 p4 ^# v; y
: {3 d2 w% i0 S
最后把按键、导电橡胶和电路板装上去。
  k9 F, e% d4 E6 |' t, [精心裁剪了电路板,正好扣上,不会阻碍其他元件,也不会影响后盖和拧螺丝。
& I# y# N9 `" N2 Q+ o$ H
4 l  U; I( S* J0 u4 W' P! J0 @( l$ P% v! _. ?/ i3 n8 \
完工!1 l* l" ^% D/ s  j2 f

; V  V6 H$ I4 Z/ E6 \& e0 G
1 g' e) L6 P' B( o$ H这是充电的MicroUSB插座。旁边的小孔用于透出低压报警LED的光线。
1 o- H' P- p3 i0 n- P9 I- d
7 v( }4 E) b  [) G$ V# a. u5 S& i4 z6 y4 e, p2 |: J' I
接收端用一片DIP16封装的STC单片机模拟CD4021。为啥要用单片机模拟而不是直接用CD4021?因为jdy-40模块接收端在有按键按下的时候输出高电平,无按键按下输出低电平,和普通手柄正好相反。当然我也可以用两片74HC00或者74HC04之类的逻辑门进行反相,但那就增加了芯片的数量。对于FC手柄这种工作频率并不高的设备来说,STC单片机完全可以胜任模拟工作。5 I& W% c& `& O% c. S1 T2 p! o" Z& A

4 m/ u. }6 c9 \1 m2 s7 \
& M# S; k% h3 f
, {5 C) i, ^- h& o电路设计有点小小的错误,所以有几根飞线。原本设计使用低压差LDO是XC6206,结果在做这个接收模块的时候,买的LDO居然找不到了!无奈只好用了AMS1117。幸好对于接收模块来说是5V降到3.3V,1117可以胜任。要是发射端手柄的话,3.7V降到3.3V,那就非得用6206不可了。
: k1 \0 Q3 R( z
0 Y) C# f  O8 j! k实测十分灵敏,延迟极小几乎感觉不出来。可惜这山寨手柄的手感并不佳,尤其是方向键,软塌塌的。看来我得买个剪线手柄改装。3 d% u9 Y3 V; h9 K( e/ A8 \) r
7 |3 M0 A5 z8 o
这是电路图,有兴趣的朋友可以参考。+ l1 \+ [! u$ A0 v& J# L
. v* v( O2 D( ~" c+ X
$ ?# n4 Y: @  D& K/ `. v
我信奉开源主义,十分痛恨把技术藏着掖着。好东西大家分享嘛!所以两个单片机的源代码大公开!9 g3 Q' M0 z, {7 O- f: ?
编译器:Keil 51。
( f* }. s! r5 ?
. e) d: u1 O4 x$ t3 q发射端:
3 ~, M4 ]4 [+ f2 r! K" o
  1. #include <INTRINS.H>+ v6 b7 a$ u; R6 K% n+ B
  2. #include "STC15W.h"
    7 p0 l: s7 i& R/ m8 e) a; @

  3. , M/ z6 S' ~& O1 z

  4. 6 e1 Q4 a9 ]5 v8 M8 w) s
  5. /*
    # |9 N- c; h) Y9 b; j! I; v
  6. --------------------------
    4 m/ y* @2 u# W2 q7 W
  7. |1 (OUT)        \__/   (INT1) 8|" R9 e7 H% n' l) [$ O  ?
  8. |                                                   |
    $ X$ _0 {- {: U! S
  9. |2 (VCC)                   (INT0) 7|
    5 O$ P$ J/ u6 Z( o2 Y) Z/ d
  10. |                 STC15W204S                   |
      ^/ y  c- C1 ]% ]: `9 X7 h
  11. |3 (LED)                         (TXD) 6|
    6 G$ l2 T3 @* c' X
  12. |                                                   |% F$ m4 z% {% r7 ~
  13. |4 (GND)                         (RXD) 5|
    . [( A  I! K2 |; x% I5 Y
  14. --------------------------
    . y, W+ Q+ q/ d* X

  15. 8 W9 X  e$ K+ A9 r# j
  16. LED ---|<|---[===]--- VCC
    , D# j' e/ q: y9 w: d' s
  17.            Red          330( e8 [) }* F' I

  18. " H- }3 W- J# [) g# j* T& f
  19. Fosc = 6MHz
    3 g: W8 |# g0 t" v; G
  20. */
    7 T0 U0 N1 n' p( o' z
  21. : z  P3 I" b- _) S
  22. : h- D# e" W( V8 f. R5 j4 T, v1 E( ^
  23. // 矩形波输出脚
    / B# c  `% f1 G- z6 }
  24. sbit OUT = P5^4;. x% F* ]" F0 u6 T) e  H" v( i
  25. // 低压指示灯引脚# b. p5 c8 _$ [  y. Y; \( W! L' A
  26. sbit LED = P5^5;  |; G7 T& V7 E7 S

  27. 3 B! M: I3 h1 ?8 O6 o: K8 {2 Y
  28. // 停机标志位
    $ r5 x8 ]5 P8 z) K* v3 y% v  h) n
  29. bit isReadyToHalt = 0;2 V; M" p. t0 B8 |
  30. " G) m+ i2 V9 O3 y% c6 I( v8 u
  31. // 矩形波次数累计
    ; L$ ~5 ?/ W! [7 ~2 C+ Q
  32. static volatile unsigned char count = 0;4 Z9 ^( s$ ^4 H( H

  33. 5 ?& v+ N, L9 U2 k" m7 \9 |

  34. , N7 ^: B- A" w% N8 y% Q$ v2 C( J. _3 {
  35. static void GPIO_Init(){
    % v) h( H8 o0 u3 ~% ~  Q  |
  36.         // P3口设置为准双向,默认靠内部弱上拉输出高电平
    8 y, Q$ @, Q: F. g, P$ I
  37.         P3M0 = 0;: K# Q- ~& V9 b+ M% C
  38.         P3M1 = 0;
    , g- T3 M) D3 U
  39.         P3 = 0xFF;
    9 \% E4 [( t% p
  40.         // P5口设置为准双向,默认靠内部弱上拉输出高电平+ Z1 t* @  z) Y2 d8 f- c, J( [
  41.         P5M0 = 0;( {6 y4 Z5 ?  F8 r# v* D# p% R
  42.         P5M1 = 0;
    2 M' ~6 E& d# t1 y
  43.         P5 = 0xFF;! U1 D+ G! e5 ^( J1 i2 d1 T
  44. }/ n+ @. T5 f! i% G5 R
  45. / C* D! g8 O% q# y% J, {
  46. static void Timer0_Init(){
    " m; R" a0 I" Z& |5 Z
  47.         // 16毫秒@6.000MHz7 p# J$ `' h7 j' R- D* e5 L
  48.         AUXR &= 0x7F;        // 定时器时钟12T模式
    4 Q* p+ ?& n0 k2 _
  49.         TMOD &= 0xF0;        // 设置定时器模式
    . i" @; J. W( E
  50.         TL0 = 0xC0;                // 设置定时初值* d. b0 ^4 `9 N7 d1 A  r2 S7 M1 f
  51.         TH0 = 0xE0;                // 设置定时初值/ q- V" M4 M( I. x4 T0 k- a
  52.         TF0 = 0;                // 清除TF0标志6 R; {9 t; M$ C: J4 ^1 K
  53.         TR0 = 1;                // 定时器0开始计时# n' A" r* f) D. F! K
  54. }
    1 a: H/ S0 E7 x1 E) P

  55. 5 U4 S/ L! ]; e9 s( D! K
  56. static void Interrupt_Init(){1 y% O; M1 M) ^. r2 i. I
  57.         // INT0中断触发类型为下降沿触发; H6 p/ y% ]% A* _0 u. n
  58.         IT0 = 1;! ]2 Q8 A. K: _
  59.         // 允许INT0中断
    1 i1 S- i2 ?# V1 u- u5 N" j) c
  60.         EX0 = 1;' ?( e0 o& r) I9 K
  61.         // INT1中断触发类型为下降沿触发
    / {; E* E  R- Q" h) l9 w2 y8 h
  62.         IT1 = 1;/ {/ Z6 N. u) I, h4 M  N7 _% I
  63.         // 允许INT1中断  Q8 [5 Y: R' R# ~- Z$ L6 K
  64.         EX1 = 1;
    ' b6 b' _) c  r! q7 y( m& Q: Q1 Y
  65.         // 允许定时器0中断
    ( B( L' n1 ], m) }* Q
  66.         ET0 = 1;
    " v3 a7 K9 E) r- Q7 P8 z
  67.         // 允许全局中断9 d7 Q& t, m, ^3 X% N6 M
  68.         EA = 1;3 J( m9 s. |, y/ u5 ^6 L$ n
  69. }3 |$ Y1 i- G" P7 q
  70. $ l$ X% \) B( D" m* }5 N/ o
  71. static void INT0_Isr() interrupt 0{
    , L) t5 l) k7 Y2 ~7 v# I  s8 g! S
  72.         // 矩形波次数累计归零! z" \# z! \' L& V
  73.         count = 0;
    / [4 b; B! R1 E7 l1 P1 E  R$ k
  74.         // 重开定时器0中断5 T5 I1 e! ?  g
  75.         ET0 = 1;' h1 y& O! s# I: \. R
  76. }' |5 ^/ d/ S, B0 ~* K

  77. ( _  K1 d6 d0 g
  78. static void Timer0_Isr() interrupt 1{
    " A3 k0 B# k) ^* w* l
  79.         // 输出矩形波
    2 [, W6 t/ \2 T9 e! Q5 V
  80.         OUT = ~OUT;- a6 A) Q$ F* o+ F& g4 u8 H: x  O
  81.         // 累计矩形波次数6 W8 H, p5 `) S8 L( V4 [. G
  82.         count++;
    # w, r1 M3 k0 j9 }7 ~. v0 ]
  83.         // 超过250个矩形波,准备停机# ~3 y9 e: K& z. a. l
  84.         if(count > 250){5 Y  H5 I8 m4 S
  85.                 count = 0;
    5 F4 `' t: M5 `: K/ u, a5 J7 J
  86.                 isReadyToHalt = 1;
    ) b! d- e/ b; {" v
  87.         }
    , u2 T* m7 R8 @% I. N
  88. }
    & K3 m5 C& E' E4 m
  89. 9 }8 {# M- H1 S' j5 q# [7 l: |
  90. static void INT1_Isr() interrupt 2{  [% s6 t& J# g- ~
  91.         // 矩形波次数累计归零
    . r6 X& i$ A" O! V8 Y% U
  92.         count = 0;
    ( x+ ?0 |3 D8 e' g* m! z0 `
  93.         // 重开定时器0中断
    2 y: _  I7 k4 J4 D
  94.         ET0 = 1;* [% E- Y" b0 S6 E  ]6 y& W
  95. }% @% k7 i9 @' J1 X

  96. $ U' ~, K) n2 A; G+ p" Y
  97. 4 `8 d( e( k; j' V
  98. void main(){7 p, O& b& H: X4 I# n$ ^
  99.         // 初始化P3和P5口
    8 g" `' b( T- p4 B5 Y9 q7 x
  100.         GPIO_Init();% ]$ q8 Z. K; S9 }2 X6 L
  101.         // 初始化定时器0
    $ \0 ^6 X- v/ N0 Z- d( B: d, t* j
  102.         Timer0_Init();
    3 C1 J) n" o8 T, i' S4 k6 h
  103.         // 初始化中断) Y" J2 {/ E5 @: V# r$ J
  104.         Interrupt_Init();  @6 T. m5 F' [0 G
  105.         * Q, d9 s3 t( M$ W8 `4 C/ S
  106.         while(1){1 U: T' g4 N% M) Z& w3 G) b( K
  107.                 // 检测电量& s0 z9 h4 \$ f5 r# [
  108.                 if(PCON & (1 << 5)){) ^& r0 a( N& I1 E
  109.                         // 如果电量低,低压指示灯亮2 E  e+ I' S4 a; q' [" G' M6 C
  110.                         LED = 0;
    4 c- ]' W, [. l- F" C2 X) O
  111.                         // 清电量检测硬件标志位
    * Z! B# f6 H3 V. S
  112.                         PCON &= ~(1 << 5);& `* B5 f/ ?, z- n. }7 B6 b2 z4 l" k
  113.                 }else{
    6 P" b3 s* C4 L1 N
  114.                         // 电量正常,低压指示灯灭5 b- d+ Q- O* H" j
  115.                         LED = 1;
    1 K4 s) u, L- Z
  116.                 }; N6 I! T* Z/ E  V. ]9 r- S
  117. ' l4 U" \) X+ x7 X1 P
  118.                 // 检测到停机标志6 E4 A$ M3 ]' ~6 ^: N( L
  119.                 if(isReadyToHalt == 1){
    ) f( w+ @% Y% E7 t
  120.                         // 暂时关闭定时器0中断
    1 |3 C) ^* U' z9 q
  121.                         ET0 = 0;
    : @4 f$ L% a& U
  122.                         // 停机之前先把矩形波输出脚置低电平,以方便INT0和INT1唤醒CPU% N# b2 q7 L9 h0 f0 e. q
  123.                         OUT = 0;
    , ~7 N4 T; j4 G! S- n
  124.                         // 停机之前先把低压指示灯灭掉,以省电5 `; B8 ]+ r) |
  125.                         LED = 1;) _9 H5 v$ I3 f+ [, z: U( o+ D! d( s
  126.                         // 进入停机模式
    ; U' Q6 q( i4 C
  127.                         PCON |= 0x02;! n) V! ^/ ^2 o' H2 v  T% K2 J
  128.                         _nop_();
    " V! R9 X' k; x, r2 A( j
  129.                         _nop_();6 S& t, R$ M5 a
  130.                         _nop_();
    # j6 a4 S. u1 \, q2 f. I( @
  131.                         _nop_();
    2 z. o7 L4 F& \. u: r! R1 {8 H
  132.                         // 唤醒,清标志位' ~( N; f- L5 Y
  133.                         isReadyToHalt = 0;7 h! `6 V* p1 r+ H) X% ^$ Z
  134.                         // 重开定时器0中断- L9 i5 j7 x, h
  135.                         ET0 = 1;
    9 {9 r/ k0 ?9 A* I* l
  136.                 }
    9 D# }! W5 \1 }% _0 s
  137.         }) g0 `* q8 W3 T* ?' `1 ^$ o$ }
  138. }' i. T8 n8 k3 y, U8 h
复制代码

' S9 a- ?- J5 T% D: a$ w5 B硬件参数配置:* b" r4 ]' v" u

3 p/ E( d! b% P# ^" E; o2 S: R
0 u, S! d$ y5 X3 k接收端:
; u$ f/ w+ r2 v" Y$ N! u) |4 j
  1. #include <INTRINS.H>" Q9 o" I& r0 Q! J& o
  2. #include "STC15W.h"' w* a" K$ T! X" r- m7 w5 `
  3. / A1 B; Z9 l3 z6 X# T

  4. : @. [2 x+ E# J
  5. /*, Z, T# `6 ^1 S2 K

  6. 8 P  h7 y! o1 s6 n5 a
  7. *---------------------------*1 S0 `7 `" x# h4 J5 _
  8. |1 (GPIO2)         \__/  (GPIO1)16|
    ) h- `4 q: a( m( U3 ?
  9. |                                                        |
    ( l* ~( T# L' Q
  10. |2 (GPIO3)                   (GPIO0)15|
    + Y* k8 u) P2 I/ @
  11. |                                                        |( R2 N) A5 J* J
  12. |3 (GPIO4)                                  14|
    , N; e% A" ~* K  U2 d9 o
  13. |                                                        |
    % I4 S7 _( T7 v( x
  14. |4 (GPIO5)                        (DATA)13|' Q1 s' M& G/ `% ^
  15. |                  STC15W204S                |
    1 C2 Z( [9 b6 v8 I6 J' x: P" P
  16. |5 (GPIO6)                   (LATCH)12|
    ! `; R( Y! k& S7 N
  17. |                                                        |
    ( C% x0 `7 q% t0 \0 }
  18. |6 (VCC)                         (CLK)11|% _) l$ D8 _6 m* D& S* t# }9 d" w
  19. |                                                          |
    ! x# b) B2 E2 t$ Q9 x+ G+ i
  20. |7 (GPIO7)                         (TXD)10|
    6 w/ c; {; P' H) j9 i4 ^
  21. |                                                        |
    & x, ~# m' {; e. n2 X9 |0 b
  22. |8 (GND)                         (RXD) 9|
    ! ]9 r; d* c" s
  23. *---------------------------*, K) Z( y( ~  A* i/ l- B6 ~
  24. Fosc = 12MHz' f' q/ a( m$ d
  25. ; _& W5 o, ^( C. }1 p- V0 z; r/ T
  26. P1.0 -> 上
    % x, U! S+ d. N' F) K
  27. P1.1 -> 左' \% M" T0 ~  U) C) S# p, v5 l
  28. P1.2 -> 下
    5 {, X! A3 {) A* O5 F- G; T& I+ x
  29. P1.3 -> 右. S+ S/ V# E2 E3 S. f9 P$ q8 U
  30. P1.4 -> SEL
    7 J# K" k! {# |0 a4 h
  31. P1.5 -> STA$ g  i/ ~( L6 K( z: c: o
  32. P5.4 -> B
    3 V3 s) _) A) ^5 X, `
  33. P5.5 -> A- P! x. |, z4 B& B/ ^8 K0 r

  34. % h: w6 P5 m) s9 L( Q4 x
  35. */) {% p+ N* Y6 K; z' y4 {& I
  36. " U/ f" o* X# d! h$ T

  37. + y5 Z6 e4 Y5 N/ C4 Q2 [# r
  38. sbit CLK        = P3^2;
    ) ~( d; m! `& A+ y5 S( a8 H
  39. sbit LATCH        = P3^3;
    6 R# i' q4 s1 R3 G
  40. sbit DATA        = P3^6;
    2 q. T3 u) I4 r4 Z5 W- U5 v

  41. . I3 U  o' J+ k; b8 s! ~
  42. bit isReady = 0;. M- N8 i4 Y( x6 {+ T% _- I
  43. static unsigned char key = 0;
    & g1 v* L+ N% E" ~9 |, E- B
  44. static unsigned char buf = 0;        // 双缓冲。这个缓冲区保存从P1和P5组合而来的键值
    3 R/ h7 X* J: w0 @5 Q- ?" x
  45. static unsigned char bufReady = 0;        // 双缓冲。这个缓冲区保存上面那个缓冲区的备份
      ]$ _/ b9 ~6 `
  46. static const unsigned char data mask[] = {0x80, 0x40, 0x10, 0x20, 0x01, 0x04, 0x02, 0x08};        // A B SELECT START UP DOWN LEFT RIGHT。为提升速度,这个表放到RAM中! [+ i5 [0 @+ m4 d' a6 W; X
  47. static unsigned char idx = 0;6 F% Z: z& c, v

  48. 5 g: {* t0 r: G% p: Z

  49. 9 {2 I* Y) X" j1 N8 p- M. S2 S
  50. static void GPIO_Init(){9 U8 ^& n! N6 a5 c; y1 \
  51.         // P1口和P5口用于接收并行信号,全部初始化为准双向,依靠内部弱上拉输出高电平
    " ]8 P# y" P: z
  52.         P1M0 = 0;' Y6 o) \) z9 l8 a( `! R. S% s
  53.         P1M1 = 0;
    8 E3 |; ~" p* i3 T
  54.         P1= 0xFF;1 V# ^% l7 l( d% L6 ?9 G0 S
  55.         P5M0 = 0;
    ! d( v/ V  h1 g# r* @
  56.         P5M1 = 0;
    , i8 ?5 D) l3 j) _; _0 w/ D
  57.         P5= 0xFF;
    + J3 z, g3 W+ x% n4 s
  58.         // P3口初始化为准双向
    7 I$ w& {7 v4 y
  59.         P3M0 = 0;- a0 L. S# o2 C& b
  60.         P3M1 = 0;# V7 K. C6 ]. ~, Z6 I4 z
  61.         P3 = 0xFF;
    4 J9 y4 i/ W- f! }% v
  62. }; Z+ T, G# J* G* k2 B& o
  63. + I  I' h- p7 I* h0 U2 W
  64. static void Interrupt_Init(){
    ' F% M8 G( |3 C; Z, R% e' o, b
  65.         // INT0中断(CLK)触发类型为上升沿+下降沿
    / n# M3 |7 j! c/ I0 x2 d) u
  66.         IT0 = 0;
    # r- j4 z  _  b; y
  67.         // 允许INT0中断7 F& s3 e% D7 F" t5 D$ Y& w
  68.         EX0 = 1;/ T( W* Y9 j& {9 A/ r4 y
  69.         // INT1中断(LATCH)触发类型为上升沿+下降沿
    : K2 P2 h! ], L
  70.         IT1 = 0;) ^$ U8 M; Z: G
  71.         // 允许INT1中断
    0 g. d; h! _5 r$ t& a1 A/ o! _$ G
  72.         EX1 = 1;
    ! |$ g) c$ B6 d. X6 c) ]1 e
  73.         // 开启全局中断# `2 g6 F4 v* o3 H1 F
  74.         EA = 1;
    # D4 e8 ~9 ]) a! c7 Y9 m' u
  75. }
    $ V& e; k) |9 e: q1 q& g

  76. 0 u0 a( ]7 q; S0 ?3 r
  77. static void INT0_Isr() interrupt 0{% s& J7 x  @6 [( L
  78.         // 只有已经成功锁存才允许CLK移位
    ' o! p, k- v: P7 o- l0 R  m4 Q
  79.         if(isReady == 0)
    0 N5 {. M6 p- Y" z
  80.                 return;8 S& @/ P1 S1 c9 R/ j2 U. J) S
  81.         // 读当前引脚电平,如果是低电平则说明是下降沿,此时直接忽略该中断2 J( |$ L- o! Z& a  u5 U" v1 N& e- X
  82.         if(CLK == 0)6 G- P0 |& q1 z' [! Z  T) V
  83.                 return;1 ~0 O5 r2 N# k+ ~+ ~- i
  84.         // CLK上升沿到来的时候,取锁存值的下一位输出
      Q7 ?# n6 S- V; W
  85.         idx++;' B4 I# J6 r. p: ^8 O5 T. d
  86.         DATA = key & mask[idx];
    7 o/ A  L1 }; v8 v; e5 f2 \$ [& `8 A
  87.         // 如果已经完成7次移位,则一轮读取完成
    ' F" D* v' b) c
  88.         if(idx >= 7)
    8 ?9 q$ X# q8 V9 @
  89.                 isReady = 0;
    : c4 G: l8 E4 ?9 ?2 V( K9 p% m6 @
  90. }7 q  F5 P% J3 h( H6 b$ D

  91. $ O1 V/ D( B1 q: s8 B0 y% V5 K* u$ d
  92. static void INT1_Isr() interrupt 2{
    . D8 S9 e& I( D' U. Z# J$ Y0 o) [2 I* b
  93.         // 读当前引脚电平,如果是低电平则说明是下降沿,此时直接忽略该中断) ?1 _7 S& Q/ [- a
  94.         if(LATCH == 0), t, B6 U2 k" Z; G1 j# M" E+ {" z+ }4 h
  95.                 return;
    0 |7 t9 T) j- i# n# S) o
  96.         // 当LATCH上升沿到来的时候,锁存所有按键状态,同时把键值A输出到DATA! H$ H) x, Z7 R6 N; g/ [2 C
  97.         key = bufReady;9 |9 y% a" y- v. O% P- n
  98.         DATA = key & 0x80;//mask[0];        // 为了加速运算,直接取表中的值而不是读表
    " i% m9 {( Q7 D# |1 i' D
  99.         idx = 0;
      ?0 @) w! }( X6 M8 O/ `: h" i
  100.         // 允许CLK进行移位2 l1 f+ r9 x$ Q3 j8 \: x
  101.         isReady = 1;, o2 e  S! `% ~* C4 D
  102. }
    % W) @  S6 t1 U% V* b
  103. 0 ^& ~  ]7 V8 {8 G  ]
  104. void main(){
      {6 g: `7 x$ f
  105.         GPIO_Init();
    : ?. z+ {" W7 q. f, q3 A
  106.         Interrupt_Init();
    " y& v! P! w: U* d# H
  107.         9 l6 m$ \$ |! ]+ w+ N) x% ^
  108.         while(1){& U# h! k7 Z: J. z# T* f
  109.                 //PCON |= 0x01;        // 进入省电模式7 t" |& O/ A* O8 H8 F1 t$ `
  110.                 //_nop_();& ~" N& h1 K" H5 i# Y6 m9 g
  111.                 //_nop_();
    % e& L2 q* d" S! I
  112.                 //_nop_();
    / C- |" _# ?. h) J3 ]" T
  113.                 //_nop_();
    - U( g( r4 X# |" P$ ]
  114.                 buf = ~((P1 & 0x3F) | ((P5 << 2) & 0xC0));
      E0 R: @3 o+ l; j' w
  115.                 bufReady = buf;
      R0 M& Y8 r3 S8 {# ?6 o! z
  116.         }, S# f% l/ l1 w/ |0 r6 |- [
  117. }4 }) {; Z* q% U6 j" d
复制代码

3 Y7 q% C) E5 b% C$ y硬件参数配置无特殊要求,晶振频率选择12M即可。
/ [/ B6 p9 Y2 J: Q' o) X
9 _- P" ~3 F9 \5 F5 m* ~# R: Z  \+ |这是编译好的固件。

本帖子中包含更多资源

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

×

评分

参与人数 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
& d) o$ R) A4 o) [" Q- L- ~) h不错的设计,想问一下楼主,FC的15针公头怎么解决?普通的公头太短了,插不进去FC的扩展接口。 ...
, I# F  \$ k  Q
坛友的改造方案
回复

使用道具 举报

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

使用道具 举报

发表于 2019-5-25 12:07:18 | 显示全部楼层
精彩,楼主动手强,也写得很详细。
1 i5 u) h2 h1 R' y5 q/ M. w4 d9 }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  d) u8 W/ `( L
精彩,楼主动手强,也写得很详细。% G0 a7 ~  N, u9 J, ^. U
2.4G方案是目前无线的最低延迟吗?

* L, Z7 k* F5 L; A4 E, u! X我没用过其他无线手柄,所以实在不知道我自己做的这个手柄到底是不是最低延迟。
  T6 i0 d3 q- R0 _不过根据网上的说法,延迟高低主要是由通信协议的复杂程度,以及数据传输速率决定的。这个模块虽然是2.4G无线模块,但由于协议很简单,所以延迟比较低。, j' \( w. o* `' E6 \& b
我用这个手柄玩一些ACT游戏,比如超级马里奥、忍者龙剑传、热血系列,完全感觉不到延迟,和游戏机自带的手柄没有任何区别。唯一的区别就是这个手柄是用火花山寨手柄改造的,外壳是垃圾回收塑料,粗糙+脆弱,导电橡胶弹性不佳,手感不是一般的差。( {/ y' L; c. o  C1 X
我手里还有十几张板子,等我有空了我再做一套,到时候买一个好一点的手柄改造。
回复

使用道具 举报

 楼主| 发表于 2019-5-29 16:56:14 | 显示全部楼层
ppad 发表于 2019-5-28 17:277 `3 Y9 v/ Z# O" i' h4 A
给技术帝赞一个,有半成品发布吗,自己焊接改造就可以,编程实在不会啊 ...
% p% u$ T. f$ U; a. |
很可惜,我手里没有多余的单片机了,LDO也找不到了,锂电池以及充电模块更是没有了。反正就是该用到的元件基本都没了,所以没法发布半成品。# X% d7 O3 u2 f& ^, p
两个板子倒是有十几张剩余。6 p) u4 D, n; N8 Q) ~
你要是有USB转TTL串口板,完全可以自己买这两种单片机,然后我给你编译好的固件,你自己用串口板下载到单片机里面就行了。两个2.4G无线模块也得通过串口板用AT命令设置参数,不过好在我在设计电路的时候就已经预留好了串口,可以直接在线下载和在线设置参数。总的来说并不麻烦。
回复

使用道具 举报

 楼主| 发表于 2019-5-29 17:00:34 | 显示全部楼层
孙大师 发表于 2019-5-28 18:55: P: w. C; E7 Z2 s4 Y
非常好,楼主是技术帝,到目前我都还没开发fc的无线套件,等空了,开发一套套件,等玩家自己组装。 ...
2 P. `1 z, l  R2 Y
能得到孙大师的赞誉,不胜荣幸!2 i' y: D; d2 l7 U8 m$ h
不如开发一个多功能手柄,比如用SFC手柄改造,L/R键配合其他组合键可以用来切换2P~4P、调节连发速度、软重启等各种功能。接收端插到15PIN扩展口。
回复

使用道具 举报

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

本版积分规则

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

GMT+8, 2026-3-22 14:29 , Processed in 0.114549 second(s), 15 queries .

Powered by Discuz! X3.5

© 2001-2025 Discuz! Team.

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