《单片机C语言部分资料.pdf》由会员分享,可在线阅读,更多相关《单片机C语言部分资料.pdf(87页珍藏版)》请在taowenge.com淘文阁网|工程机械CAD图纸|机械工程制图|CAD装配图下载|SolidWorks_CaTia_CAD_UG_PROE_设计图分享下载上搜索。
1、第三章 单片机C 语言编程基础本章主要学习51单片机的外部引脚和内部结构等,叙述一下。本书任务驱动教学,引入案例有浅变深,循序渐进,给读者留下思考和发挥空间。3.1利用单片机的I/O 口驱动L ED3.1.1利用单片机的P 0.0端口驱动1只LED叫烁)R3 1K编程的目的是利用C 语言控制单片机I/O端口按要求输H际 形 波 画 中信号,信号的周期 IC ST1由延时函数决定C G -V I IZIvlrlZXTALi_、电路原a轮 苹 二 早 注*丁皿Rl 1KSTC-89C51 h 坪 的 P0 口采方 RESET载时有两种接法:1 3 辐 口 上 拉 暨 PSEN31竺*口输出高电平时
2、 LE D 兑;另一种E EA39PO.O/ADO 鼻-PO.I/ADl TPO.2/AD2-7PO.3/AD3 送一P0.4/AD4 PO.5/AD5 专一P0.6/AD6 用一PO.7/AD7 4一P2.WA8P2.I/A9P2.2/A1OP2.3/A IIP2.4/AI2P2.5/A13P2.6/A14P2.7/AI5R2 IK nL ED1%L ED2伙I此利用P 0 驱动负、辕 用 1K。电阻接电源正极,此时P0藤 动 有 效,在 P0.7输出低电平时,STC-89C51端 确 入 电 流 达 20市 耳 即4 PL?-PI 3制 L ED2的工作电流。Z p|jP3.0/RXDP3
3、.1/TXDP 3.2/I P3.3/1NUP3.4/J0P3.5/T1P3.6AVRP3.7/RDU匕4-、八二;Hr lH图 3-3-1中的R 3为限流电阻,限燔在拉出电,7Jii7图3-1-1驱动LED电路原理单片机的最小系统包括晶体振荡电路,加电复位电路,同时要求单片机的31引脚正接高电平。时钟频率主要由晶体CY 决定,C l、C 2为独石电容,用于微小调整单片机时钟的振荡频率;R 1和 C3组成加电复位电路,C 3为电解电容器;整个电路由+5V电压供电。电路使用的元件参数见表3.1.1。表3.1.1 3-1-1电路元件表元件名称 序号 标称 规 格(封装,功率电压等参数)作用单片机
4、IC STC89C51 DIP40 核心芯片电容器C130PF独石振荡电容器C230PF独石振荡电容器C310 MF点解电容器复位晶振CY12MHzS型振荡电阻R1IKQ1/4W,金属膜电容器C 3放电电阻电阻R2IKQ1/4W,金属膜端口电位上拉电阻电阻R3IKQ1/4W,金属膜限流电阻发光二极管LED15红色高亮显示发光二极管LED26 5红色高亮显示二、程序设计1.程序设计平台程序设计采用k e i l C 软件,为了养成个良好的文件管理习惯,建议:编程前,在计算机的某个硬盘分区下建立一个目录,目录的名字为你编写程序的主题,然 后 把 k ei l C产生的所有文件都放在该目录下。程序设
5、计步骤如下:(1)运行k ei l C,创建一个项目。利用k ei l C 菜单栏中pr o j ect-n ew pr o j ect 创建,项目的名字为你编程的主题,如本案例可以用“LE D.u v 2”或“一 个 LE D 闪烁实验.u v 2”,存放目录为你的主题目录下;(2)创建建一个文件,然 后 以“.c”后缀名,文件存放在你的主题目录下;(3)把 c 文件添加在你的项目中,在 pr o j ect w o r k s pa ce窗口利用a dd f i l e t o g r o u p实现。如果软件界面不显示这个窗口,运行k ei l C 菜单栏中的v i ew-pr o j
6、ect w i n do w(4)设置编译器,是编译过程中能生成“.h ex”文件。默认文件名与主题名字相同。运行 pr o j ect-o pt i o n f o r *t a r g et 1 -o u t pu t 窗口 下点击 cr ea t e H E X f i l e。(5)在编程区域写你的程序,结束后存储文件并编译,要做检查,尽量避免警告出现,直到程序编译无误为止.(6)程序烧写并试运行。这个过程称为软件和硬件联合调试,如果实验板无误,程序编译通过,但在硬件上运行不成功是常用的事情,需要对程序进行多次调试。在没有实验板的情况下,可以利用pr o t eu s 软件仿真调试,也
7、可以检验你的程序设计结果。2.程序设计(1)利用P0.0 口驱动LE D 闪烁,高电平有效#include包含头文件sbit L ED=P0A0;L ED 接 P0.0。在 kellC51 软件中,定义 PO.O 为 P0A0,void delay(unsigned char x)/延时函数iunsigned char i,j;for(i=0;i x;i+)for(j=0;j 200;j+);ivoid main(void)j/主函数While(l)/程序死循环(L ED=0;/PO0输出低电平,L ED灭void delay(lOO);调用延时函数,延时一段时间,约 0.3秒,不精确L ED
8、=1;/PO0输出高电平,L ED亮void delay(lOO);/*/(2)利用P0.7端口驱动L ED闪烁,低电平有效/*/#includesbit L ED=P0A7;void delay(unsigned char x)(unsigned char i,j;for(i=0;ivx;i+)for(j=0;j IOO();j+);)void main(void)包含头文件,程序为小5 号字延时函数主函数while(l)L ED=-L ED;/L ED初始状态为灭,执行一次,L ED改变一次状态void dclay(lOO);延时段时间三、程序说明I.应为使用的单片机芯片为S T C8 9
9、 C5 1,因此程序开始处加入#i n cl u de,文件r eg 5 1.h中包含了 5 1芯片所有特殊功能寄存器的名称定义和相对应的地址值;2 .单片机程序单步顺序执行,先执行主函数,在主函数可以调用分函数,分函数可以调用分函数,但分函数不能调用主函数,程序执行一条命令再执行下一条,单片机等待的过程是执行了一个循环命令或一个浪费时间的程序,实际执行过程永远不会结束。d elay ()为函数延,单片机在执行此函数相关指令时占用的时间过长,在执行过程中,如果没有中断,单片机只能忙这一件事情。利 用d elay ()不能得到精确的延时。延时函数还可以利用下面的函数实现。void delay(u
10、nsigned int x)(while(x)/*I3 .利用位定义命令让L ED等价于P O.O或P 0.7,等于先sbit P 0 _ 0 =POP,然后#d efinedLE D P 0 _ 0,也在程序前面不做此类定义,在程序里面直接写成P 0A0 =1或P 0A0 =0,先定义是为了增加程序的可读性。程序执行p(ro=1后,PO.O对以的单片机内部位寄存器就设置为高电平,同 时PO.O端口也输出高电平,单片机的所有I/O 口都可位未定义,也可以字节定义。4 .单片机C语言程序设计需要的C语言关键字不多,并且在keiic中用到的关健字是独有的,因此对于没有学习过C语言的人学习单片机C语
11、言程序设计困难并不是很大,主要掌握单片机C语言书写格式,怎样用C语言控制单片机的硬件资源,另外在编程时,还要有清晰的逻辑思维头脑和认真实践,由浅逐步深入学习,当你坚持到最后时,单 片 机C语言程序设计实际上很简单。VCC(+5V)R29 IK5.每个人在编写程序时都有自己的风格。一般情况下,*j嘀 徒 距 为 0,其下每条语句前留一个说 明,每一个函娄t留 党吃腐罄“区阴95,XTAL I可读性。XTAL 2RI 1K3.1.2 利用 pojqpgti 8 个 1C3 ion 常RESETP0.0/AD0P0.I/ADIPO.2/AD2PO.3/AD3P0.4/AD4PO.5/AD5P0.6/
12、AD6P0.7/AD73914要有中文或英文3X _,近 三 堂 包 初 于 提 高 程 序 的 层 次 感 和35_ ,一、参考电31KENAL EEAP2.0/A8P2.1/A9P2.2/A1OP2.3/A IIP2.4/AI2P2.5/AI3P2.6/AI4P2.7/A15鼻 喉 流 水 灯 雷 惨L ED 1-8实验电路见滤:3-3-2所 示,1P 0 口的上拉电阻可以使用8个 1SHD T-PL 2 4-PI.3I-初P3.0/RXDP3.1/TXDP3.2/INT0P3.3/INTJP3.4/TOP3.5/T1P3.6AVRP3.7/RD噬 础 上,P 0 口 依 次 接 入 8个
13、 L E D,二 F17图3-1-2流水灯电路在利用P r o t eu s软件仿真时,可以用电阻排代替。单片机最小系统在单片机元件放置后已经默认,即 C l、C 2、C 3、CY、R1可以省略。其 它 元 件 选 取 见 表 3.1.2所 示。表3.1.1 3-1 -2电路Proteus软件元件表元件名称component总类 Category分类 Sub-Category结果 Results模型 Model type单片机Micoroprocessor IC8051 Family80C51电阻排ResistorResistor PackRESPACK-8ANAL OG发光二极管Optoel
14、ectronicsL EDsled-redDIGITAL二、参考程序#includevoid delay(void)unsigned char i,j;for(i=0;i 255;i+)for(j=0;j 255;j+);void main(void)unsigned char j=0 x01;while(1)j=j 1;if(j=0 x00)j=0 x01;P0=j;delay();/*/三、程序说明I.语 句 执 行 的 目 的 是 控 制 P0整个字节的数据在循环时左移变化,程序循环第一次,P0=0 x02,P0.1连接的L ED亮,其它灭;循环第七次,P().7连接的L ED亮,其它灭
15、;循环第八次,j=0 x00,if语句条件满足,j=0 x01,P0.0连接的L ED亮,其它灭,然后依次变化下去。如果P0 口驱动8 个 L ED低电平有效,如下修该:void main(void)unsigned char j=Oxfe;while(1)(j=(j 1)1 0 x01;if(j=Oxff)j=Oxfe;PO=j;delay();J2.delay。函数无形参,延时时间不能设置。3.1.3利用P0 口驱动一个数码管,显示0-9,并循环一、参考电路实验电路在单片机的最小系统基础上,P0 口接一只共阳数码管,见图3-1-3。带小数点的数码管是由8 个 L ED组成,七 个 L ED
16、组成数字,另一只L ED用来显示小数点。如果数码管内部的8 只 L ED的正极接在起,负极分别引出,引脚依次命名为a、b、c、d、e、f、g 和 d o t,称为带小数点的7段共阳极性数码管。AL EP2.4/A12P2.5/AI3P2.6/AI4P2.7/AI5X、2 7M生七士士二vccP1.0Pl.IPl.2Pl.3Pl.4Pl.5Pl.6Pl.7P3.4TOP3.5/T1P3.2/INT0P3.3/INTJP3.0/RXDP3.1/TXD图3-1-3单片机驱动共阳数码管电路单片机的P0.0-P0.7 口分别接数码管的a-dot引脚,如果让数码管显示1,数码管b、c段亮,程序控制P0输出
17、Oxbe十六进制编码即可,因此共阳数码管显示0-9十进制数字,需要利用10个显示码组成的数组。对于共阴数码管,也有相应的编码要求。小数点在不用时一般不让显示,高位端口 P0.7输出高电平即可。由于P0每个端口的灌电流达20m A,数码管每段L ED正常显示5mA即可,因此需要R29用来限制数码管每一段电流,以防止驱动电流过大而烧毁器件。利用Proteus软件仿真时,数码管米用 Optoelectronics 元件库中 7-Segmcnt Displays 下的 7-SEG-COM-ANODE。二、参考程序/*!#includecode unsigned char sevcn_seg 10=0
18、xc0,0 xf9,0 xa4,0 xb0,0 x99,0 x92,0 x82,0 xf8,0 x80,0 x90J;void delay(void)/*时间延迟函数*/unsigned char i,j;for(i=0;i 255;i+)for(j=0;j=255;j+);void main(void)unsigned char i;/*变量i用来储存09*无穷循环*/while(1)for(i=0;i10;i+)P0=seven_segi;/*输出09到共阳七段显示器*/dclay();/*调用时间延迟函数delay*/*I三、程序说明1.当程序中使用常量数据时,可以把数据存储在单片机的程
19、序存储器中,对此类数据声明时,前面需要加上关键字code或co n st,如本实验中的共阳数码管数字显示需要的编码,表3-1-3是共阳数码管编码,表3-1-4是共阴数码管编码。单片机驱动液晶显示器显示的汉字也是种常量数据。表3-1-3共阳数码管显示编码显示数字dotgf edcba16进制011000000OxcO1111110010 xf92101001000 xa4310110000OxbO4100110010 x995100100100 x926100000100 x827111110000 xf88100000000 x809100100000 x90表3-1-4共阴数码管显示编码显示
20、数字dotgfedcba16进制0001111110 x3f1000001100 x062010110110 x5b3010011110 x4f4011001100 x665011011010 x6d6011111010 x7d7000001110 x078011111110 x7f9011011110 x6f2.本程序数码管显示使用了 个for循环,让变量i依次由0递增到9,并将数字显示码送到P 0,需要注意,seven_seg10有10各数据,seven_seg0为第一个数据,seven_seg9为 第10个数据。数码管显示的数据变化时间由延时函数决定。for循环体嵌套在while循环体中
21、,数码管回循环显示0 9,永不结束,除非电路断电。利用数码管也可以显示日期和时间,在以后的程序设计案例中就可以学到。3.2 单片机定时器/计数器应用3.2.1利用TimerO中断产生1秒延时,让数1 个码管显示秒计数本案例主要目的是熟练掌握单片机内部TimerO或 T im eri的编程控制方法,会利用TimerO或 Timer 1 中断精确定时。同时掌握数码管动态显示原理,学会6 位数字显示的程序设计。本案例使用的电路为图3-1-3。一、程序设计/*/#includecode unsigned char sevcn_seg101=0 xc0,0 xf9,0 xa4,0 xb0,0 x99,0
22、 x92,0 x82,0 xf8,0 x80,0 x90);cp=O;i+;)unsigned char cp,i;声明全局变量void timerO_isr(void)interrupt 1/timerO中断服务函数ITR0=0;停止计数TL 0=0 xll;TL 0重新预置THO=Oxee;TH0重新预置TR0=0;开始计数cp+;/timeiO中 断 1 次,变量cp 加 1if(cp=200)中断200次,时间刚好为1秒i f(i =1 0)i =0;P 0 =s e v e n _s e g i/P 0输出显示数据1v o i d t i m e r O _i n i t i a l
23、 i z e(v o i d)r/t i m e r O中断初始化函数EA=0;/设置中断允许寄存器I E中 的EA位,关闭中断总开关TMOD=0 x 0 1;设置计时器模式控制寄存器,T i m e。工作在定时方式1T R 0 =0;/设置计时器控制寄存器TCON寄存器的TR0位为0,T i m e r O/停止计数T L O =O x l l;T H 0 =O x e e;T i m e r。的1 6位计数器初始值为O x e e l 1,12MHz晶体振/频率,单片机的机器周期为1微妙,T i m e r O每1微秒加1计数,加满溢出变产生中断,从计数到中断刚好为5毫秒P T 0=1;设
24、置中断优先次序寄存器I P中的PT0位,T i m e r t)中断优先E T 0=1;设置中断允许寄存器I E中ETO的位,开启中断小开关EA=1;/打开中断总开关TR0=1;/开始计数v o i d m a i n (v o i d)t i m e i i)_i n i t i a l i z e()/t i m e r O初始化,为中断做好准备w h i l e (1);等待中断/*I二、程序说明1,中断服务函数名中,interruput为关键字,1 为 timerO中断号。在 reg51.h头文件中已经定义,表 3.2.1为单片机常用中断的中断号。在使用中断服务函数时,直接在名后加in
25、terruput和中断号即可。表3.2.1 r e g 5 1.h中单片机常用中断号定义中断源中断触发原因中断号INTO外部INTO引脚有低电平或下降沿信号输入0TimerOTimerO计数溢出1INTI外部INTO引脚有低电平或下降沿信号输入2Timer 1Timer 1计数溢出3串行中断串口缓存SBUF写入数据或读出数据42.t i me r。可以用作计数,也可以用来定时,由由TMO D寄存器中C厅为决定,作为计数器使用时,接受单片机外部引脚P3.4输入的脉冲加计数;作为定时器使用时、接受单片机内部的机器周期脉冲。如 果 单 片 机 的 振 荡 频 率 为 九 振 荡 周 期 为 则 机
26、器 周 期 为7 =1 2/。本案例中f =1 2 M H z,则7 =1微秒,t i me r O工作在模式1为1 6为加计数器,当计数器初始值为Ox e e ll时,则从开始计数到产生中断需要的时间为Ox f f f f Ox e e l 1个微秒,刚好为5 0 0 0微秒,也即5毫秒。本案例t i me r。的初装也可以利用下面语句完成:/*/#defined TEMORO_COUNT Oxeel ITL O=TEMORO_COUNT&OxOOff;取 TEMORO_COUNT 的低字节并装入 TL OTH0=TEMORO_COUNT 8;/TEMORO_COUNT 左移 8 位,并将低
27、字节装入 TEMORO_COUNT/*/利用定时器/计数器定时时.,需要现设置工作模式,并计算它的初装值,计算初装值不好计算,常利用计算机中的计算器工具辅助。t i me r O工作在模式1可以最大6 5 5 35微秒中断1次,如工作模式2,最大25 6微秒中断1次。3.当程序中只涉及一个中断时,可以不对中断的优先级进行设置,因此在本案例中语句PT O-1可以省略。程序中有多个中断但没有进行优先级设定的情况下,单片机中断优先级默认按终端号递增而依次降低。4.数码管显示语句放在了 t i me d)中断服务函数里面,由于5毫秒中断1次,因此数码管显示的数据会每5毫秒更新1次。1秒内更新20 0次
28、,更新过程是把原来的数据覆盖,但显示数据1秒内变化1次。3.2.2利用4个数码管,实现秒信号加计数一、电路原理图3-2-1所示的电路中,4位七段数码管采用4只单个数码管组成,可以显示0 0 0 0-9 9 9 9,数据输入端并联后接P0 口,位选即每个数码管的阳极分别接P2 口,中间加非门驱动。因为P2 口反相驱动,因此,如果千位数码管显示,P2.7输出低电平,P 2的其它端口输出高电C2 30P(),_ 12L-C D-!-X T A L 2R E S E TPO.2/A D 2PO.3/A D 3P0.4/A D 4PO.5/A D 5P0.6/A D 6PO.7/A D 7TFC3 1(
29、)H并且此时PO输出十莅P S E NA L EE A7SEG-晚 X 4-C A,非 门 琐电阻R29是限流电阻。斗P1.0Pl.lPl.2Pl.3Pl.4Pl.5PI.6PI.7P3.2/1 NT OP3.3/INT IP3.4/B)P3.5 Z HP3.O/R XDP3.I/T XDP2.1/A 9P2.2/A IOP2.3/A I1P2.4/A I2P2.5/A I3P2.6/A I4P2.7/A I5P2.0/A 8图 3-2-1 4 位七段数码管显示二、程序设计#include#defined unsigned char uchar#dcfincd unsigned int uin
30、tcode uchar seven_seg10=0 xc0,0 xf9,0 xa4,0 xb0,0 x99,0 x92,0 x82,0 xf8,0 x80,0 x90);code uchar seg_scan4=0 xef,0 xdf,0 xbf,0 x7f);各个数码管对应的位选数据uchar counter4=0,0,0,0);uint cpj;void timerO_isr(void)interrupt 1(ucharj;TRO=0;TL 0=0 xll;TH0=Oxee;TR0=0;cp+;if(cp=200)(cp=0;counter0+;/个位、十位、百位和千位数/timerO中断
31、服务函数停止计数/TL 0重新预置TH0重新预置开始计数timerO中 断 1 次,变量cp 加 1中断200次,时间刚好为1秒个位数,1秒 加 1)if(counter0=)0)counter|0=0;counter 1 +;if(counterl=10)counter!1 =0;counter2+;)if(counter2=10)counter2=0;counter3+;)if(counter3=10)counter3=0;P O=s ev en_s eg cou nt er|j ;P O输出数据编码P 2 =s eg_s can j;/P 2 输出位选信号j+;i f(j=4)j=0;)
32、v oi d t i m er O_i ni t i ali z e(v oi d)/t i m er O 中断初始化函数(E A =0;T MO D =0 x 0 1;T R O =0;T L 0 =0 x ll;T H O =Ox ee;P T O=1;E T O=1;E A=1;T R 0=1;)v oi d m ai n(v oi d)(t i m er O_i ni t i ali z e()w hi le(1);)三、程序说明1 .i m er O第1次中断,j =0,显示个位,显示5毫秒后,t i m er。第2次中断,j =1,显示十位,以后随着中断依次显示百位和千位,最后重新
33、显示个位。每位显示停留的时间为5毫秒。中断4次才能让4为依次扫描显示完,占用的时间为20毫秒,1秒钟内,4位数码管扫描显示5 0遍,根据人眼视觉暂留特点,你看到的结果是4位数据同时显示,这种显示方法为动态扫描显示。2 .变量j =0时,cou nt er 0 是个位十进制数,执行P 0 =s ev en_s eg cou nt er 0,P 0 口输出个位显示数据编码;数码管的位选信号只利用了 P2的高4位,执行P 2 =s eg_s can,P 2 =Ox ef,经过非门反相,加在数码管上的位选信号只有个位是高电平,此时只显示个位。3.数组coumerlj 也可以用1个变量代替,在显示时需做
34、下面处理uint x;P0=seven_segx/1000;P2=seg_scan3J;P0=se ven_seg x%1000/100;P2=seg_scan2;P0=seven_scgx%1000%100/10;P2=seg_scanl;P0=seven_segx%1000%100%10;P2=seg_scan0;P0输出千位数据编码千位数码管共阳极设置为高电平P0输出百位数据编码千位数码管共阳极设置为高电平P0输出十位数据编码千位数码管共阳极设置为高电平P0输出千位数据编码 位数码管共阳极设置为高电平/*/4.思考题(1)要让数码管在电路加电开始就显示1230,怎样更改有关数据?(2)为
35、什么不用P2 口直接驱动数码管?(3)本案例如果200微秒中断1次,也可以实现1定时,显示结果会怎样?3.2.3设计一个6位数码管时间显示程序本案例使用6 位数码管显示时间,能显示时/分/秒,显示格式是00.00.0()到 23.59.59。其中小时和分钟之间的小数点常亮,分钟和秒之间的小数点进行秒闪烁。一、参考电路二、参考程序/*I#include#dcfincd unsigned char ucharcode uchar seven_seg|10=Oxc0,0 x f9,0 xa4,0 xb0,Ox99,Ox92,Ox82,0 xf8,0 x8(),Ox90);code uchar seg
36、_scan6=0 xfb,0 xf7,0 xef,0 xdf,0bf,0 x7f);/各个数码管对应的位选数据uchar counter3=0,0,0);时位、分位和秒位uchartick,cp,ij;/tick:秒信号,cp:中断次数累计void dispaly(void)uchard:d=d*tick;/d 的 值 1秒内改变1次,要么0 x 0 0,要么Oxffd=dl 0 x7f;/d 的 值 1秒内改变1次,要么0 x 7 f,要么Oxffswich(i)(case 0:P0=seven_segcounter0%10;break;显示秒个位case 1 :P0=seven_segco
37、unter0/10;break;显示秒十位case 2:PO=d&seven_segcounter0%10;break;/数据高 8 位 1 秒改变 1 次,实现小数点秒闪烁case 3:P0=seven_segcounter0/10;break;显示分十位case 4:P0=Ox7f&seven_segcounter0%10;break;显示数据高 8 位为低电平,小数点常亮case 5:P0=seven_segcounter0/10;break;显示时十位 break;P2=seg_scani;i+;if(i=6)i=0;void timerO_isr(void)interrupt 1 t
38、imer。中断服务函数TR0=0;停止计数TL 0=0 xll;TL 0重新预置TH0=Oxee;TH0重新预置TR0=0;开始计数cp+;/timerO中 断 1 次,变量cp 加 1if(cp=100)中断100次,时间刚好为0.5秒cp=0;tick=-tick;秒脉冲信号i f(j =2)刚好1秒j =0;cou nt er 0+;个位数,1秒加1i f(cou nt er 0 =60)cou nt er|0=0;cou nt er!1 1+;|i f(cou nt er l=60)cou nt er l=0;cou nt er 2+;i f(cou nt er 2 =2 4)cou
39、nt er 2=0;di s p lay O;Iv oi d t i m er O_i ni t i ali z e(v oi d)/t i m er O 中断初始化函数(E A =0;T MO D =0 x 0 1;T R 0 =0;T L 0 =0 x ll;T HO =Ox ee;PT 0=1;E T 0=1;E A =1;T R 0=1;)v oi d m ai n(v oi d)(t i m er O_i ni t i ali z e()w hi le(1);/t i m er O初始化,为中断做好准备三、程序说明1.利用counter 2 counterfl和 counter。变量
40、分别表示时、分和秒位的数值大小,也可以利用结构体定义这些变量,如:typcdef struct(ucar hour;ucar min;ucar sec;time;time now;/now是数据类型为time的变量然后就可以用 now.hour,now.min和 now.sec分 另U 代替counter2、counter和counter0.变量2.执行timed)中断服务函数时调用了 dispaly()函数,直接把dispaly()的函数体程序写在中断函数体内也行,但中断服务函数会显得臃肿。timer。每 5 毫秒中断1 次,调用dispaly()函数执行1次,在执行dispaly()过程中
41、,当 i=0 时,只显示秒个位,当 i=H 上 只显示秒十位,依次类推。为了让小时的个位小数点常亮,让小时个位显示时,把显示编码数据的高8 位设置为0;为了分个位小数点秒闪烁,把分个位小数点位设置一个周期变化的量即可。3.程序与复杂,使用的变量就愈多,在程序分析和设计时,需要注意使用的变量最好使用有一定含义的字符表示。3.3 键盘程序设计按键是一种开关,通过外界作用力,导电金属或导电非金属接触与分离实现电路通断的控制是按键的基本机械原理,如计算机键盘、手机、M P 3以及电子表按键。按键是计算机系统输入设备,也是人机信息交换的主要途径。按键按下会产生抖动现象,不能安全有效的对系统控制,本节根据
42、按键产生的抖动机理,提出以中断、延时等措施消除键盘输入过程中的不稳定因素,实现单片机系统键盘的稳定输入。3.3.1 键盘抖动现象按键按下都会发出一声响,谁然有的按键声音很轻微,但这都是导体碰撞产生的震动。这种现象称为键盘抖动。如果不对键盘的抖动进行处理,按键会对系统电路或程序产生意外的干扰。为了观察按键的抖动现象,我们先做一个小实验,分析一下一个微触按键产生抖动对系统的影响。图3 3 1力口数计数小系统图3-3-2加数计数小系统在图3-3-1所示的一个加数计数小系统中,设计数器的脉冲输入端C P为上升沿有效,加计数器初始显示为0。按键不按时,CP=0,计数器不加1计数。一般认为:按键按下,C
43、P端由低电平变为高电平,含有电平上升沿,计数器加1计数,并且按下1 次,计数器加1。实际实验时会发现,按键按下1次,计数器不是加1,而是跳跃一次性增加3 或 4。原因是按键按下在导体接触的瞬间产生了震动。图 3-3-2是按键按下过程中C P端实际电平改变情况。T 1为不按按键时刻,T 2 为按健按下瞬间的抖动,T 3 为按键按下稳定时刻,T 4为按键放开时刻瞬间,T 5 为按键放开时刻。从图中可以了解到,按键按下的瞬间由于震动会是按键内部的导体稳定接触,而是在导通和不导通之间来回弹跳,虽然时间一瞬间,但 使 CP端获得了多个电平的上 升沿。按键抖动时间的长短由按键的机械特性决定,一 般 为 5
44、mslOmso因此不能直接把按键作为1个脉冲的输入。VCC(+5V)在数字电路平常利用触发器消磨1 sgi动,但 在 则 游 统 中,按键可以直接接在单片机的I/O 口上当悝3.3.2利用外部XTAL2盘 程 庙I本案列利用外部照1 y 0 作却务程序,在中断脚务冲除油一、参考电路C3 1()RESETPO.O/ADOPO.1/AD1PO.2/AD2PO.3/AD3P0.4/AD4PO.5/AD5P0.6/AD6PO.7/AD7现象。乒 LEDI就 下R JL让单片机执行外部中断服键盘控制_ 2 9 _-J PSENALE-EAP2.O/A8P2.I/A9 FP2.2/AIO与 一P2.3/A
45、1I-P2.4/AI2金一P2.5/AI3省 一P2.6/AI4一P2.7/AI5 3-R3 I0K在最小系统叫抄上,单 片机驾日v c c -i-P由于P3.2接有上啦电阻R 3,所 以 其;012342 P l.55P3.2为低电平。为了消除键盘抖动血部 与io键盘接衽P3.2端口,按键不按时,P3.O/RXD-r r-P3I/TX D中一 C4 0.IUP33/JN n电 如果本键不下,P3.2电源地短路,P3.4/TO-6|P 3.5 m lj胃潞露皮哂。,1 KEY图3-3-3利用外部中断INTO实现键盘输入电路二、程序设计#includesbit L ED=P0A0;void in
46、tO_isr(void)interrrupt 0 unsigned char i=0;i=i;L ED=i;delay();Ivoid main(void)L ED=0;EA=0;EX0=1;/INTO中断服务函数,INTO的中断号为0/INTO中断1次,i值改变1次/INTO中断1次,L ED工作状态变化1次调用延时函数芯片初始化时,L ED灭开启INTO中断PXO=1;/INTO中断优先,可以省去EA=1;/开信总中断开关while(l);等待按键按下,中断发生三、程序说明这里没有设置INTO是下降沿触发中断或是低电平触发中断,原因是按键按下,不管产生不产生键抖现象,总能使INTO引脚产生
47、1个下降沿和低电平。如果设置只有下降沿才触发 INTO中断,需要利用设置计时器控制寄存器TCON的 ITO=1位,按键按下是否产生中断,可以利用程序检测TCON的 IE0位。利用外部中断触发作为按键输入很好的解决了键盘抖动问题。如果需要多个键盘,把 INTO 口与I/O 口之间用键盘连接,I/O 输出低电平扫面信号即可。在数码管动态显示电路中,为了节省硬件资源,可以在INTO 口和P2 口之间接入键盘,实现8 只按键输入。3.3.3利用延时程序在常嗯典-I-XTAL I按键按下产生4tMz西伸 XTAL 2跳过抖动,再对慌热”状态检 测,L-C Z l-t-2:RESETPO.O/ADOPO.
48、I/ADIPO.2/AD2PO.3/AD3P0.4/AD4VCC(+5V),可延时一段时间-21SEVEN_SEG理 腼 输 入PO.5/AD5,I.,P0.6/AD6.挈木P 0.7/A D 7*-个键盘设计,实现对数码管显示数据整。一、电路原理3 10H-PSEN3 AL E3 EA在单片机最系统的基础上,K6o地,见图3-3解示。数码管仍使厚P;:iP1.3-J-PI.4崂PL 6 S-P1.7在 Switches&Relasy 下的 SwitiPP2.0/A8P2.I/A9P2.2/AI0P2.3/A1IP2.4/A12P2.5/A13P2.6/A14$磁盘一端分别接p3Q、P 3.1
49、,另一端接P3.0/RXDPS 毕 件 中,汗键的快文名字为BUTTON,P3.4TT0 P3.5/T1-P3.6WR 7 P3.7/R D一KEY1h KEY2图 3-3-4利用延时函数消除键盘抖动实现键盘输入电路二、程序设计#includc#define uchar unsigned charcode uhar seven_seg10=0 xc0,0 xf9,0 xa4,0 xb0,0 x99,0 x92,0 x82,0 xf8,0 x80,0 x90;sbit key 1 =P3.0;sbit key2=P3.1;uchar key Instate,key2_state;按键按下的状态变
50、量void delay(uchar i)while(i)i;)void key_scan(void)if(keyl=0)delay(200):while(key 1 =0)key l_state=1;)if(key2=0)dclay(200);while(key2=0)key2_state=1;void main(void)char i;while(l)(key_scan();if(keyl_state=1)i+;key Instate=0;if(i9)i=0;)if(key2_state=1)(i;key2_state=0;if(i 0)i=9;P0=seven_segi;/键盘扫描函数如果