《单片机C语言学习好资料.pdf》由会员分享,可在线阅读,更多相关《单片机C语言学习好资料.pdf(97页珍藏版)》请在taowenge.com淘文阁网|工程机械CAD图纸|机械工程制图|CAD装配图下载|SolidWorks_CaTia_CAD_UG_PROE_设计图分享下载上搜索。
1、前言.错误!未定义书签。基础知识:单片机编程基础.2第一节:单数码管按键显示.1 3第二节:双数码管可调秒表 24第三节:十字路口交通灯 27第四节:数码管驱动.35第五节:键盘驱动.40第六节:低频频率计.6 8第七节:电子表.7 9第八节:用行口应用.86基础知识:单片机编程基础单片机的外部结构:1、D I P 40 双列直插;2、P O,P L P 2,P 3 四个8 位准双向I/O 引脚;(作为I/O 输入时,要先输出高电平)3、电 源 V C C (P I N 40)和 地 线 G N D(P I N 20);4、高电平复位 RE SE T (P I N 9);(1 0 u F电容接
2、V C C 与 RE SE T,即可实现上电复位)5、内置振荡电路,外部只要接晶体至 XI (P I N 1 8)和 XO (P I N 1 9);(频率为王频的1 2倍)6、程序配置E A(P I N 31)接高电平V C C;(运行单片机内部RO M 中的程序)7、P 3 支持第二功能:RXD、T XD、I N T O、I N T I、T O、T 1单片机内部I/O部件:(所为学习单片机,实际上就是编程控制以下I/O部件,完成指定任务)1、四个8 位通用I/O 端口,对应引脚 P O、P K P 2 和 P 3;2、两 个 1 6 位定时计数器;(T M O D,T C O N,T L O
3、,T H O,T L L T H 1)3、一个串行通信接口;(SC O N,SBU F)4、一个中断控制器;(I E,I P)针 对 AT 89 C 5 2单 片 机,头文件AT 89 x5 2.h 给出了 SFR特殊功能寄存器所有端口的定义。教科书的1 6 0 页给出了针对M C S5 1 系列单片机的C 语言扩展变量类型。C 语言编程基础:1、十六进制表示字节0 x5 a:二进制为 o i o no i O B;0 x6 E 为 o no ni o。2、如果将一个1 6 位二进数赋给一个8 位的字节变量,则自动截断为低8位,而丢掉高8 位。3、+va r表示对变量va r先增一;va r一
4、表示对变量后减一 o4 x I=O xO f;表示为 x=x O xO f;5、T M O D =(T M O D&O xf O )|0 x0 5;表 示 给 变 量 T M O D 的低四位赋值0 x5,而不改变T M O D 的高四位。6、Wh i l e(1 );表示无限执行该语句,即死循环。语句后的分号表示空循环体,也就是;在某引脚输出高电平的编程方法:(比如Pl.3 (PI N4)引脚)tti n c l ud e /该头文档中有单片机内部资源的符号化定义,其中包含PL 3vo i d m a i n(vo i d )/vo i d 表 示没有输入参数,也没有函数返值,这入单片机运行
5、的复位入口Pl _ 3 =1;/给 Pl _ 3 赋值 L引脚P1.3 就能输出高电平V C CW hi l e (1 );死 循 环,相当L OOP:go to L OOP;注意:P 0的每个引脚要输出高电平时,必须外接上拉电阻(如4K7)至VCC电源。在某引脚输出低电平的编程方法:(比如P2.7 引脚)tti n c l ud e 该头文档中有单片机内部资源的符号化定义,其中包含P2.7vo i d m a i n(vo i d )/vo i d 表 z j 没有输入参数,也没有函数返值,这入单片机运行的复位入口P2 _ 7 =0;/给 P2 _ 7 赋值 0,引脚P2.7就能输出低电平G
6、 NDW hi l e(1 );/死 循 环,相当L OOP:go to L OOP;在某引脚输出方波编程方法:(比如P 3.1引脚)tti n c l ud e /该头文档中有单片机内部资源的符号化定义,其中包含P3.1vo i d m a i n(vo i d )/vo i d 表 示没有输入参数,也没有函数返值,这入单片机运行的复位入口W hi l e(1 )/非零表示真,如果为真则执行下面循环体的语句P3 _ l =1;/给 P3 _ l 赋值 L引脚P3.1就能输出高电平V C CP3 _ l =0;给 P3 _ l 赋值 0,引脚P3.1就能输出低电平G ND)由于一直为真,所以不
7、断输出高、低、高、低,从而形成方波将某引脚的输入电平取反后,从另一个 引 脚 输 出:比如 P 0.4 =N O T(P l.1)tti n c l ud e /该头文档中有单片机内部资源的符号化定义,其中包含P0.4和PL 1vo i d m a i n(vo i d )/vo i d 表 示没有输入参数,也没有函数返值,这入单片机运行的复位入口Pl _ l =1;/初始化。Pl.1 作为输入,必须输出高电平W hi l e(1 )非零表示真,如果为真则执行下面循环体的语句i f(Pl _ l =1 )读 取Pl.h 就是认为Pl.1 为输入,如果P1.1 输入高电平V C C P0 _ 4
8、 =0;/给 P0 _ 4 赋值0,引脚P0.4 就能输出低电平G NDe l se /否则Pl.1 输入为低电平G ND/P0 _ 4 =0;/给P0 _ 4 赋值0,引脚P0.4 就能输出低电平G ND P0 _ 4 =1;/给 P0 _ 4 赋值L 引脚P0.4 就能输出高电平V C C /由于一直为真,所以不断根据PL 1的输入情况,改变P0.4的输出电平将某端口8个引脚输入电平,低四位取反后,从另一个端口 8个引脚输出:(比如 P2 =NOT(P3 )tti n c l ud e 该头文档中有单片机内部资源的符号化定义,其中包含P2和P3vo i d m a i n(vo i d )
9、/vo i d 表 示没有输入参数,也没有函数返值,这入单片机运行的复位入口P3 =Oxff;/初始化。P 3作为输入,必须输出高电平,同时给P3口的8 个引脚输出高电平W hi l e(1 )/非零表示真,如果为真则执行下面循环体的语句 取反的方法是异或1,而不取反的方法则是异或0P2 =P3 0 x0 f/读取P3,就是认为P3 为输入,低四位异或者1,即取反,然后输出)由于一直为真,所以不断将 P3 取反输出到P2)注意:一个字节的8位D7、D6至DO,分别输出到P3.7、P3.6至P3.0,比如 P3=0 x0f,则 P3.7、P3.6、P3.5、P 3.4四 个 引 脚 都 输 出
10、低 电 平,而P3.3、P3.2、P3.1、P3.0 四个引脚都输出高电平。同样,输入一个端口P2,即是将P2.7、P2.6至P2.0,读入到一个字节的8位D7、D6至DO。第一节:单数码管按键显示单片机最小系统的硬件原理接线图:1、接 电 源:V C C (PI N4 0 )、G ND(PI N2 0)o加接退耦电容O.l uF2、接晶体:X 1(PI N1 8)、X 2(PI N1 9)。注意标出晶体频率(选用1 2 M H z),还有辅助电容3 0 p F3、接复位:RE S (PI N9)O接上电复位电路,以及手动复位电路,分析复位工作原理4、接配置:E A (PI N3 1)o说明原
11、因。发光二极的控控制:单片机I/O输出将一发光二极管L E D 的正极(阳极)接 PL 1,L E D 的负极(阴极)接地G ND o只要PL 1 输出高电平V C C,L E D 就正向导通(导通时L E D 上的压降大于I V),有电流流过L E D,至发L E D 发亮。实际上由于Pl.1高电平输出电阻为1 0 K,起到输出限流的作用,所以流过 L E D 的电流小于(5 V T V)/1 0 K 二0.4 m A o 只要Pl.1 输出低电平G ND,实际小于0.3 V,L E D 就不能导通,结果 L ED不亮。开关双键的输入:输入先输出高一个按键K EY _ ON 接在PL 6 与
12、 GN D之间,另一个按键K EY _ OF F 接 PL 7 与GN D之间,按 K EY _ ON 后 L ED亮,按K EY _ OF F 后 L ED灭。同时按下L ED半亮,L ED保持后松开键的状态,即ON亮 OF F 灭。t t in c l u d e t t d e fin e L ED Pl /用 符 号L ED 代替 Pl _ lt t d e fin e K EY _ ON Pr6/用符号K EY ON 代替 Pl 6t t d e fin e K EY _ OF F P7/用 符号 K EY _ OF F 代替 Pl _ 7v o id ma in (v o id )
13、单片机复位后的执行入口,v o id表示空,无输入参数,无返回值(K EY _ 0 N=1;/作为输入,首先输出高,接下K EY _ 0 N,Pl.6则接地为0,否则输入为1K EY _ 0 F F =1;/作为输入,首先输出高,接下K EY _ 0 F F,P L 7则接地为0,否则输入为1W hil e(1 )/永远为真,所以永远循环执行如下括号内所有语句if(K EY _ ON=O)L ED=1;/是K EY _ ON 接下,所示PL 1 输出高,L ED亮if(K EY _ OF F=O)L ED=O;/是K EY _ OF F 接下,所示Pl.1 输出低,L ED灭 /松开键后,都不
14、给L ED赋值,所以L ED保持最后按键状态。/同时按下时,L ED不断亮灭,各占一半时间,交替频率很快,由于人眼惯性,看上去为半亮态数码管的接法和驱动原理一支七段数码管实际由8 个发光二极管构成,其中7个组形构成数字8的七段笔画,所以称为七段数码管,而 余 下 的1个发光二极管作为小数点。作为习惯,分别给8个发光二极管标上记 号:a,b,c,d,e,f,g,ho对应8的顶上一画,按顺时针方向排,中间一画为g,小数点为h。我们通常又将各二极与一个字节 的 8 位对应,a (DO),b (DI),c (D2),d (D3),e (D4),f(D5),g(D6),h(D7),相应 8 个发光二极管
15、正好与单片机一个端口 P n的8个引脚连接,这样单片机就可以通过引脚输出高低电平控制8个发光二极的亮与灭,从而显示各种数字和符号;对应字节,引脚接法为:a(Pn.0),b (Pn.1),c (Pn.2),d (Pn.3),e (Pn.4),f(Pn.5),g(Pn.6),h(Pn.7)o显示字符共阴极段选码其阳极段选码显示字符共阴极段选码共阳极段选码03FHC0HC39HC6H106HF9HD5EHA1H25BHA4HE79H86H34FHB0HF71H84H466H99HP73H82H56DH92HU3EHC1H67DH82Hr31HCEH707HF8Hy6EH91H87FH80H8FFH0
16、0H96FH90H“灭”00HFFHA77H88HB7CH83H如果将8个发光二极管的负 极(阴极)内接在一起,作为数码管的一个引脚,这种数码管则被称为共阴数码管,共同的引脚则称为共阴极,8个正极则为段极。否则,如果是将正 极(阳极)内接在一起引出的,则称为共阳数码管,共同的引脚则称为共阳极,8个负极则为段极。以单支共阴数码管为例,可将段极接到某端口 Pn,共阴极接GN D,则可编写出对应十六进制码的七段码表字节数据如右图:1 6键码显示的程序我 们 在P 1端口接一支共阴数码管SL ED,在P2、P3端口接1 6个按键,分别编号为K EY _ O、K EY _ 1到K EY _ F,操作时只
17、能按一个键,按 键 后SL ED显示对应键编号。t t in c l u d e t t d e fin e SL ED Plt t d e fin e K EY 0 P2 Pttdefine KEY_1 P2ttdefine KEY_2 P22ttdefine KEY_3 P23ttdefine KEY_4 P2Nttdefine KEY_5 P2ttdefine KEY_6 P2飞ttdefine KEY_7 P2Mttdefine KEY_8 P3飞ttdefine KEY_9 P3ttdefine KEY_A P32ttdefine KEY_B P33ttdefine KEY_C P3
18、Nttdefine KEY_D P35ttdefine KEY_E P3飞ttdefine KEY F P3/Code unsigned char Seg7code16二/用十六进数作为数组下标,可直接取得对应的七段编码字节/0 1 2 3 4 56 7 8 9 A bC d E F0 x3f,0 x06,0 x5b,0 x4f,0 x66,0 x6d,0 x7d,0 x07,0 x7f,0 x6f,0 x77,0 x7c,0 x39,0 x5e,0 x79,0 x71;void main(void)(unsigned char i=0;/作为数组下标P2=Oxff;/P2作为输入,初始化输出
19、高P 3=O x f f;/P 3作为输入,初始化输出高W h i l e (1)i f(K E Y _ O =0)i=0;i f (K E Y _ 1=0)i=l;i f(K E Y _ 2=0)i=2;i f (K E Y _ 3=0)i=3;i f(K E Y _ 4=0)i=4;i f (K E Y _ 5=0)i=5;i f(K E Y _ 6=0)i=6;i f (K E Y _ 7=0)i=7;i f(K E Y _ 8=0)i=8;i f (K E Y _ 9=0)i=9;i f (K E Y A=0)i=0 x A;i f(K E Y _ B=0)i=O x B;i f(K
20、E Y _ C =0)i=O x C;i f (K E Y _ D =0)i=O x D;i f (K E Y E =0)i=O x E;i f (K E Y F =0)i=O x F;S L E D =S e g 7C o d e i ;开始时显示3根 据i取应七段编码第二节:双数码管可调秒表解:只要满足题目要求,方法越简单越好。由于单片机I/。资源足够,所以双数码管可接成静态显示方式,两个共阴数码管分别接在P 1(秒十位)和 P 2(秒个位)口,它们的共阴极都接地,安排两个按键接在P 3.2(十位数调整)和 P 3.3(个位数调整)上,为了方便计时,选用12M H z 的晶体。为了达到精确
21、计时,选用定时器方式2,每计数250重载一次,即250u s,定义一整数变量计数重载次数,这样计 数 4000次即为一秒。定义两个字节变量S 10和 S 1分别计算秒十位和秒个位。编得如下程序:t t i n c l u d e C o d e u n s i g n e d c h a r S e g 7c o d e 16 二/用十六进数作为数组下标,可直接取得对应的七段编码字节/0 1 2 3 4 56 7 8 9 A bC d E F0 x3f,0 x06,0 x5b,0 x4f,0 x66,0 x6d,0 x7d,0 x07,0 x7f,0 x6f,0 x77,0 x7c,0 x39
22、,0 x5e,0 x79,0 x71;void main(void)unsigned int us250=0;unsigned char slO=0;unsigned char si=0;unsigned char keylO=0;/记忆按键状态,为1按下unsigned char keyl=0;/记忆按键状态,为1按下/初始化定时器TimerOT M O D =(T M O D&O x F O)0 x 02;T H 1=-250;/对 于8位二进数来说,-250二6,也就是加250次1时为2 5 6,即为0T R I =1;w h i l e /-循环1P l =S e g 7C o d e
23、 s l O ;显示秒十位P 2=S e g 7C o d e s i ;显 示秒个位w h i l e (1)/-循环2计时处理i f (T F O =1)T F O =0;i f (+u s 250=4000)u s 250=0;i f(+s l =10)s i =0;i f (+s l O =6)s l O =0;)b r e a k;结束“循 环2”,修改显示)按十位键处理P 3.2=1;/P 3.2 作为输入,先要输出高电平i f (k e y l O =1)等松键i f (P 3.2=1)k e y 10=0;e l s e 未按键i f (P 3.2=0)k e y l O =1
24、;i f(+s l O =6)s l O =0;b r e a k;结束“循 环2”,修改显示按个位键处理P 3.3=1;P 3.3作为输入,先要输出高电平i f (k e y l =1)/等松键 i f (P 3.3=1)k e y 1=0;e l s e 未按键i f (P 3.3=0)k e y l =1;i f(+s l =10)s i =0;b r e a k;结束“循 环2”,修改显示)循环 2 e n d/循环 1 e n d/m a i n e n d第三节:十字路口交通灯如果一个单位时间为1秒,这里设定的十字路口交通灯按如下方式四个步骤循环工作:6 0个单位时间,南北红,东西
25、绿;1 0个单位时间,南北红,东西黄;6 0个单位时间,南北绿,东西红;1 0个单位时间,南北黄,东西红;解:用P1端口的6个引脚控制交通灯,高电平灯亮,低电平灯灭。ttinclude/s b it用来定义一个符号位地址,方便编程,提高可读性,和可移植性sbit SNRed=P0;/南北方向红灯sb it S N Y e llow =Pl;/南北方向黄灯sb it S N G re e n =P1 2;/南北方向绿灯sb it E W R e d =P3;/东西方向红灯sb it E W Y e llow =P1 4;/东西方向黄灯sb it E W G re e n =P1 5;/东西方向绿
26、灯/*用软件产生延时一个单位时间v oid De la y lU n it(v oid )u n sig n e d in t i,j;f or(i=0;i1 0 0 0;i+)f or(j0;j1 0 0 0;j+);/通过实测,调 整j循环次数,产 生1 m s延时/还可以通过生成汇编程序来计算指令周期数,结合晶体频率来调整j循环次数,接 近1 m s)/*延时n个单位时间*/v oid De la y (u n sig n e d in t n )f or(;n!=0;n-)De la y lU n it();v oid m a in(v oid )w hile (1 )SNRed=O;
27、SNYellow=0;SNGreen=l;EWRed=l;EWYellow=0;EWGreen=O;Delay(60);SNRed=0;SNYellow=l;SNGreen=0;EWRed=l;EWYellow=0;EWGreen=0;Delay(10);SNRed=l;SNYellow=0;SNGreen=0;EWRed=0;EWYellow=0;EWGreen=l;Delay(60);SNRed=1;SNYellow=0;SNGreen=0;EWRed=0;EWYellow=l;EWGreen=0;Delay(10);第四节:数码管驱动显示“1 2 3 4 5 678”P1 端口接8 联共
28、阴数码管S L E D8的段极:P L 7 接段h,,P1.0 接段aP2 端口接8 联共阴数码管S L E D8的段极:P2.7 接左边的共阴极,P2.0接右边的共阴极方案说明:晶振频率f osc 二 1 2 M H z,数码管采用动态刷新方式显示,在 1 m s定时断服务程序中实现t t in c lu d e u n sig n e d c ha r DisBu f 8 ;/全局显示缓冲区,DisBu f 0 对应右S L E D,DisBuf7对应左 SLED,void DisplayBrush(void)code unsigned charcathode8=Oxfe,Oxfd,Oxf
29、b,0 xf7,Oxef,Oxdf,Oxbf,0 x7f;阴极控制码Code unsigned charSeg7Code16=/用十六进数作为数组下标,可直接取得对应的七段编码字节0 x3f,0 x06,0 x5b,0 x4f,0 x66,0 x6d,0 x7d,0 x07,0 x7f,0 x6f,0 x77,0 x7c,0 x39,0 x5e,0 x79,0 x71;static unsigned char i=0;/(0 i=8)i=0;/指向下一个数码管和相应数据)v oid T im e rO I n t R ou t e (v oid )in t e rru pt 1T L O =-
30、1 0 0 0;由于 T L O 只有8b it s,所 以 将(-1 0 0 0)低8位赋给T L 0T H 0 =(-1 0 0 0)8;取(-1 0 0 0)的高8位赋给T H 0,重新定时1 m sDispla y Bru sh();)v oid T im e rO I n it (v oid )T M O D=(T M O D&O x f O)|0 x 0 1;/初始化,定时器T O,工作方式1T L O =-1 0 0 0;/定时 1 m sT H O =(-1 0 0 0)8;T R O =1;/允许T O开始计数E T O =1;/允许T O计数溢出时产生中断请求v oid D
31、ispla y (u n sig n e d c ha r in d e x,u n sig n e d c ha rd a t a V a lu e )DisBu f in d e x _ =d a t a V a lu e;v oid m a in(v oid )(u n sig n e d c ha r i;f or(i=0;i8;i+)Displa y (i,8-i);/DisBu f 0 为右,DisBu f 7为左T im e rO I n it();E A=1;/允 许C P U响应中断请求W hile (1);第五节:键盘驱动指提供一些函数给任务调用,获取按键信息,或读取按键值
32、。定义一个头文档,描述可用函数,如下:#i fn def _ K EY _ H _ /防止重复引用该 文 档,如 果 没 有 定 义 过 符 号_ K EY _ H _,则编译下面语句#defi n e _ K EY _ H _ /只要引用过一次,即 tti n c l ude ,则定义符号 _ K EY _ H _un s i gn ed c ha r k eyH i t(vo i d);/如果按键,则返回非0,否则返回0un s i gn ed c ha r k eyGet(vo i d);/读取按键值,如果没有按键则等待到按键为止void keyPut(unsigned charucKe
33、yVal);/保存按键值 ucKeyVal到按键缓冲队列末void keyBack(unsigned charucKeyVal);/退回键值 ucKeyVal 到按键缓冲队列首#endif定义函数体文档KEY.C,如下:#include“key.h#define KeyBufSize 16 定义按键缓冲队列字节数un s i gn edc ha rK eyBuf K eyBufS i z e ;/定 义 一个无符号字符数组作为按键缓冲队列。该队列为先进/先出,循环存取,下标从 0 到 K eyBufS i z e-1un s i gn ed c ha r K eyBufW p=O;/作为数组下
34、标变量,记录存入位置un s i gn ed c ha r K eyBufR p=O;作为数组下标变量,记录读出位置/如果存入位置与读出位置相同,则表明队列中无按键数据un s i gn ed c ha r k eyH i t(vo i d)i f(K eyBufW p =K eyBufR p )r etur n(0 );el s e r etur n(1 );unsigned char keyGet(void)unsigned char retVal;/暂存读出键值while(keyHit()=0 );等 待按键,因为函数keyHit()的返回值为0表示无按键retVal 二 KeyBuf
35、KeyBufRp;/从数组中读出键值if(+KeyBufRp=KeyBufSize)KeyBufRp=0;/读位置加1,超出队列则循环回初始位置return(retVal);vo i d k eyP ut(un s i gn ed c ha ruc K eyV a l )K eyBuf K eyBufW p =uc K eyV a l;/键值存入数组i f(+K eyBufW p =K eyBufS i z e)K eyBufW p=O;/存入位置加1 ,超出队列则循环回初始位置)vlx six slz vlx six six six slz six xlx slz six six six*1
36、*six sixT*XTX T*TX TX XTX XTX*TX TX XTX%lz sl*six six viz six%lz sl*six six%lz six slz xlx six viz six%lz six viz sixp*T*7X XIX XTX XT%XTS*TX XjX XTX ZT%*TX XjX X7X XjX XT*TX TX TX XTX*TX TX*T%*TXvL*vt*%tz xt*%tz v!six siz xlz%tz siz xl vllx xlx%lxXTS*TS TS TX*TX ZTX TS TX ZT*TX TX TX ZT*TX TX TX TX
37、 T%T%TX XTX XTX TS*TS由于某种原因,读出的按键,没有用,但其它任务要用该按键,但传送又不方便。此时可以退回按键队列。就如取错了信件,有必要退回一样xlx six 1 xlx xlx xlx lx*1 v!x lx*1lx*1 lx xlx vt*T X X I X T X T X X T X X T X X I X X T X X T*Z T X T*T X X T X X I X X T X XT%T X *T X X I X X T X X T*T%Z T*X T X X T X X I X XT%T X X T X X T X X I Xvtx viz%!xlx si
38、x slz six six six%!xlx six slz x!xt*xlx lz six six six lz six slz x!lx vlx*lx lx xlx lx*1*1*six vlx*lx lx xlx xlz six%lz six sl=K eyBufS i z e)K eyBufR p=K eyBufS i z e-l;K eyBuf K eyBufR p =uc K eyV a l;/回存键值下面渐进讲解键盘物理层的驱动。电路共同点:P 2 端口接一共阴数码管,共阴极接GN D,P 2.0 接 a 段、P 2.1接 b 段、P 2.7 接 h 段。软件共同点:c o de
39、 un s i gn ed c ha rS eg7 Co de 1 0 是七段数码管共阴编码表。Co de un s i gn ed c ha r S eg7 c o de 1 6 二/0 1 2 3 4 56 7 8 9 A bCdEF0 x3f,0 x06,0 x5b,0 x4f,0 x66,0 x6d,0 x7d,0 x07,0 x7f,0 x6f,0 x77,0 x7c,0 x39,0 x5e,0 x79,0 x71;例一:Pl.0接一按键到GND,键编号为 6显示按键。ttinclude ttinclude“KEY.Hvoid main(void)Pl_0=1;/作为输入引脚,必须先
40、输出高电平while(1)/永远为真,即死循环 if(Pl_0=0)如果按键,则为低电平 keyPut(6);/保存按键编号值为按键队列whi l e(P 1 0 二 二 0 );/如果一直按着键,则不停地执行该循环,实际是等待松键)i f(k eyH i t()!=0 )/如果队列中有按键P 2=S eg 7Co de k ey Get();/从队列中取出按键值,并显示在数码管上例二:在例一中考虑按键2 0 ms抖动问题。t t i n c l u de t t i n c l u de“KEY.H”v o i d m a i n(v o i d)P l _ 0 =1;/作为输入引脚,必须先
41、输出高电平w hi l e(1 )永远为真,即死循环 i f(P l _ 0 =0 )如果按键,则为低电平 delay20 nls();/延时 20 ms,跳过接下抖动k ey P u t (6);/保存按键编号值为按键队列w hi l e(P 1 0 二 二 0 );/如 果一直按着键,则不停地执行该循环,实际是等待松键delay20 1ns();/延时 20 ms,跳过松开抖动i f (k ey Hi t ()!=0 )如果队列中有按键P 2=S eg 7Co de k ey Get ();/从队列中取出按键值,并显示在数码管上例三:在例二中考虑干扰问题。即小于2 0 ms的负脉冲干扰。t
42、 t i n c l u de t t i n c l u de“KEY.Hv o i d m a i n(v o i d)P l 0 =1;作为输入引脚,必须先输出高电平w hi l e(1 )永远为真,即死循环 i f(P 1 _ O =0 )如果按键,则为低电平 del a y 2 0 n l s ();/延时 2 0 m s,跳过接下抖动if(Pl 0 =1)continue;/假按键k ey P u t (6);/保存按键编号值为按键队列w hi l e(P 1 0 二 二 0 );/如 果一直按着键,则不停地执行该循环,实际是等待松键del a y 2 0 n l s ();/延时
43、 2 0 m s,跳过松开抖动if(keyHit()!=0)/7 如果队列中有按键P2=Seg7Code keyGet();/从队列中取出按键值,并显示在数码管上例四:状态图编程法。通 过 2 0 m s 周期中断,扫描按键。/*J J j j j j j j Ja ej j j j/T3采用晶体为1 2 KHz 时,指令周期为1 m s(即主频为IKHz),这样T 0 工作在定时器方式2,8位自动重载。计数值为2 0,即可产生2 0 nls的周期性中断,在中断服务程序中实现按键扫描*T TS#T Ts#Ts#T#T T%#T#T Tx T%Ts/S#T#T*T%T%#T/t t i n c
44、l u de t t i n c l u de“KEY.Hv o i d m a i n(v o i d)(T MO D=(T MO D&O x f O )|0 x 0 2;/不改变T 1的工作方式,T O为定时器方式2T HO =-2 0;/计数周期为2 0个主频脉,即2 0 n l sT LO=T HO;先软加载一次计数值T R O=1;/允 许T O开始计数ET O=1;/允 许T O计数溢出时产生中断请求EA=1;/允许CP U响应中断请求w hi l e(1 )/永远为真,即死循环i f (k ey Hi t ()!=0 )/如果队列中有按键P 2=S eg 7Co de k ey
45、Get();/从队列中取出按键值,并显示在数码管上void timerOint(void)interrupt1/20ms;T O的中断号为1 static unsigned char sts=0;Pl_0=1;/作为输入引脚,必须先输出高电平switch(sts)case 0:if(Pl_0=0)sts=l;break;/按键则转入状态1case 1:if(Pl_0=l)sts=0;/假按错,或干扰,回状态0else sts=2;keyPut(6);/确实按键,键值入队列,并转状 态2b r ea k;c a s e 2:i f(P 1 _ O=1 )s t s=3;b r ea k;/如果松
46、键,则转状态3c a s e 3:i f (P 1 _ O=O )s t s=2;/假松键,回状态2el s e s t s=O;/真 松 键,回状态0,等待下一次按键过程例五:状态图编程法。/J 如果采用晶体为1 2 MHz 时,指令周期为 l u s(即主频为1 MHz),要产生2 0 n l s左右的计时,则计数值达到2 0 0 0 0,T 0 工作必须为定时器方式1,1 6位非自动重载,即可产生2 0 m s 的周期性中断,在中断服务程序中实现按键扫描*jL*JL*JL*X*X;*;!*JL*jL*1 JL*jL*X*/t t i n c l u de t t i n c l u de
47、“KEY.Hv o i d m a i n(v o i d)T MO D 二(T MO D&O x f O )O x O l;/不改变T 1的工作方式,T O为定时器方式1T LO 二-2 0 0 0 0;/计数周期为2 0 0 0 0个主频脉,自动取低8位T HO =(-2 0 0 0 0)8;/右移8位,实际上是取高8位T R O=1;/允 许T 0开始计数ET O=1;/允 许T 0计数溢出时产生中断请求EA=1;/允许CP U响应中断请求w hi l e(1 )永远为真,即死循环if(keyHit()!=0)如果队列中有按键P2=Seg7Code keyGet();/从队列中取出按键值
48、,并显示在数码管上)void timerOint(void)interrupt1/20ms;T O的中断号为1 static unsigned char sts=0;TLO=-20000;方式 1为软件重载THO=(-20000)8;右移8位,实际上是取高8位P1 0=1;作为输入引脚,必须先输出高电平s w i t c h(s t s )c a s e 0:i f(P 1 _ O=O )s t s=l;b r ea k;/按键则转入状态1c a s e 1:i f(P 1 _ O=1 )s t s=O;/假按错,或干扰,回状态0el s e s t s=2;k ey P u t (6);/确
49、实按键,键值入队列,并转状态2b r ea k;c a s e 2:i f(P 1 _ O=1 )s t s=3;b r ea k;/如果松键,则转状态3c a s e 3:i f (P 1 _ O=O )s t s=2;/假松键,回状态2el s e s t s=0;/真松键,回状态3 等待下一次按键过程例六:4 X 4 按键。/T%#T Ts#Tj ej j j J 由P l 端口的高4 位和低4 位构成4 X 4的矩阵键盘,本程序只认为单键操作为合法,同时按多键时无效。这样下面的X,Y 的合法值为0 x 7,O x b,O x d,O x e,O x f,通过表 ke y C od e
50、影射变换可得按键值 J aj 4T%*T%*T T%T%J J j j j J ja j/#T#T T%T#T#T*Ts Ts/t t i nc l u d et t i nc l u d e“KE Y.H u ns i gne d c h ar ke y S c an(v oi d )/返回0表示无按键,或无效按键,其它值为按键编码值 code unsigned char keyCode16=/OxO,0 x1,0 x2,0 x3,0 x4,0 x5,0 x6,0 x7,0 x8,0 x9,OxA,OxB,OxC,OxD,OxE,OxF 0,0,0,0,0,0,0,1,0,0,0,2,0,3