找回密码
 注册

QQ登录

只需一步,快速开始

查看: 24896|回复: 32

自制FC无线手柄

  [复制链接]
发表于 2019-5-22 14:16:45 | 显示全部楼层 |阅读模式
本帖最后由 雷精灵2046 于 2019-6-14 09:28 编辑 ) l2 M+ ^( X3 g) K' X/ @4 g/ ^0 V
2 N* Z. R4 s: L8 ?6 ^3 R/ Z
没有用复杂的分立元件搭建发射接收电路,直接用的现成的2.4G无线模块jdy-40。
5 r) U! R# H# n! L0 T6 `( j# q5 i; ~) @

/ d5 j4 G& ~2 W发射端靠3.7V锂电池供电,用了一片SOP8封装的STC单片机,负责产生连发脉冲,同时负责检测电池电量,电压低于3V左右的时候触发低压中断,低压指示LED就会亮起来告知该充电了。平时发射模块和单片机均处于睡眠状态,有按键按下才会唤醒,从而实现省电。实测睡眠状态下整机电流约1~2uA。板子洗了一下稍微干净了一点。因为对于微功耗设备来说,焊接残余的助焊剂可能会增加漏电流。2 M1 q) U4 m$ I$ j3 g
9 l: n9 _- k5 b  b+ T, B& z; q
买了一个火花的FC山寨手柄,去掉里面的牛屎板子,并修正一下塑料挡板,把锂电池和充电模块装进去。
/ @& x. Q- d& _6 N7 n为了减少体积,充电模块裁剪得十分小,并且更换了充电电阻使之适应这个小小的锂电池。这么小容量的电池,也不需要多么大的充电电流是吧?
% q0 E/ y; {6 t% d* e6 y然后统统用热熔胶粘上。充电电流比较小,所以发热很少,不会熔化热熔胶。
( e4 e5 \0 P* E. n0 Y: K" V4 V; s7 R, q; N$ l; O" r* a2 K
/ [! _. e$ v$ ~& L+ L! ~$ y
, v! L+ i* V8 a. p, m
最后把按键、导电橡胶和电路板装上去。
. C3 l1 `5 x/ ]2 b! t精心裁剪了电路板,正好扣上,不会阻碍其他元件,也不会影响后盖和拧螺丝。. t4 @$ H1 w: X) b7 f" Y! h
6 v6 `! L& u. f- [

  M& c% l& \  c- k$ N0 H1 W完工!. V3 g* z+ R' C4 s! k! g
0 i6 g0 T0 _/ Z9 Y7 d$ b# q/ v

4 w% U# l9 }: u这是充电的MicroUSB插座。旁边的小孔用于透出低压报警LED的光线。
, _  t. s8 Y" `( K' a! {1 p  l3 Q- }
/ h; Y) |8 K1 R( ^# O2 y
8 D3 S4 ^2 z  r4 ]2 }$ f( N- f接收端用一片DIP16封装的STC单片机模拟CD4021。为啥要用单片机模拟而不是直接用CD4021?因为jdy-40模块接收端在有按键按下的时候输出高电平,无按键按下输出低电平,和普通手柄正好相反。当然我也可以用两片74HC00或者74HC04之类的逻辑门进行反相,但那就增加了芯片的数量。对于FC手柄这种工作频率并不高的设备来说,STC单片机完全可以胜任模拟工作。
5 s% X6 ?9 G1 g0 y6 O) I- r! X; `/ B/ ]# b% {7 b/ Q
( S; s! [" b. g6 {, T
$ H9 Y2 O6 v% y/ l' G# m
电路设计有点小小的错误,所以有几根飞线。原本设计使用低压差LDO是XC6206,结果在做这个接收模块的时候,买的LDO居然找不到了!无奈只好用了AMS1117。幸好对于接收模块来说是5V降到3.3V,1117可以胜任。要是发射端手柄的话,3.7V降到3.3V,那就非得用6206不可了。( _& D* N1 p: F: j
! [$ S) n4 K! V
实测十分灵敏,延迟极小几乎感觉不出来。可惜这山寨手柄的手感并不佳,尤其是方向键,软塌塌的。看来我得买个剪线手柄改装。8 u) O& R2 W  @( t* j  ]  |
4 o! Y7 `" \8 X$ |
这是电路图,有兴趣的朋友可以参考。
. Y  {/ A) b, O
+ L+ M& H/ n- t, r/ O7 g. M
7 A, j3 X; ]# F" m1 y  Q我信奉开源主义,十分痛恨把技术藏着掖着。好东西大家分享嘛!所以两个单片机的源代码大公开!8 D$ x  S& ~8 A# G7 Y/ N5 H
编译器:Keil 51。* V: I# }( T& ]2 y$ e2 z7 ]
) v3 s5 r) h0 x7 N6 ]3 D& `
发射端:( C4 s' z9 i; J& o8 R4 [
  1. #include <INTRINS.H>
    2 P& `9 J6 p5 R8 H7 L
  2. #include "STC15W.h") m% g, g$ A3 S$ H& F

  3. + f+ h* t0 k' F% Z* N' N
  4. 5 b, E' g% T" v5 ]% N2 i% C6 V
  5. /*
    ( j1 s, J5 F( K1 Z( Q+ m4 c' u
  6. --------------------------$ ]2 B+ O- T3 A7 Y
  7. |1 (OUT)        \__/   (INT1) 8|
    9 K( I& \9 s* [7 P9 E/ }
  8. |                                                   |  w! m6 N) z8 M% R5 u
  9. |2 (VCC)                   (INT0) 7|# I* L9 N0 Y& h: N( [) o, Z6 V
  10. |                 STC15W204S                   |2 ?  [* h$ i1 {: P( X
  11. |3 (LED)                         (TXD) 6|
    , ]' S6 X3 I! [+ P
  12. |                                                   |; K7 o& D/ K2 l! V2 O* o
  13. |4 (GND)                         (RXD) 5|
    9 }) B6 w; p7 k8 Z0 o# G: R
  14. --------------------------
    3 O0 i2 [/ L: c+ _

  15. - f  |2 X- T7 ~) o$ H. S5 @
  16. LED ---|<|---[===]--- VCC$ K' K# T* d4 F
  17.            Red          330
    : y  Q; x" h& s, z1 _# x! F. r2 k

  18. - H& C8 d0 y- W/ {
  19. Fosc = 6MHz: H4 F7 L* V" ~* b
  20. */
    , c4 {+ R  G/ u& o

  21. / q+ X# L% }3 s, b9 n+ r
  22. + Q/ T1 A5 O  _; \5 i/ M
  23. // 矩形波输出脚& }6 \9 G* X/ {8 w
  24. sbit OUT = P5^4;
    6 _0 m( V5 {- z+ `3 B3 s2 ~* z
  25. // 低压指示灯引脚& n% y- j! h. C" i6 L
  26. sbit LED = P5^5;
    . X, b4 C0 ]& _/ ]

  27. ) M2 C$ m9 I; O- A' z+ v3 g
  28. // 停机标志位
    ( r8 @1 I' _" R# q3 i+ ^! J  H
  29. bit isReadyToHalt = 0;5 W5 M5 Y6 Y% A, L

  30. 6 l; I. u+ u; w( @- V& ~
  31. // 矩形波次数累计' U- {7 T! e& P4 e6 B
  32. static volatile unsigned char count = 0;3 W/ Y* T( {- P7 [4 S3 M* i
  33. $ k* t$ T  ~# _9 N) C
  34. ' V4 w+ ^/ \  h. G8 M. Q
  35. static void GPIO_Init(){
    7 K+ W& d3 g  U; Q* z0 r4 x9 B
  36.         // P3口设置为准双向,默认靠内部弱上拉输出高电平
    8 A+ y4 A3 A; O2 r! x" j$ l+ _
  37.         P3M0 = 0;
    / t0 }1 d) s) H' m. v9 A
  38.         P3M1 = 0;
    2 l6 v, j4 T( Y3 d  y
  39.         P3 = 0xFF;9 P. J4 |- ?5 T2 ]9 z
  40.         // P5口设置为准双向,默认靠内部弱上拉输出高电平
    " l( N, Y. W# Z
  41.         P5M0 = 0;
    2 E0 l! a4 o0 s7 P* c3 g2 e
  42.         P5M1 = 0;( M7 X, Q9 r7 d2 C
  43.         P5 = 0xFF;7 f$ b' p: w1 F0 P
  44. }0 W. t) U4 R6 L& A
  45. ' y- ]3 {8 @" T( Y* L
  46. static void Timer0_Init(){6 U- J! S0 B' k: H- @7 A9 u/ J. U, o
  47.         // 16毫秒@6.000MHz
    9 Q+ t* E% e7 E  Y
  48.         AUXR &= 0x7F;        // 定时器时钟12T模式) v% q8 e/ l5 W5 S' Z& ^
  49.         TMOD &= 0xF0;        // 设置定时器模式+ d* f* g; x# L# \. b6 f/ K7 Q8 V& C
  50.         TL0 = 0xC0;                // 设置定时初值0 K( I" ~% x. M' ^7 |3 J
  51.         TH0 = 0xE0;                // 设置定时初值0 W" W8 [; }8 n! c" ~# C2 C
  52.         TF0 = 0;                // 清除TF0标志8 B+ S! U0 [5 I8 ?5 k2 o) k
  53.         TR0 = 1;                // 定时器0开始计时
    3 N. `+ j0 c5 }" E) o- X
  54. }
    6 x/ k$ M5 s- A' s

  55. ! Q6 P+ q5 X- m3 t6 j5 f
  56. static void Interrupt_Init(){
    7 z; o5 U* B' Z: V
  57.         // INT0中断触发类型为下降沿触发6 w& M! f; ?7 Y0 \2 j/ s& z
  58.         IT0 = 1;
    $ s3 U* c- m( P# I6 f
  59.         // 允许INT0中断
    3 e+ O, L! i4 X4 v
  60.         EX0 = 1;9 P9 t+ X. U& l' e1 X( [
  61.         // INT1中断触发类型为下降沿触发
    5 Y: B6 U4 n* P! T% {
  62.         IT1 = 1;# y% @- y; X: |( P; S0 b, K
  63.         // 允许INT1中断
    # _6 Z! ]% [# A) Q9 o
  64.         EX1 = 1;
    2 v: J; C$ n8 H8 @& V& Z, g0 B5 s
  65.         // 允许定时器0中断  \7 C+ z# v7 ~* F1 B! h) g
  66.         ET0 = 1;
    ; _0 [$ n! k8 P  M. H( }% ?9 q
  67.         // 允许全局中断
    . M# x, f- O. g6 h. T6 D
  68.         EA = 1;
    ' z& I9 `& _% D$ a6 V$ {7 R
  69. }' ?/ o) `, a2 n7 i

  70. ) j' ]) k8 d4 w
  71. static void INT0_Isr() interrupt 0{
    + ^6 }' N2 N# o  y4 Y; s& ]7 P
  72.         // 矩形波次数累计归零
    . h- s9 i7 R. u( Q$ w) i: o, B
  73.         count = 0;
    1 R* X5 a8 E4 @  u6 x
  74.         // 重开定时器0中断! i! w& E* B4 C4 Z; {4 y: ~( T0 O/ L
  75.         ET0 = 1;0 s$ ]( T6 g4 q
  76. }" s+ n4 u& @/ X4 N! ]% D
  77. ( [9 V! v8 s( ?) s: x. i
  78. static void Timer0_Isr() interrupt 1{' X4 \. X7 M2 [4 b6 L1 H5 u5 U
  79.         // 输出矩形波
    2 U; x; x' b8 o! t
  80.         OUT = ~OUT;. m1 F2 Q* X% |, b
  81.         // 累计矩形波次数/ y9 |* ?1 t) q7 k) w& |9 K
  82.         count++;
    / Q% q( P! o( s, N  r
  83.         // 超过250个矩形波,准备停机0 A' E1 V: X* t% _, M
  84.         if(count > 250){, v' P5 ~) K& U
  85.                 count = 0;; Z1 f1 `9 V/ O  I& ^. l) o' Z
  86.                 isReadyToHalt = 1;
      c0 a! V  c* D" ]2 `. U
  87.         }
    4 I. W2 G# [$ O# u
  88. }9 L, U2 B5 n) K& M3 o/ W; ?
  89. 7 d  y0 f% g- Y0 Z1 `! D+ X! D
  90. static void INT1_Isr() interrupt 2{. B% s* X1 D& w: Q
  91.         // 矩形波次数累计归零: Q! H5 N- Q) [, r! `2 F
  92.         count = 0;7 `+ W2 m& z+ I
  93.         // 重开定时器0中断
    $ ~* X6 e1 c9 l2 o  a6 g7 I
  94.         ET0 = 1;
    # z9 M4 m/ h" j) ~/ [' O/ B8 g
  95. }" p& A* Q, @8 K, L

  96. ! @  E9 u, L  c5 |% e9 C6 C

  97. 1 s# i- O' F- Z
  98. void main(){+ b' }; j2 y9 a+ o/ R
  99.         // 初始化P3和P5口
    ) _, U! B) Q3 H4 {
  100.         GPIO_Init();
    . m% P- k$ D/ Q; C; M$ }
  101.         // 初始化定时器0
    8 ^& B" d' w; H2 ~0 b% x5 L- s. _
  102.         Timer0_Init();
      y! i' X' |& L( H; c+ P
  103.         // 初始化中断, X8 J7 t" N( t; Y* u' @
  104.         Interrupt_Init();
    2 O# f; \* O8 e+ z
  105.         9 v( M* Q$ T- x9 F$ m: l
  106.         while(1){
    # X) w! k% r+ L
  107.                 // 检测电量
      g' j/ i' Y8 p/ a; M, y
  108.                 if(PCON & (1 << 5)){* d: l2 o: f' o  w5 d4 E
  109.                         // 如果电量低,低压指示灯亮
    2 J& `  W# L, }% P6 p2 z6 w
  110.                         LED = 0;
    0 ~1 C% ~6 b4 }4 v% h5 ~
  111.                         // 清电量检测硬件标志位( V! N5 V: D* J& b  ^& {
  112.                         PCON &= ~(1 << 5);  u& l+ w# T* U3 Z* g* w" c
  113.                 }else{
    ! }) b4 g5 p+ L1 n' p
  114.                         // 电量正常,低压指示灯灭
    3 X6 z4 ^$ e# q& g$ C
  115.                         LED = 1;
    2 x# P# W- j5 _0 s- _
  116.                 }
    % A+ z  L+ {/ m: E; l

  117. & v# }0 b* [& d0 `6 g
  118.                 // 检测到停机标志  g' O  [" _2 _
  119.                 if(isReadyToHalt == 1){
    * V* ~$ i1 V7 b
  120.                         // 暂时关闭定时器0中断/ T) i# R! J( A0 _3 t8 \7 _
  121.                         ET0 = 0;
      t5 w' A5 m8 H2 F
  122.                         // 停机之前先把矩形波输出脚置低电平,以方便INT0和INT1唤醒CPU+ E/ K0 _( \# i# Y/ e
  123.                         OUT = 0;8 y  d4 `. k2 T
  124.                         // 停机之前先把低压指示灯灭掉,以省电
    2 v/ E$ o7 [* P" K
  125.                         LED = 1;
    $ B1 [# k1 _6 d. P+ h  C" g# W+ k
  126.                         // 进入停机模式/ B! `9 ]( U& b) ^5 ~" T
  127.                         PCON |= 0x02;
    % n0 B: A7 g8 ?
  128.                         _nop_();
    7 k- W$ o4 D0 u% L* d( u  g- u
  129.                         _nop_();3 I% y4 a) h& p& G9 t
  130.                         _nop_();% q7 i4 h3 I7 a7 e5 B7 ~2 J
  131.                         _nop_();
    # T( A7 W2 _' ~+ O" E
  132.                         // 唤醒,清标志位
    + e# ^5 \+ y9 M2 j' e4 A
  133.                         isReadyToHalt = 0;
    1 o0 o' [' D$ M# W" F2 G
  134.                         // 重开定时器0中断6 ^. j- a8 {8 A6 |& }/ D, B' {
  135.                         ET0 = 1;
    % `$ E6 W( j/ |2 p8 C2 e# ^
  136.                 }
    ) r) b7 E+ R" S" |
  137.         }# n' l# i% [# q+ z7 p
  138. }% F( X! D9 x9 I; ^
复制代码
6 O& x1 x- G% p7 E6 K. e! W
硬件参数配置:" |4 Y  f. y; t. n$ \. \, p
& n" t& a0 o3 s) P- o: b% \; W

+ Y& Z$ s  ~) L* ]8 X" w接收端:
% f+ p: O$ |* J& {
  1. #include <INTRINS.H>
    - g" _6 Z0 b! U& S$ C1 z% V
  2. #include "STC15W.h"
    : l2 ]6 z$ y7 X2 v" b

  3. " _; u+ E  A- X. b: c$ v  J# P! u

  4. 8 I% _% o7 F) T8 O
  5. /*) d8 |( A% J" s1 F, ~

  6. 8 [5 L' A/ S7 P7 [( N0 v
  7. *---------------------------*1 S1 x3 Y- n* \
  8. |1 (GPIO2)         \__/  (GPIO1)16|
    5 U8 H" d- _2 g; w4 ^& H; {
  9. |                                                        |' {" o8 ^3 @3 I. m! e: \5 o0 B6 n
  10. |2 (GPIO3)                   (GPIO0)15|
    . u6 R& |" X  E, e
  11. |                                                        |
    8 D* ?6 [5 M; A3 Q5 E5 _! N
  12. |3 (GPIO4)                                  14|2 |. X' _, a, m) A. \& p
  13. |                                                        |
    6 U$ ]4 h( {  H( y% {
  14. |4 (GPIO5)                        (DATA)13|9 W9 c5 W' Q/ l, `, D
  15. |                  STC15W204S                |% C6 p: P7 v+ i6 W, F# D
  16. |5 (GPIO6)                   (LATCH)12|8 V3 {7 b( M" ?: s9 N
  17. |                                                        |9 z+ q* C. W: B& ?
  18. |6 (VCC)                         (CLK)11|
    8 G8 Z" \8 n6 x4 X, K4 |" ?" `
  19. |                                                          |
    % \, N: `. B: g/ I1 i
  20. |7 (GPIO7)                         (TXD)10|& T/ E* J- t% ~9 W( f* ?
  21. |                                                        |
    6 D' I$ d- Q8 C* g" ~- b' F
  22. |8 (GND)                         (RXD) 9|% s+ P! b1 w0 C- N6 n
  23. *---------------------------*
    6 F2 \0 q' a$ [( {
  24. Fosc = 12MHz& O5 q: B+ [$ `8 D3 k% [
  25. " i1 a+ {7 c( w. Q( p
  26. P1.0 -> 上
    7 A8 Z* l/ e: E9 _* [
  27. P1.1 -> 左0 f8 M0 U' C7 L
  28. P1.2 -> 下" u1 U7 q6 K( H% {3 _4 a
  29. P1.3 -> 右
      s- q' e" M$ h
  30. P1.4 -> SEL3 L5 W3 a0 y" N8 K# ]( [3 [( D" h3 m
  31. P1.5 -> STA1 I, j/ {* w: B/ c- [* J! w  p2 p
  32. P5.4 -> B3 v: b+ D# }$ J- O4 _
  33. P5.5 -> A' D" Y) S5 s: p. I: R

  34. 0 g3 g0 w& S1 ]1 [1 u6 j0 n& D
  35. */3 ]4 t3 v& ?; o+ n
  36. 8 z+ z0 V" T/ {8 r- [

  37. / m4 q. w8 b9 J  i+ m
  38. sbit CLK        = P3^2;+ X/ D: ^* P1 _# p" P( b
  39. sbit LATCH        = P3^3;
    6 X9 s2 Y" J9 L  V$ _
  40. sbit DATA        = P3^6;
    7 Y. z& P: J8 r3 ~. ?# ~
  41. ' b; G! A) O8 o
  42. bit isReady = 0;
    1 a8 s4 m, |$ j+ Y8 Z1 [
  43. static unsigned char key = 0;
    $ t% Y! t5 F' \" Y
  44. static unsigned char buf = 0;        // 双缓冲。这个缓冲区保存从P1和P5组合而来的键值
    5 F( T( m$ i# I
  45. static unsigned char bufReady = 0;        // 双缓冲。这个缓冲区保存上面那个缓冲区的备份
    + l% f. w) L- s+ }0 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中) ?% O. M: N, |4 _" e3 y1 }# k
  47. static unsigned char idx = 0;4 o5 w: U# O  `& x) j

  48. , j' L+ `- s2 ~( T- N# ?7 b& w
  49. , B1 O0 `, b( N! n# X3 U' O2 b
  50. static void GPIO_Init(){
    . X5 O6 W7 d* B9 q/ U  [8 _
  51.         // P1口和P5口用于接收并行信号,全部初始化为准双向,依靠内部弱上拉输出高电平
    1 K- v9 T2 U: r" O) {( p4 y  D
  52.         P1M0 = 0;
    * T( @! p1 u9 W4 X+ Z2 U  x
  53.         P1M1 = 0;7 y& ]- H/ B/ u9 a" u1 H; ~8 q
  54.         P1= 0xFF;3 n' t9 f; b+ |% B4 c0 F0 L1 r
  55.         P5M0 = 0;: p1 \7 P3 d  O3 w8 k! {
  56.         P5M1 = 0;4 d  G) o" u! J& \; t
  57.         P5= 0xFF;  K3 A/ i( V7 y3 s
  58.         // P3口初始化为准双向2 Z) X! ^0 @& b* F" x# ?, \6 |/ F
  59.         P3M0 = 0;4 w4 a- Q. ^- {# Q+ ^+ x0 f
  60.         P3M1 = 0;
    ; ~$ d/ g% t! h" ?
  61.         P3 = 0xFF;
      m5 G  r. o" {3 I, l
  62. }
    ! d  Y8 R3 L' B' w; z4 K& Z

  63. ( ]: A7 |; b& B4 R( ]
  64. static void Interrupt_Init(){# s/ d, @& ?! Y; z- J' I
  65.         // INT0中断(CLK)触发类型为上升沿+下降沿- T2 P6 t1 P  U
  66.         IT0 = 0;
    * u- e5 T8 h: A' s* m' W7 k
  67.         // 允许INT0中断
    ) `2 t( G- l# F" u% A
  68.         EX0 = 1;' {5 A1 W2 a# m) \
  69.         // INT1中断(LATCH)触发类型为上升沿+下降沿' ]" z: Z" p3 I, n9 G
  70.         IT1 = 0;
      v. A! ~# c; m. `/ l( K
  71.         // 允许INT1中断
    , `* f/ j, c+ k; c. Y
  72.         EX1 = 1;& E- C# F9 |8 ?2 j
  73.         // 开启全局中断
    $ [; g9 O( w4 a' l7 F: C
  74.         EA = 1;8 Y# m) t+ w' J6 @7 D
  75. }
    2 G/ b( C' g& _; C7 L7 v& i

  76. + o9 K5 g! K7 Y# r$ q( f5 h4 W' y
  77. static void INT0_Isr() interrupt 0{
    9 @$ M1 ~! k7 `; C
  78.         // 只有已经成功锁存才允许CLK移位+ i0 O7 b. Q0 N7 A# g
  79.         if(isReady == 0)% ?5 X/ Y2 I9 B& x! E
  80.                 return;  q; ~1 R) z- F1 [
  81.         // 读当前引脚电平,如果是低电平则说明是下降沿,此时直接忽略该中断1 a* p3 X- j4 T2 y9 |1 j- H
  82.         if(CLK == 0), P+ ]6 g( h7 u5 S* j
  83.                 return;
    7 }( Z: b! f! h  S5 F. K
  84.         // CLK上升沿到来的时候,取锁存值的下一位输出  X  \) l# b- L2 {
  85.         idx++;
    5 t, _; L3 b: ?
  86.         DATA = key & mask[idx];7 a/ Q, L2 Q. O6 V
  87.         // 如果已经完成7次移位,则一轮读取完成+ E( ]0 Q! A: u
  88.         if(idx >= 7)
    ' a/ t  W& O; h+ l6 u* h! `. y
  89.                 isReady = 0;
    + W9 U3 X6 [* H9 R  }5 H) g( R
  90. }
    0 f% k: p3 j* c7 s2 v" ]5 H
  91.   \3 L4 ~" q- }+ f; i4 g+ J
  92. static void INT1_Isr() interrupt 2{
    % R9 ]. W- p& D* u
  93.         // 读当前引脚电平,如果是低电平则说明是下降沿,此时直接忽略该中断3 |  I2 k) \. _% `
  94.         if(LATCH == 0)
    7 _$ V3 \8 z4 }7 V9 v) O: p; |
  95.                 return;! ^3 I) y3 G+ N' |/ K
  96.         // 当LATCH上升沿到来的时候,锁存所有按键状态,同时把键值A输出到DATA
    ' y- {$ Y5 n: ]  ~# W5 W  o1 O
  97.         key = bufReady;$ N1 u  q9 U" |$ s8 ^" \0 ~5 Q
  98.         DATA = key & 0x80;//mask[0];        // 为了加速运算,直接取表中的值而不是读表
    : _2 x7 }" c1 n% F( m7 u& t9 u' D
  99.         idx = 0;7 q; X) v( v2 P9 r+ k
  100.         // 允许CLK进行移位
    / R5 u9 M9 S; h+ R1 J
  101.         isReady = 1;4 c# `+ z# G/ ?4 h2 _
  102. }" e  I/ T! H0 G7 @6 @' H8 J5 Z

  103. 4 G- C4 t  R2 C: @2 ?0 s% E
  104. void main(){" r! y( e% y  |0 \5 [2 J. H
  105.         GPIO_Init();
    % F- A& {* ^; j& W0 E& h/ O
  106.         Interrupt_Init();5 y, u+ N% k& p- k0 t3 B3 X) u1 t4 n
  107.         8 ^" O% B7 j; @6 n! A8 l2 r: i, t
  108.         while(1){) i7 c, o' Q  Q
  109.                 //PCON |= 0x01;        // 进入省电模式# w8 u" A7 E4 n! a
  110.                 //_nop_();, ]* T3 J6 F; r. u0 z( a" p
  111.                 //_nop_();
    - `0 H) y$ z0 Q8 L
  112.                 //_nop_();
    7 n2 Y5 c8 R  R
  113.                 //_nop_();1 L: T# i" l$ @! r2 C
  114.                 buf = ~((P1 & 0x3F) | ((P5 << 2) & 0xC0));
    9 Y' k$ @. a: L. E$ q& }8 n8 k- ?
  115.                 bufReady = buf;
    + w! Q6 K5 L+ E. ^
  116.         }
    ; t, g( `' ?2 P$ ?. @5 ^$ v" w! t* N
  117. }
    , y$ q  e: n/ n
复制代码
5 T) }8 T1 W& `$ d9 y
硬件参数配置无特殊要求,晶振频率选择12M即可。, g' n/ |& m) V8 i
. Z# R$ E7 [" W# J: f% u
这是编译好的固件。

本帖子中包含更多资源

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

×

评分

参与人数 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
6 o3 R8 N6 `% \8 L5 T9 q; n7 F不错的设计,想问一下楼主,FC的15针公头怎么解决?普通的公头太短了,插不进去FC的扩展接口。 ...
* N9 f! l1 l& l! [) y3 i7 }
坛友的改造方案
回复

使用道具 举报

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

使用道具 举报

发表于 2019-5-25 12:07:18 | 显示全部楼层
精彩,楼主动手强,也写得很详细。6 G, F- N$ q1 E3 |# \9 L& e( K
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% C1 k6 g& d4 M6 E" g- N
精彩,楼主动手强,也写得很详细。
" t- ?' e. ~+ c3 f, I, L4 f3 G2.4G方案是目前无线的最低延迟吗?
9 B) S3 R7 n$ k/ `' }, T& I" o
我没用过其他无线手柄,所以实在不知道我自己做的这个手柄到底是不是最低延迟。
: U5 N% e8 u$ ^/ W不过根据网上的说法,延迟高低主要是由通信协议的复杂程度,以及数据传输速率决定的。这个模块虽然是2.4G无线模块,但由于协议很简单,所以延迟比较低。* \- ]2 j" P4 X6 L$ @
我用这个手柄玩一些ACT游戏,比如超级马里奥、忍者龙剑传、热血系列,完全感觉不到延迟,和游戏机自带的手柄没有任何区别。唯一的区别就是这个手柄是用火花山寨手柄改造的,外壳是垃圾回收塑料,粗糙+脆弱,导电橡胶弹性不佳,手感不是一般的差。7 y" Y% t: y* P4 S# D" H5 {7 Y9 }
我手里还有十几张板子,等我有空了我再做一套,到时候买一个好一点的手柄改造。
回复

使用道具 举报

 楼主| 发表于 2019-5-29 16:56:14 | 显示全部楼层
ppad 发表于 2019-5-28 17:272 k$ Q" H- g2 p/ K
给技术帝赞一个,有半成品发布吗,自己焊接改造就可以,编程实在不会啊 ...

; g% r$ b) c% Q4 \) y  w很可惜,我手里没有多余的单片机了,LDO也找不到了,锂电池以及充电模块更是没有了。反正就是该用到的元件基本都没了,所以没法发布半成品。
8 r: x# r0 H- T/ v( W0 Y两个板子倒是有十几张剩余。
7 T3 l5 a/ X9 G3 B! T你要是有USB转TTL串口板,完全可以自己买这两种单片机,然后我给你编译好的固件,你自己用串口板下载到单片机里面就行了。两个2.4G无线模块也得通过串口板用AT命令设置参数,不过好在我在设计电路的时候就已经预留好了串口,可以直接在线下载和在线设置参数。总的来说并不麻烦。
回复

使用道具 举报

 楼主| 发表于 2019-5-29 17:00:34 | 显示全部楼层
孙大师 发表于 2019-5-28 18:55
9 i$ v, q: x, \# P3 }: ^0 k非常好,楼主是技术帝,到目前我都还没开发fc的无线套件,等空了,开发一套套件,等玩家自己组装。 ...

/ V" p1 o& a0 E! r8 T2 n* L能得到孙大师的赞誉,不胜荣幸!9 E. k/ I; I  S; @( U) }' x
不如开发一个多功能手柄,比如用SFC手柄改造,L/R键配合其他组合键可以用来切换2P~4P、调节连发速度、软重启等各种功能。接收端插到15PIN扩展口。
回复

使用道具 举报

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

本版积分规则

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

GMT+8, 2026-5-15 20:06 , Processed in 0.098501 second(s), 14 queries .

Powered by Discuz! X3.5

© 2001-2025 Discuz! Team.

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