找回密码
 注册

QQ登录

只需一步,快速开始

扫一扫,访问微社区

巢课
电巢直播8月计划
查看: 3|回复: 0
打印 上一主题 下一主题

[硬件] 吴坚鸿单片机程序风格赏析——(一)按键行列扫描与蜂鸣器

[复制链接]

551

主题

1470

帖子

3万

积分

EDA365管理团队

Rank: 9Rank: 9Rank: 9Rank: 9Rank: 9

积分
39487
跳转到指定楼层
1#
发表于 2019-9-27 15:07 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式

EDA365欢迎您!

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

x
(1)技术体会:在行列式扫描结构的薄膜按键里,干扰很大,按键扫描程序非常讲究,尤其是去抖动的处理。
6 y  j5 g; [6 Z& O$ q8 U- ^ (2)功能需求:每按一个按键,蜂鸣器就响一次。
" t. Y0 ^; l* N( j$ X (3)硬件原理:4 o0 B" G0 h: ~% b% \
(a)用4个IO来做2X2按键行列扫描,其中作为输入的2个IO口必须接上拉电阻20K左右。
# }6 t  t2 B- Z (b)用1个IO经过8050三极管来驱动有源蜂鸣器,有源蜂鸣器通电就一直响,断电就停止。而无源蜂鸣器是要靠断断续续的开关信号来驱动才能响,就是要频率来驱动。; I) E' a" R/ ?, v0 Q# I+ `
(4)源码适合的单片机IC18F4620,晶振为22.1184MHz# k5 e9 N3 X- q8 {) ?1 L
(5)源代码讲解如下:
' I% R$ M+ Q' A, Z9 e- A% ^* ]/ @ #include<pic18.h>         //包含芯片相关头文件9 P9 k) b" o1 J0 E
: I: r  G) u6 t" A+ _3 c! ^
//补充说明:吴坚鸿程序风格是这样的,凡是输出IO后缀都是_dr,凡是输入的//IO后缀都//是_sr9 s5 O8 V% Y- J0 D
8 I2 v4 T5 I) {
#define  beep_dr  LATA1  //蜂鸣器输出, j, A0 _. M- e7 ?& g

3 p( V/ k  ^% ^; {( b: h #define key_dr1 LATB3  //2X2按键行输出. B' j% x, U1 E: M/ n2 b3 x( P
#define key_dr2 LATB4 //2X2按键行输出0 A6 m5 ^# J! B6 r9 [! w

2 r( f3 _# }' T, G5 l( y! o #define key_sr1 RB6    //2X2按键行输入! j3 ]% r- `$ ^. l) [* \. l
#define key_sr2 RB7   //2X2按键行输入: n3 Z) F. c' w) m- V1 {) w2 D

2 H" w' D! F) Q //补充说明:吴坚鸿程序风格是这样的,凡是做延时计数阀值的常量# B' M& n0 r2 E) i) N5 v$ R) V+ ^
//前缀都用cnt_表示。0 ?3 W# G! Q9 b& S
#define cnt_delay_cnt1   25   //按键去抖动延时阀值
# {. m# V( Q& Y0 h! ~" N$ h& [2 V #define cnt_delay_cnt2   5    //按键行输出信号稳定的小延时阀值, x5 J& N: l- |0 x3 o6 C

6 g$ t$ E1 m% _" j #define cnt_voice_time   60  //蜂鸣器响的声音长短的延时阀值
. ^$ ^; f  \8 i: i void delay1(unsigned int de)  ;//小延时程序,时间不宜太长,因为内部没有喂看门狗
2 J* S, ~/ ^: ]7 b8 i0 |0 ~! G/ A1 I, S( |
//补充说明:吴坚鸿程序风格是这样的,凡是按键扫描函数都放在定时中
; V% s2 f7 ]' A& e" c  L# s //断里,凡是按键服务程序都是放在main函数循环里。有人说不应该把子程序//放在中断里,别听他们,信鸿哥无坎坷。! U3 H5 a) I4 X6 c
void key_scan();                         //按键扫描函数,放在定时中断里
' s$ N, p% g& h2 E: R0 {4 [8 S void key_service();                            //按键服务函数,放在main函数循环里# {: V. t" L" l( p

/ j  ^0 y! f, }# w* l3 s* ~, o5 x- o1 B5 s7 A
//补充说明:吴坚鸿程序风格是这样的,凡是switch()语句括号里面的变量名
  k7 W6 F& |" [  [( [2 ?7 f* P* M //后缀都用_step表示。) ]2 T" f6 `6 [! D
) l+ _( @2 y, |
unsigned char key_step=1;      //按键扫描步骤变量,在switch()语句的括号里
2 _) K5 Q& I1 ]7 U& H //补充说明:吴坚鸿程序风格是这样的,凡是按键或者感应输入的自锁变量名4 X* @& N; n7 S  z( Z5 N
//后缀都用_lock表示。
+ h! M/ U( w  z/ K2 j7 t. g# l9 V unsigned char key_lock1=0;   //按键自锁标志8 F) J, p7 C2 c2 Q3 G& L, Y
//补充说明:吴坚鸿程序风格是这样的,凡是计数器延时的变量) r. v) N4 Z3 M8 k3 X7 v( }
//后缀都用_cnt表示。
! H0 q& e' C3 I  [+ R+ o3 z. R unsigned int  delay_cnt1=0;     //延时计数器的变量% v# ^0 b" V2 i
unsigned int  delay_cnt2=0;     //延时计数器的变量1 q7 Q* |5 J  Z
unsigned int voice_time_cnt;        //蜂鸣器响的声音长短的计数延时
+ Q" G4 ^" k. }/ E1 Z2 o; B1 V
//补充说明:吴坚鸿程序风格是这样的,凡是做类型的变量的分类4 K/ o  }  r) f# B1 i/ m
//后缀都用_sec表示。
- S# ^* Y# o8 e5 I. R! F1 ? Unsigned char key_sec=0;  //哪个按键被触发
1 U1 h, p/ z$ R! F- D6 i2 }. e% v$ n9 v- h
//主程序' l, i  r' c+ G: l  g3 c
main()
0 j2 T; a' e8 n! {; [' v0 K {
# }0 i9 Y5 B3 M  J/ P( S6 J; L ADCON0=0x00;  
* A0 ?4 j+ v& D ADCON1=0x0f;                               //全部为数字信号
/ T$ B* ]0 I' Y- U$ R2 d5 l5 J: Q  t     ADCON2=0xa1;                               //右对齐
" X/ _$ O0 w& H% v1 J     RBPU=0;                                      //上拉电阻% i  Z' c" `1 N7 u6 K* }( |1 f( u
     SSPEN=0;                                    //决定RA5不作为串口' ^0 U* E/ _) x  E& i- {
9 w9 B) W4 e' L# t- @! \& n
     TRISB3=0;            //配置按键行扫描IO为输出
6 a9 \- y: I/ q. s     TRISB4=0;           //配置按键行扫描IO为输出% ^: F  y/ x- d3 e+ u
     TRISB6=1;           //配置按键列扫描IO为输入0 Q: h* h7 _" z+ B& u$ L8 P
     TRISB7=1;           //配置按键列扫描IO为输入% l: c" x5 l- g$ t3 F! Q
8 T( \0 b- d" i

* j# a" L6 U3 t3 j. z4 ]     T1CON=0x24;     //定时器中断配置
+ S; {5 H  w9 ~  n8 b     TMR1H=0xF5;
9 ^5 L; g& W: _! D! ]8 s: Q     TMR1L=0x5F;
" G4 U# v" e2 l5 V3 D3 O0 x     TMR1IF=0;! W# c" S, K( Z+ U& u9 v2 s9 Z, F1 a
     TMR1IE=1;
8 X8 {1 `# B6 e# L$ z9 F9 `     TMR1ON=1;
: S2 D8 i' [8 S+ t+ |     TMR1IE=1;9 P8 H* H" e* ]; S0 D+ A
//补充说明,以上的内容为寄存器配置,每种不同的单片机会有点差异,, h  M! \* u5 L, y1 G
//大家不用过度关注以上寄存器的配置,只要知道有这么一回事即可. G/ `( V- u: [1 w
+ b7 [4 m8 p7 c" w- O, t+ v7 c
     beep_dr=0;                               //关蜂鸣器,上电初始化IO  r, h7 ]8 E9 t+ i+ Y1 L
; ]- g" U* \  \1 V' g( ?: {
    while(1)    / k7 k/ |; R3 g
    {* A; O" Z5 ?- P: o
                      CLRWDT(); //喂看门狗,大家不用过度关注此行$ W; P. @/ U% B: k' m1 L$ h8 m
                 key_service();        //按键服务
8 Q! B1 e. b8 c" X3 v( y0 d3 B }$ a' A* I6 |2 h6 C7 w' I5 M
' g* c" @8 K; x8 u: X
}
4 }" i$ K" _+ g1 F. f8 J. B        ( @- j' L5 `$ M  i; y# m
* N- T% m3 `0 @0 P1 G
void key_scan()                                //按键扫描函数$ l2 X) u$ f2 l, O
{  
8 A1 X# T& Y2 }/ ^6 A7 Y1 t     //补充说明:如果中断一次就把所有的按键都扫描完,中断占用的时间片就会太多,势//必会影响main函数里其他子程序的运行,为了避免一口气把所//的按键都扫描完,此' N+ E. J! E: L/ y; W
//处用switch语句把4个按键分成2等分,一次中断只扫描2个按键
6 m8 U% r1 ^" F" [1 ] switch(key_step)    //按键扫描步骤,
/ s- L1 q- O1 W, p/ H {
9 ]. O; O) W( _" }# s; {         case 1:   //扫描1号键,2号键$ z- C' v! k4 t: _8 q+ y7 w
                 key_dr1=0;      //按键行扫描输出第一行低电平' ^. V; o: B* y) m* o" }
                 key_dr2=1;2 s- k" j2 z, p" z4 _  r
                 delay_cnt2=0;  //延时计数器清零
) ^( F' s3 d! I                 key_step++;     //切换到下一个运行步骤8 U( [, X" Q3 ~! y  @
                 break;: G: |8 {3 X( l3 G
         case 2:0 L' }" [' Z. f# G4 ]9 Z3 p( e) N
                 delay_cnt2++;
7 _) W/ N1 U1 j                 if(delay_cnt2>cnt_delay2) //小延时,但不是去抖动延时,替代一直受网友争议的delay1(40)   
7 Z- ?& Q, `. o! s                 {
" r7 y- o* [6 q$ {% E; ~: t8 {- N6 {" h                        delay_cnt2=0;
3 L' [- D7 d+ u/ u                        key_step++;     //切换到下一个运行步骤5 D* ]+ C2 `$ Q4 A( z
                 }" ?& [, D0 S$ l- h5 |' A/ j* v
                 break;! z9 }9 _. x( u% O7 C) }
         case 3:
) o) r, o( o0 ]  }                 if(key_sr1==1&&key_sr2==1), U1 D& c; b+ b" U2 N) y: c
                 {   //如果没有按键按下,则2个IO输入都是高电平
' {% \4 F: O( m$ A0 i                         key_step++; //如果没有按键按下,下一个中断扫描下2个9 `/ o$ N, {) E0 E
//按键
3 j+ l- I& w$ K key_lock1=0;  //按键自锁标志清零
4 d. n3 `8 F! ~                          delay_cnt1=0; //按键去抖动延时计数器清零,此行非常巧妙        0 S# W+ M$ L$ Z+ v7 z. l
) R$ ~( j9 x0 T. k6 ?: q; O
                   }8 q: [$ Y9 }. S  v: `3 Q" c
Else   if(key_sr1==0&&key_sr2==1&&key_lock1==0)
7 H" {. d8 N( c# o. d                  {     // key_lock1按键自锁,避免按键一直触发,下降沿有效- Y; R' F8 F5 N2 s2 R  W# y
                         ++delay_cnt1;  //延时计数器
6 A7 M$ L/ t8 t //补充说明:有按键触发之后,不要马上响应,要延时一段时间去抖动,此处本人设计非常* n7 e2 \/ i( |* L& u7 m/ }& Y( [
//巧妙,很多人仅仅知道按键延时的时候要保证还能去处理别的程序,这样是还不够的,' Z1 U) [4 g7 M6 G
//在延时去抖动的时候,还必须要监控延时这段时间里,按键IO输入口是否会由于受到某//种干扰突然由低变成高,如果一旦变成高,那么延时计数器delay_cnt1必须重新清零, u2 c8 Z' l& ?" A
//我当年就是因为这样处理,把卖给富士康100台受干扰死机的设备修好了,老板马上9 x4 m1 D5 B& D$ u# f: t
//给我加薪1000元。
) L* ~: ]# ^8 x) r' X5 l% h6 c' W. o                         if(delay_cnt1>cnt_delay_cnt1)  //延时计数器超过一定的数值
. k# u- s8 ?! P* _7 Q                         {
% Z9 H+ f. O0 n- W. x/ `9 c6 N                              delay_cnt1=0;
  b' f* ~6 m; l- [( T- U$ m5 b key_lock1=1;  //自锁按键置位,避免一直触发,只有松开按键,, o. X/ K/ x. Q: [
//此标志位才会被清零$ {: I; D2 r6 D% u' G
                                        key_sec=1;         //触发1号键1 V) v3 x8 T( `/ z8 Z1 e& N- }: V! O+ l; v
                         }
/ N4 Y! U, P7 P0 l, ^' t                                         . k+ s0 k8 d- f2 Q' u6 H2 z
                 }/ |' a7 Y; S9 [( e
                 else if(key_sr1==1&&key_sr2==0&&key_lock1==0)
* z% H$ u& t9 s/ _& m9 ]                 {6 Y. Q& y. m& Q7 k, ?& Y7 R
                         ++delay_cnt1;
6 [: X0 J! U3 @  \                          if(delay_cnt1>cnt_delay_cnt1)
- J' o. J8 F+ F7 Y/ p5 B5 L6 R  p                          {2 V) R- o; b: R" R
                                  delay_cnt1=0;
* Z6 C. w8 ?5 _6 K3 ` key_lock1=1;  //自锁按键置位,避免一直触发
! V) F( x( ?6 M1 i0 x1 y                                           key_sec=2;         //触发2号键
9 V5 ?; F5 n6 [4 j1 O; L                                                
* N: c6 J/ G5 x, }' N+ s; E                         }        
" \- Y4 }& t2 z                      }
- s+ _* p' ?: P6 I0 J/ G              break;, F: U8 @1 s9 z: `! ?8 A& b( a9 k
         9 m. G7 _; v  ~- y
         case 4:       //扫描//扫描3号键,4号键* ]$ A$ J( b' i  \& k- Q
                 key_dr1=1;     
( \# |, b. g& [) `& Q/ l5 r$ ~                 key_dr2=0;   //按键行扫描输出第二行低电平3 a4 `- I6 F% L! L9 _) Q
                 delay_cnt2=0;  //延时计数器清零
, U+ a+ W, V5 d: R" s                 key_step++;     //切换到下一个运行步骤
: o4 r% K4 }; F! f5 U/ }& d                 break;4 y1 W7 `! P4 P, ?. j. F4 H
         case 5:4 K3 g7 f; }" z$ M2 C4 a, V
                 delay_cnt2++;4 g" x" l$ G3 l2 S# q
                 if(delay_cnt2>cnt_delay2) //小延时,但不是去抖动延时,替代一直受网友争议的delay1(40)    $ x" O2 k) r* r! b
                 {
/ F% E9 x( H4 \1 l( U6 j5 {: W% O                        delay_cnt2=0;: X$ e2 r8 a- l" `$ _: r+ [
                        key_step++;     //切换到下一个运行步骤" B5 \0 P' k: c, s+ ^' b
                 }0 {9 p; D- p: F5 A7 P1 L
                 break;5 S- S* i3 U* M1 _" V
         case 6:% K3 q% x2 c8 _+ A; ]
                 if(key_sr1==1&&key_sr2==1)
2 J# M. q. X! P+ U" ?. r8 u                 {   
1 _* d( f; g% ?9 E                         key_step++;
2 H; ^2 r" I* q# u key_lock1=0;  2 e. c0 I  Z2 _0 y; i! ?5 {3 Y
                          delay_cnt1=0;
9 J$ j% j$ j3 `+ Y2 R
: N' g3 E9 X4 b* c                   }
% b$ j% p: d; {' h3 y, E Else   if(key_sr1==0&&key_sr2==1&&key_lock1==0)
2 |. i+ \- q+ j! d+ |3 \1 Y! i. y                  {     , f% e( r; D2 v) ]& N6 F7 d
                         ++delay_cnt1;
! ^  }# n+ u4 R8 A2 P: P                         if(delay_cnt1>cnt_delay_cnt1) & C+ x' a1 g/ k+ P: f) {7 \: V3 j
                         {
9 y  r, v- `2 Q/ Z) R                              delay_cnt1=0;1 I, Y( k) {2 r# p3 O  r. I4 \
key_lock1=1;  
  ]9 J# b2 p( [+ i& v                                        key_sec=3;         //触发3号键
3 Y5 M% E6 ~, N+ h/ u7 F# S; t3 Q" i, r                         }
& ?, R7 j0 Y1 i5 `( H                                         2 w# l+ J' K: x/ ~  {5 u5 u
                 }
, K5 U- s% p! d* u; g1 X                 else if(key_sr1==1&&key_sr2==0&&key_lock1==0)- s# y, F& v7 w9 W# z7 X
                 {( b4 w% F, z6 B, j% m
                         ++delay_cnt1;( G# ]  L" q4 p& {
                          if(delay_cnt1>cnt_delay_cnt1)/ {5 C/ k/ p" \3 Q. n
                          {/ H8 f8 d3 L/ f% ]$ p2 L
                                  delay_cnt1=0;
& h% Y3 F; ?  N2 {9 Y3 E0 r* `" } key_lock1=1;  //自锁按键置位,避免一直触发
: |  M+ _6 T9 m/ H: ~. x' A' W+ |                                           key_sec=4;         //触发4号键6 p% B1 y9 \- W
                                                 8 @3 |8 }9 h9 f6 w4 g
                         }        
% W2 `1 p& @1 E2 A0 t                      }
1 `; ~4 T2 A: x: ]1 t* O1 V              break;
8 C, U( k0 @3 E+ h1 D      }. l/ K$ k+ |$ v( V+ Q
if(key_step>6)   //第1组按键与第2组按键反复轮流扫描
, D* \. c  j! I8 P* l {% C! Y' ^) }4 M0 {5 q
         key_step=1;        
& I5 a" B1 R4 d/ z }' N. n9 Z  a* U' m7 [) l: R
}) H* X& V" I$ E. d- r% h# d- W. D5 i

! e6 I; y1 g- Z8 r void key_service()                //按键服务函数
9 T9 _7 ~+ Q" \( \3 } {
" Y3 u1 |- p' u+ E2 }+ s" k/ T         switch(key_sec)                //按键服务状态切换: N: f. u9 Q* e; D7 ]3 A, D
         {
1 k, @0 {8 e& Q" d- u- w! s  A( u                 case 1:// 1号键
/ l# o$ X3 j! h$ {3 |; [0 \0 q; i# s! h! D  H1 O3 f
. T/ D' b! I2 q& a( }  V6 S
// 补充说明:voice_time_cnt只要不为0蜂鸣器就会响,中断里判断voice_time_cnt不为0% |- D$ e  u6 F( b: t; @
//时,会不断自减,一直到它为0时,自动把蜂鸣器关闭/ {$ ]5 B" h- h8 |! L) f8 c
                                   voice_time_cnt= cnt_voice_time;    //蜂鸣器响“滴”一声就停; x) s2 r# B. w% K6 d
                                                                                          
# _& s7 D, K8 u                         key_sec=0;   //相应完按键处理程序之后,把按键选择变量清零,0 C8 T* u* ]- i( h
//避免一直触发  R+ [/ T; }' W
                         break;        
! J% b# f' y0 |* o                 case 2:// 2号键
4 u* z5 m1 @1 v5 y! I                                  voice_time_cnt= cnt_voice_time;    //蜂鸣器响“滴”一声就停  i  Z0 ], H9 U: k2 c4 h
                         key_sec=0;   //相应完按键处理程序之后,把按键选择变量清零,
" M; [5 }7 d5 Y9 q) l& @ //避免一直触发1 }9 [7 r9 r" n6 u# v( R
                         break;        4 D% ~# X+ `3 n3 q2 i
                 case 3://3号键
7 {' X: }5 \, r7 Z7 L( y1 R- l6 Q
                                  voice_time_cnt= cnt_voice_time;    //蜂鸣器响“滴”一声就停
/ j7 X9 E: a. E8 H+ T                         key_sec=0;   //相应完按键处理程序之后,把按键选择变量清零,# L6 Q* {7 M8 D
//避免一直触发" Z4 N% [& R" I7 q1 y5 M
                         break;        : X/ K( ]7 ^2 ]7 y
                 case 4://4号键4 q+ K. q0 e7 y! @) g1 _
$ m# F: A  C' f: `+ N+ X
                                  voice_time_cnt= cnt_voice_time;    //蜂鸣器响“滴”一声就停' G0 I+ i$ q0 j5 |$ V
                         key_sec=0;   //相应完按键处理程序之后,把按键选择变量清零,. t' Y6 \- `# G, h0 [9 e& n! g
//避免一直触发
( m* O: \! a" L0 ~6 P                         break;        
  r3 A0 g& [* Q  P# I/ G5 ]) G8 |) |$ J! K% ^5 A
) }# L3 f! Z" Z6 X2 C5 a6 K0 ^0 U
4 \- p& Z) S7 x1 H
                         5 A) Y( N1 |8 J# D1 d# B
         }               
' R) O# Q# G/ l$ b$ ? }
& K& p# B. v8 }6 Z
1 o% i+ r% y( q) f% T# h: C  S. w! G6 s& Q

6 s2 ~9 b! h  Y6 r4 l- q4 D; {* W3 F3 j+ L3 A0 F3 l3 c/ y
//中断
1 S" v, m, O4 ?3 a+ r void interrupt timer1rbint(void)
* v6 [, w% g# D {3 J$ H$ W) ]4 p. l7 O4 ?
     if(TMR1IE==1&&TMR1IF==1)    //定时中断
" x& P$ U' b7 R  Q9 I" w* i7 }         {
! Y; e; a; O" O: V/ t         
7 I# [; e# f* @3 u. k# v                TMR1IF=0;     //定时中断标志位关闭9 S0 _0 S3 x; i: f: p! {& |
                 TMR1ON=0;    //定时中断开关关闭3 f) F( P/ i9 F2 A3 L, \8 m1 V

: Y7 P* B3 Q- M                  key_scan();                    //按键扫描函数2 B  ?: A" Q8 y  ~7 o9 F' z
       if(voice_time_cnt)                       //控制蜂鸣器声音的长短0 C6 T4 y& g. z
                  {! D, z$ Z- }6 Q, E
                         beep_dr=1;         //蜂鸣器响
/ I  H; \! d9 G' a                       --voice_time_cnt;        //蜂鸣器响的声音长短的计数延时
2 K% \$ S/ `9 k- d8 T! h& I5 Q                  }
- v# y" b3 l- J8 ^                 else # ]  \, r/ d7 o8 @, N
                 {' Z3 J% }! J2 M& W: V
beep_dr=0;      //蜂鸣器停止; V3 W. v, B; c% x+ |) q
                 }. ?; e2 r& c6 T0 a; c5 ~
       TMR1H=0xF5;     //重新设置定时时间间隔
6 y2 ~1 g0 a. M; v# @       TMR1L=0x5F;+ ^. W  z4 h/ M$ U% V
       TMR1ON=1;        //定时中断开关打开
/ v& I& y% x( h0 q* }     }
7 G7 r- _% J2 V6 q0 r& w4 t/ n }+ y; `" A, z& v" i- X# q
) p( O/ G$ d9 A! C! s" t$ C: d
# R  n3 H# V1 R1 a

  Z( Z' q  s0 n& ~4 H
5 c6 ~( d5 K. M0 I+ g, w9 n void delay1(unsigned int de)! Y% J% |4 B+ Y
{
# f; s1 y9 k" x/ w7 a' [( V5 H         unsigned int t;& O* H& T9 r5 K
         for(t=0;t<de;t++);
/ U/ Y$ v2 j6 p }2 }3 z1 ]8 m+ d/ p2 v3 ?  j  k

4 _, \! D+ `3 l' u' _: m# i0 f; e3 W' ]9 E. y
(6)小结:
" I5 b% x7 q  }2 S- y  i3 K3 O3 b   以上是我常用的编程结构。后续我做的所有项目基本上是这样一种编程结构。这一节技术上要特别重视按键扫描。有按键触发之后,不要马上响应,要延时一段 时间去抖动,此处本人设计非常巧妙,很多人仅仅知道按键延时的时候要保证还能去处理别的程序,这样是还不够的,在延时去抖动的时候,还必须要监控延时这段 时间里,按键IO输入口是否会由于受到某种干扰突然由低变成高,如果一旦变成高,那么延时计数器delay_cnt1必须重新清零,我当年就是因为这样处 理,把卖给富士康100台受干扰死机的设备修好了,老板马上给我加薪1000元。(未完待续下一节)
分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友 微信微信
收藏收藏 支持!支持! 反对!反对!
您需要登录后才可以回帖 登录 | 注册

本版积分规则

关闭

推荐内容上一条 /1 下一条

巢课

技术风云榜

关于我们|手机版|EDA365 ( 粤ICP备18020198号 )

GMT+8, 2025-4-5 07:19 , Processed in 0.057698 second(s), 32 queries , Gzip On.

深圳市墨知创新科技有限公司

地址:深圳市南山区科技生态园2栋A座805 电话:19926409050

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