找回密码
 注册

QQ登录

只需一步,快速开始

查看: 22020|回复: 27

自制FC无线手柄

  [复制链接]
发表于 2019-5-22 14:16:45 | 显示全部楼层 |阅读模式
本帖最后由 雷精灵2046 于 2019-6-14 09:28 编辑
( K& x; C4 S- ^) Q$ t
- e. l5 \8 f8 F' d$ `7 S没有用复杂的分立元件搭建发射接收电路,直接用的现成的2.4G无线模块jdy-40。3 I7 G) }# D" E$ I% g% w5 q
$ y1 {3 K) X! Y4 E# `% l% M+ B
6 p+ T2 q! e, n& I. e( V* C
发射端靠3.7V锂电池供电,用了一片SOP8封装的STC单片机,负责产生连发脉冲,同时负责检测电池电量,电压低于3V左右的时候触发低压中断,低压指示LED就会亮起来告知该充电了。平时发射模块和单片机均处于睡眠状态,有按键按下才会唤醒,从而实现省电。实测睡眠状态下整机电流约1~2uA。板子洗了一下稍微干净了一点。因为对于微功耗设备来说,焊接残余的助焊剂可能会增加漏电流。/ _8 J+ q- J, q' H! ^4 W9 p

+ ^7 X' z1 }2 \( |/ A买了一个火花的FC山寨手柄,去掉里面的牛屎板子,并修正一下塑料挡板,把锂电池和充电模块装进去。* M& p8 U8 l" m2 @$ j3 m* p
为了减少体积,充电模块裁剪得十分小,并且更换了充电电阻使之适应这个小小的锂电池。这么小容量的电池,也不需要多么大的充电电流是吧?
  ~  z$ _/ i) h! S" G' G3 Z然后统统用热熔胶粘上。充电电流比较小,所以发热很少,不会熔化热熔胶。( |. {4 e# h5 p2 \3 D: T2 z
; b7 g3 C+ j- T* Z& {
: i8 ]0 U# p5 ]/ K8 C
, x" I- k8 J6 f8 `" V/ F2 k
最后把按键、导电橡胶和电路板装上去。& w3 z% P. Z* U+ C: t
精心裁剪了电路板,正好扣上,不会阻碍其他元件,也不会影响后盖和拧螺丝。
2 \# V- U5 r1 ^' t, x+ g
& S6 b+ i# M1 I% e) v. m6 w6 h3 K: ]" p% l* d0 @
完工!
3 M+ g  Q' J9 p7 m( Y8 s' V" p
1 O6 J# K' n/ U2 F$ b* |3 ]" |/ P7 i" I: M$ N
这是充电的MicroUSB插座。旁边的小孔用于透出低压报警LED的光线。8 c7 @: I! s7 n  s3 A( D' @

7 _- L9 w4 h- W( f2 c9 g& H2 }0 A0 P3 W
接收端用一片DIP16封装的STC单片机模拟CD4021。为啥要用单片机模拟而不是直接用CD4021?因为jdy-40模块接收端在有按键按下的时候输出高电平,无按键按下输出低电平,和普通手柄正好相反。当然我也可以用两片74HC00或者74HC04之类的逻辑门进行反相,但那就增加了芯片的数量。对于FC手柄这种工作频率并不高的设备来说,STC单片机完全可以胜任模拟工作。
, Z+ P- C- v7 H% Z. X: j! @
5 u$ Z9 e" z, Q6 ^
- v# u7 T; U- {- U" @2 ^' y. y7 r
电路设计有点小小的错误,所以有几根飞线。原本设计使用低压差LDO是XC6206,结果在做这个接收模块的时候,买的LDO居然找不到了!无奈只好用了AMS1117。幸好对于接收模块来说是5V降到3.3V,1117可以胜任。要是发射端手柄的话,3.7V降到3.3V,那就非得用6206不可了。
' d( B5 a$ D' g/ z6 b2 ]1 x6 y4 i1 |' f9 h* z/ f) M
实测十分灵敏,延迟极小几乎感觉不出来。可惜这山寨手柄的手感并不佳,尤其是方向键,软塌塌的。看来我得买个剪线手柄改装。
% J$ H$ S* G( I6 R0 J0 ]% `9 I: |( g$ p4 T3 [0 ^
这是电路图,有兴趣的朋友可以参考。/ ~1 v" I# M5 f0 Q- n! }+ r% b

9 F' c! E  H9 a
! _0 @" g' f. r! T9 ]- t我信奉开源主义,十分痛恨把技术藏着掖着。好东西大家分享嘛!所以两个单片机的源代码大公开!
% Q- L6 }% L! t( J8 v; K编译器:Keil 51。) @/ @( Q, A' W; o

  n( M0 K/ n1 y" g- S* i' v发射端:
: Y# ^% O8 i% B0 H2 X/ c" s8 J
  1. #include <INTRINS.H>
    9 _  e/ [2 r) b
  2. #include "STC15W.h"
      D9 k9 T/ z( N5 D- ^4 V) R1 H
  3. $ ?, L; n7 @# n# N
  4. 3 r% N/ ?  V# e3 H6 i" p; W
  5. /*( B) }8 T1 `. a6 m$ s
  6. --------------------------
    2 }3 ?9 F1 H, J: C
  7. |1 (OUT)        \__/   (INT1) 8|$ X- E. H$ p- N, z( T# j0 S
  8. |                                                   |9 q* K) ~: ?6 @6 B/ ~' {4 e
  9. |2 (VCC)                   (INT0) 7|" O  ]* d+ \7 O0 W
  10. |                 STC15W204S                   |9 v1 w0 i9 j9 v# T9 L! i
  11. |3 (LED)                         (TXD) 6|" f+ k9 H) z! y4 n6 O" r
  12. |                                                   |/ t9 S7 w8 l2 _' X
  13. |4 (GND)                         (RXD) 5|- _% g* c( U: ~  w/ P
  14. --------------------------
    2 F( J( V1 {# \0 n3 D9 M" d

  15. " x) P) t9 x, ~! o$ x2 K$ E0 a7 V
  16. LED ---|<|---[===]--- VCC
    7 e1 S# ]1 u! @' r* `/ [4 E+ J
  17.            Red          330
    ; t; Z4 P1 v" d; m6 }3 @2 a
  18. & Y% K; X: i; s9 ~+ U" P9 ?9 t
  19. Fosc = 6MHz5 C/ T& M; p6 S, @& P1 N
  20. */
    . Y6 y1 f" W$ c/ i8 D9 r

  21. * g5 k; w- R3 F- E- Y* F" e
  22. : R2 n) L5 B* V7 l4 R
  23. // 矩形波输出脚
    5 ~1 q( Z! I3 Q. V7 K
  24. sbit OUT = P5^4;
    . F' S8 E% A% j5 r
  25. // 低压指示灯引脚
    5 M8 \/ H6 m3 p7 \
  26. sbit LED = P5^5;
    ( W* M: j! b1 y6 W1 A
  27. 1 ?' F2 s( f7 \) D+ y  o
  28. // 停机标志位/ P' q4 f' K4 O
  29. bit isReadyToHalt = 0;# w! `5 J' n# h, Y7 L0 |! e
  30.   B( _# m  o8 }
  31. // 矩形波次数累计
    ' |& @' r4 }/ W% I( m. ~: V
  32. static volatile unsigned char count = 0;5 h  n% G5 j* C
  33. ; g) J- e# |# ~  R$ B' z/ {

  34. 0 A1 ^2 Q; t9 e& ]
  35. static void GPIO_Init(){
    - ?$ c! Y0 i. z/ n
  36.         // P3口设置为准双向,默认靠内部弱上拉输出高电平
    ; o7 ]8 c+ I/ U
  37.         P3M0 = 0;
    $ ?% x! i# h2 W
  38.         P3M1 = 0;  q9 \/ u$ ?3 b
  39.         P3 = 0xFF;
      w% L. h" W$ @- K  k  {& |" @
  40.         // P5口设置为准双向,默认靠内部弱上拉输出高电平
    6 l$ S0 U0 @8 k4 G# H7 \
  41.         P5M0 = 0;2 j+ p$ \6 R) b
  42.         P5M1 = 0;$ h* u% H* R1 ?! ^
  43.         P5 = 0xFF;
    $ b- J/ L* a5 H  I  N
  44. }
    2 Y" w3 V3 d% w# d
  45. ! b: c) [1 t+ U+ x% U
  46. static void Timer0_Init(){9 f8 s+ G3 I, z9 ^
  47.         // 16毫秒@6.000MHz
    ( u: a* w- ]9 I9 d
  48.         AUXR &= 0x7F;        // 定时器时钟12T模式
    & V  Z  ]& u; l0 b# {- a
  49.         TMOD &= 0xF0;        // 设置定时器模式
    ! l8 v5 K) O* o
  50.         TL0 = 0xC0;                // 设置定时初值
    ' W  h( w0 T7 u$ T/ ]+ r
  51.         TH0 = 0xE0;                // 设置定时初值' M' c# G4 N' ?* O
  52.         TF0 = 0;                // 清除TF0标志: l" k/ J  _. `0 N" r9 E5 }
  53.         TR0 = 1;                // 定时器0开始计时) k6 U5 s, _) ?, C% K8 o
  54. }
    9 f8 @) Z' P3 n6 G. K

  55. 7 [  e- L' U4 v5 c1 w; E/ E
  56. static void Interrupt_Init(){" }: ~, I) ^- n& M7 g, T7 I
  57.         // INT0中断触发类型为下降沿触发' O, g/ S3 u, c: y4 |9 ]
  58.         IT0 = 1;
    1 y/ H" g$ p0 @2 T: ^# F% [
  59.         // 允许INT0中断
    / D  [9 n+ K3 \$ W$ L
  60.         EX0 = 1;
      j6 r$ s- `6 J6 Z! I# r
  61.         // INT1中断触发类型为下降沿触发
    0 A- c% l" ^0 E+ T) E! S# U+ m
  62.         IT1 = 1;
    3 J* w# _2 w8 h- Y
  63.         // 允许INT1中断
    " b8 X3 B4 e* D+ t3 R5 B
  64.         EX1 = 1;- y; I: e! _- ]
  65.         // 允许定时器0中断
    . t5 p) N$ Q/ f6 A- s
  66.         ET0 = 1;7 s  A! L3 O8 E) i
  67.         // 允许全局中断
    " [$ C9 p: I+ L6 h/ _
  68.         EA = 1;' p- J2 S# C2 H9 c) t9 e
  69. }
    * d( h7 G( Q: \" _
  70. - k3 \0 J; Q- E, `
  71. static void INT0_Isr() interrupt 0{, M. |& e/ Z2 t: ?
  72.         // 矩形波次数累计归零
    * U0 E% f4 K2 M0 z: q" s& g" o
  73.         count = 0;
      g* P+ \2 C' W/ N; S7 w
  74.         // 重开定时器0中断
    . x& \+ C% i9 H2 R/ l
  75.         ET0 = 1;9 X, f9 _) g2 s: F% Y) O
  76. }0 \2 |# @5 u+ H! j0 |1 p: H1 r& P8 N
  77. ( I* q0 k# a) B6 w$ V7 s1 |) {
  78. static void Timer0_Isr() interrupt 1{; V6 x7 X. X; B# v7 j2 h* \; g0 p
  79.         // 输出矩形波
    * S9 r8 i4 x5 D& B) z$ G
  80.         OUT = ~OUT;' Z: O$ r* R4 B, ~0 Y
  81.         // 累计矩形波次数
    5 _+ f) @% d5 B, Y5 ~4 V, \4 A
  82.         count++;
    # D4 S- {0 v* q, {) C2 i& Z& u
  83.         // 超过250个矩形波,准备停机$ ]( v, R, K/ l0 K8 N4 f/ S( n
  84.         if(count > 250){
    " s, u4 |* b+ S! E, w
  85.                 count = 0;. B! Q" H! p. P% k7 p/ E
  86.                 isReadyToHalt = 1;
    4 W: O1 ~% I7 `9 g9 d
  87.         }9 T  Y; v1 j9 X
  88. }
    9 Y% I) w- F# w8 S" W
  89. $ l2 D0 O+ J' C4 D3 N% c; S" ]
  90. static void INT1_Isr() interrupt 2{
    * T) M* H" M4 \9 D1 z; Z" E$ {3 S
  91.         // 矩形波次数累计归零
    6 z$ y/ T0 s2 s8 ?1 Z  L
  92.         count = 0;8 S8 z1 v8 a( l
  93.         // 重开定时器0中断
    * p/ R, r9 o/ {7 ?7 y- _
  94.         ET0 = 1;
    1 V0 r+ r1 b( y
  95. }
    ( z* m/ ?) i$ |2 d% b

  96. ) Y& G% G- g. w1 u

  97. - A- G5 Z" ~6 L+ ?. u( J' ^
  98. void main(){
    9 n# [3 Q" `! R- M7 `* @2 ?
  99.         // 初始化P3和P5口) b8 Z' ?1 k$ ^# J; j# q
  100.         GPIO_Init();* s* ~' k3 U: {, U' D
  101.         // 初始化定时器0' D) S- y2 l* S
  102.         Timer0_Init();
    9 @! l# {' \" o. w6 @. O' W: g+ M
  103.         // 初始化中断4 `* ^* d3 u4 s# p
  104.         Interrupt_Init();
    - z( K! b5 o) T7 L
  105.         + |& Z, J1 `, Z- B: R
  106.         while(1){
    7 z8 O" e, a5 k
  107.                 // 检测电量: [4 ?$ ]& p; p7 ~: e! L4 c, Z
  108.                 if(PCON & (1 << 5)){1 J% m4 y% S% D1 O
  109.                         // 如果电量低,低压指示灯亮7 m: C" [" _" U
  110.                         LED = 0;$ ?' m9 y2 A. Z  p# X
  111.                         // 清电量检测硬件标志位7 T0 _2 K0 b* ^; N. E* Y' h4 `" [* R
  112.                         PCON &= ~(1 << 5);: ?, p, r3 [2 d5 y& a/ Q7 _* {; o
  113.                 }else{# S% Q9 v6 j! }7 x2 }! J5 B
  114.                         // 电量正常,低压指示灯灭
    ' d' o+ Y9 n# Q$ M5 [" a
  115.                         LED = 1;
    " r, t9 ~7 d, q, B6 z! S5 F
  116.                 }( J1 {" @+ A( Z- M: _1 p" F

  117. 8 ]: E, \3 D) q+ |' u
  118.                 // 检测到停机标志
    : I+ o$ i6 W% d9 J  Z
  119.                 if(isReadyToHalt == 1){9 a( S- r: A' A2 P$ q* h
  120.                         // 暂时关闭定时器0中断
    9 H- m7 y6 ?/ ~/ H3 ]
  121.                         ET0 = 0;
    " c3 U" [7 H0 e( h. U" {7 w
  122.                         // 停机之前先把矩形波输出脚置低电平,以方便INT0和INT1唤醒CPU
    % ^, ~  h" O* p% M+ C& T. P# y7 Q
  123.                         OUT = 0;% t; {0 e; X0 X* ^; q
  124.                         // 停机之前先把低压指示灯灭掉,以省电7 h9 j+ a1 Z8 ~) S0 B
  125.                         LED = 1;8 u( B; y: c# N; i5 _
  126.                         // 进入停机模式
    ( |! ~2 n* ]- M' \( {7 V8 P
  127.                         PCON |= 0x02;1 e/ W( c# {# j. u* V; x
  128.                         _nop_();$ O! Z- r9 h: Z5 G
  129.                         _nop_();' A5 R0 [+ f: }  ]: I& z# X) P
  130.                         _nop_();
    $ i* i! c2 g1 ~  M9 x3 i. ?9 Z
  131.                         _nop_();
    : a) }; R# X$ H' \
  132.                         // 唤醒,清标志位8 c& z) A" t# {3 i/ X
  133.                         isReadyToHalt = 0;+ T. J. O/ k0 W8 N
  134.                         // 重开定时器0中断5 ?7 H  e9 X0 Q! S' ^
  135.                         ET0 = 1;
    * J7 z; K: h& \+ x5 @; v: i' N) @- s
  136.                 }. x) K" ?. ?' j. W
  137.         }" U9 B( H9 H6 C* A* Z% T  h
  138. }' q$ p9 I% t& L6 E6 p/ ^* |
复制代码

6 V2 A/ ?$ G" ^6 ^( u2 `硬件参数配置:
( q$ g1 H1 c* r, ]+ f
" a/ g* A" L9 E0 l
3 g0 T0 Q) s5 H/ l/ ?接收端:+ w% M6 D/ {7 k: J. Q$ x: }+ r
  1. #include <INTRINS.H>
    5 N! Z6 @. i; Y% h5 U5 ~6 A7 p
  2. #include "STC15W.h"4 F! |% z8 Z& a9 R
  3. . j* h+ h" e3 z7 v! `& t
  4. 6 r6 U4 `" _% [9 A2 Z+ _! q
  5. /*9 L" p7 Y5 K& e" L6 q8 l: w
  6. 7 I2 I" e) w% U4 @" u; W
  7. *---------------------------*
    : F" E' O! s' k- l; m9 l) k$ z
  8. |1 (GPIO2)         \__/  (GPIO1)16|
    3 a3 E, D8 I9 \! d2 |$ K
  9. |                                                        |* u: d5 Y# X9 Y. V" a
  10. |2 (GPIO3)                   (GPIO0)15|: d, _: {2 D3 }
  11. |                                                        |# P7 w  u% h0 X) D/ k3 C9 F
  12. |3 (GPIO4)                                  14|
    - ~5 y, V# \8 ]  I: F0 a2 K
  13. |                                                        |
    : i& Z7 T1 h1 H
  14. |4 (GPIO5)                        (DATA)13|
    ; @: y! P. L' A  I& u1 Y) V' `
  15. |                  STC15W204S                |
    - `( E8 J7 X7 R8 l  I: ?3 k3 M
  16. |5 (GPIO6)                   (LATCH)12|
    - s* `5 _& }' [% }  w
  17. |                                                        |
    5 e+ R" S" p5 I9 b" W  Q# x
  18. |6 (VCC)                         (CLK)11|
    ' v* A2 L7 h5 D; ]& r  S
  19. |                                                          |/ w( Q( z1 N- n2 @, n  s
  20. |7 (GPIO7)                         (TXD)10|* o. }% @% f/ L' o8 d/ {- Y% F! X5 G. ^
  21. |                                                        |
    - e7 B7 q- _) r, @
  22. |8 (GND)                         (RXD) 9|
    : ?. l2 Z: y& @( G
  23. *---------------------------*
    9 V9 y+ o7 r" h# x/ k. d1 T" G
  24. Fosc = 12MHz; k4 X# p: w; I% @" T2 o
  25. . v4 g% D! }0 X
  26. P1.0 -> 上
    2 [, F/ ?. _& q  V# C2 y" S' ]
  27. P1.1 -> 左
    0 m& n4 U: T! o9 e% y6 l' x6 b1 v
  28. P1.2 -> 下8 t4 q3 B$ E7 ]; C0 ^1 B/ ?
  29. P1.3 -> 右% D1 F; c: H1 j) B3 B+ P! Y  B* I
  30. P1.4 -> SEL
    $ n5 J3 r3 k& |  j
  31. P1.5 -> STA
    ( d- Y% h% R0 |+ x9 ?7 b  k& f
  32. P5.4 -> B
    * U: e- b$ K, G' @- N7 X
  33. P5.5 -> A
    ) F" s4 u7 L' s) \% ]

  34. : y9 i" C9 U1 u& k8 {; b5 d
  35. */' \1 A! s4 f  r
  36. ' }+ m6 U! d2 h% G0 n

  37. * z, l- W* j( a/ e- B+ X
  38. sbit CLK        = P3^2;7 b" I* q5 @6 c; x& z0 ?
  39. sbit LATCH        = P3^3;
    7 F5 x" i' G. a# i% e% A9 b
  40. sbit DATA        = P3^6;
    * v% S  `6 o) u4 l, H

  41. . l1 R- r1 o* q* d
  42. bit isReady = 0;+ `/ i% w% ~8 s1 p2 \9 z9 F
  43. static unsigned char key = 0;
    % v$ ^0 |. P# M- l7 Z$ s
  44. static unsigned char buf = 0;        // 双缓冲。这个缓冲区保存从P1和P5组合而来的键值
    ; d- W. T1 b9 M& C( X3 _3 O
  45. static unsigned char bufReady = 0;        // 双缓冲。这个缓冲区保存上面那个缓冲区的备份
    1 ]& `5 k4 X" A+ {- l
  46. static const unsigned char data mask[] = {0x80, 0x40, 0x10, 0x20, 0x01, 0x04, 0x02, 0x08};        // A B SELECT START UP DOWN LEFT RIGHT。为提升速度,这个表放到RAM中
    " j9 k, \. e0 x8 M
  47. static unsigned char idx = 0;
    / ^- M: C6 I' o0 b* \5 k

  48. : n, G; x' |0 a, k

  49. ' s# ]6 t% x' ~6 Y% C7 ?1 \& D
  50. static void GPIO_Init(){
    ! }+ F# }4 B# A' G$ U: F, U; J
  51.         // P1口和P5口用于接收并行信号,全部初始化为准双向,依靠内部弱上拉输出高电平
    : b3 N) B+ C; I# R
  52.         P1M0 = 0;
    2 ^1 {$ Q# O1 N' X7 u2 k
  53.         P1M1 = 0;
    7 i5 `7 V: E2 W( L) j# Q
  54.         P1= 0xFF;3 |6 R+ U+ @/ z) r( D
  55.         P5M0 = 0;- E6 e. G6 W' x  Q$ _
  56.         P5M1 = 0;
    0 M2 q3 j6 z! u7 |) }
  57.         P5= 0xFF;, f$ m, F6 |4 e  c" Y+ C7 \
  58.         // P3口初始化为准双向
    ( H- T# H) R( v' w( c4 R8 l
  59.         P3M0 = 0;* }: |1 o5 E# N( X; H
  60.         P3M1 = 0;
      f  y! F% {, a, l& {' t( B
  61.         P3 = 0xFF;
    $ q2 X! w* W8 X( n- u4 G3 P4 a
  62. }/ {7 R: s0 M) u; E

  63. " y) z' O7 ^6 E/ F: K6 O
  64. static void Interrupt_Init(){
    7 p5 Y3 O6 `6 E8 K* t# E
  65.         // INT0中断(CLK)触发类型为上升沿+下降沿# l1 Q. Y; y+ g; Q1 v
  66.         IT0 = 0;
    , _" y* m4 B: u6 W9 B
  67.         // 允许INT0中断: a/ \+ M7 ~0 V" k1 U1 v
  68.         EX0 = 1;. ]9 n$ I( o3 E* u# m: |
  69.         // INT1中断(LATCH)触发类型为上升沿+下降沿
    4 L! z9 u8 y' b! g3 u
  70.         IT1 = 0;  s, E4 ~3 T9 N/ s2 S" X4 o! p4 O
  71.         // 允许INT1中断% g! T, b8 \5 o; Z# \# w8 K9 |
  72.         EX1 = 1;
    0 c! O( h1 \# k2 t; T: B
  73.         // 开启全局中断, f) m8 X+ t, e" k
  74.         EA = 1;
    ' c! d7 M- w4 W/ s8 L' X" K
  75. }& A$ k" G1 W5 O

  76. 3 F$ {/ C1 Z& m, j5 ]! y
  77. static void INT0_Isr() interrupt 0{
    . y8 P. X$ n% A8 t8 d& R% n4 i: z
  78.         // 只有已经成功锁存才允许CLK移位* y4 x+ b$ F6 S" o1 }
  79.         if(isReady == 0)( _6 b4 D0 L3 z7 F& Q
  80.                 return;
    5 V% P  L1 i3 _6 b, J
  81.         // 读当前引脚电平,如果是低电平则说明是下降沿,此时直接忽略该中断
    3 w. z/ o$ `- Q  _3 t, w+ w2 f! v. H
  82.         if(CLK == 0)9 L$ s4 J7 S' A
  83.                 return;
    7 L4 W1 |" L8 m: c# k% v& U5 o- k
  84.         // CLK上升沿到来的时候,取锁存值的下一位输出
    - T/ l8 V* C3 t. s! P
  85.         idx++;* h$ c9 H$ `3 R
  86.         DATA = key & mask[idx];
    4 M  O! O, E! O. t/ M
  87.         // 如果已经完成7次移位,则一轮读取完成; G) _. _/ C. N2 |" Z4 J% ]
  88.         if(idx >= 7)3 P" ]2 Q6 L: k4 U, [9 D
  89.                 isReady = 0;
    1 U1 |( K" ]; k/ q0 R1 h0 {8 A
  90. }
    $ p4 r+ u' O8 q5 j1 N" z2 J) R
  91. 1 a7 u+ ~" l, ~: g0 @7 J+ c7 r% j& A
  92. static void INT1_Isr() interrupt 2{* G- D" R; e1 E3 G$ j" }4 ^
  93.         // 读当前引脚电平,如果是低电平则说明是下降沿,此时直接忽略该中断
    8 y$ }/ h  r9 ^; l, d
  94.         if(LATCH == 0)8 {# Q  k. C3 U! \  Y) N1 h0 e/ ?
  95.                 return;
    : ~2 [8 Y$ X2 J% B
  96.         // 当LATCH上升沿到来的时候,锁存所有按键状态,同时把键值A输出到DATA" R0 _6 l8 J# e, p8 W) C9 D# N( b# \
  97.         key = bufReady;: s  N- l4 |1 H) X7 e2 |( r
  98.         DATA = key & 0x80;//mask[0];        // 为了加速运算,直接取表中的值而不是读表
    8 `9 E. g! E' `1 S$ H" p
  99.         idx = 0;3 ^) b. z$ G6 h. C' q) a1 |; H! M
  100.         // 允许CLK进行移位# C' a, _  y/ N4 ~: C
  101.         isReady = 1;( {5 X0 D* c* v* V5 D& I
  102. }! z& [/ @9 c5 U5 L# O( q
  103. & n' k0 }; Q- g. c) m: a
  104. void main(){
    . m5 s# ?1 S8 o! f; Z$ E; k' |) F
  105.         GPIO_Init();+ z' y8 c+ ]9 m6 U& h( n3 M8 _4 ]
  106.         Interrupt_Init();  r3 d* e0 M7 ]" f& J( p- e/ R- B
  107.         ! b* F9 J* y) }
  108.         while(1){
    7 j3 g/ y7 c! V5 v
  109.                 //PCON |= 0x01;        // 进入省电模式
    1 ]  {0 v; g4 V' ~9 r- S2 m$ _
  110.                 //_nop_();
      a( A4 H  C' t6 i
  111.                 //_nop_();
    # m) n6 P6 n) ]& w/ D6 z
  112.                 //_nop_();
    1 ^3 V: u1 Y/ F0 x6 N
  113.                 //_nop_();3 k6 J% I! c/ W
  114.                 buf = ~((P1 & 0x3F) | ((P5 << 2) & 0xC0));4 n1 \- H2 h; B8 i) O8 i
  115.                 bufReady = buf;" X; e$ R% O: D1 |+ V* W
  116.         }" }% s, @: r9 `) F( M
  117. }- R, ^' p, g) V$ k4 f6 ^0 @0 B( w- J; B
复制代码
& K+ K1 p0 j" K% o: w4 Y
硬件参数配置无特殊要求,晶振频率选择12M即可。
; c: p& N  }1 @) b, V% ^, p: T, i: K6 J& ?& T9 a0 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
( G, E" Y* m! z/ B8 R& H# I不错的设计,想问一下楼主,FC的15针公头怎么解决?普通的公头太短了,插不进去FC的扩展接口。 ...
& C/ m& L# q& `* d. v9 c
坛友的改造方案
回复

使用道具 举报

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

使用道具 举报

发表于 2019-5-25 12:07:18 | 显示全部楼层
精彩,楼主动手强,也写得很详细。" B. s7 \* Z, n' Q
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, n4 X. h0 I- B
精彩,楼主动手强,也写得很详细。
! }( w5 D/ E' f2.4G方案是目前无线的最低延迟吗?

3 e7 q* c& R& f7 ^! ]: C我没用过其他无线手柄,所以实在不知道我自己做的这个手柄到底是不是最低延迟。, y( Y( \' B  S8 S6 U. a
不过根据网上的说法,延迟高低主要是由通信协议的复杂程度,以及数据传输速率决定的。这个模块虽然是2.4G无线模块,但由于协议很简单,所以延迟比较低。
$ |% B5 c$ t0 M5 p' _我用这个手柄玩一些ACT游戏,比如超级马里奥、忍者龙剑传、热血系列,完全感觉不到延迟,和游戏机自带的手柄没有任何区别。唯一的区别就是这个手柄是用火花山寨手柄改造的,外壳是垃圾回收塑料,粗糙+脆弱,导电橡胶弹性不佳,手感不是一般的差。
  o  N1 q/ z2 i0 v# A我手里还有十几张板子,等我有空了我再做一套,到时候买一个好一点的手柄改造。
回复

使用道具 举报

 楼主| 发表于 2019-5-29 16:56:14 | 显示全部楼层
ppad 发表于 2019-5-28 17:27
- I2 P9 v" t/ w/ ]. z/ G6 \给技术帝赞一个,有半成品发布吗,自己焊接改造就可以,编程实在不会啊 ...
" w4 [6 R9 Y! q) C0 U
很可惜,我手里没有多余的单片机了,LDO也找不到了,锂电池以及充电模块更是没有了。反正就是该用到的元件基本都没了,所以没法发布半成品。
" `" N- O, L- i+ [两个板子倒是有十几张剩余。
: g* A. ]" j7 \; q  T. Q你要是有USB转TTL串口板,完全可以自己买这两种单片机,然后我给你编译好的固件,你自己用串口板下载到单片机里面就行了。两个2.4G无线模块也得通过串口板用AT命令设置参数,不过好在我在设计电路的时候就已经预留好了串口,可以直接在线下载和在线设置参数。总的来说并不麻烦。
回复

使用道具 举报

 楼主| 发表于 2019-5-29 17:00:34 | 显示全部楼层
孙大师 发表于 2019-5-28 18:556 ^3 B- z- [$ F7 X- m- O
非常好,楼主是技术帝,到目前我都还没开发fc的无线套件,等空了,开发一套套件,等玩家自己组装。 ...
& [' T3 U2 a; Y" p8 F& f. Q
能得到孙大师的赞誉,不胜荣幸!. w( }3 d. V$ q+ @, X# m+ Y9 c$ E& W
不如开发一个多功能手柄,比如用SFC手柄改造,L/R键配合其他组合键可以用来切换2P~4P、调节连发速度、软重启等各种功能。接收端插到15PIN扩展口。
回复

使用道具 举报

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

本版积分规则

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

GMT+8, 2025-7-6 01:52 , Processed in 0.108112 second(s), 14 queries .

Powered by Discuz! X3.5

© 2001-2025 Discuz! Team.

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