单片机实验总结_第1页
单片机实验总结_第2页
单片机实验总结_第3页
单片机实验总结_第4页
单片机实验总结_第5页
已阅读5页,还剩89页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

心得:1.劳劳逸(脑力劳动,体力劳动,娱

乐活动)2.发现问题,解决问题就是在你的

大脑中建立广泛的联系3.条缕清晰的做事风

格会让你的大脑变得异常秩序,清晰。做到

了此三点你的大脑会一天天聪明,清楚,灵

活起来。反过来有秩序的大脑将会使你的行

为更加利索,清晰。

注意:我的人生需注意1.不要口出妄语,只

要脚踏实地。2.不要轻易生气,不要轻易露

出邪恶的表情。3.不要做作要自然。4.不要

猥琐,慌张,要大方,放松,镇定,让自己

尽量多的处在禅定状态中

2010年5月8日

单片机学习中的问题总结:(天才可以被训练出来,任何人可以在任何领域取得惊人的

成就,只要你对你所从事的领域感兴趣,并能长久地保持专注,并具有吃苦耐劳的精神。你

的成功与否取决于你的思维方式(习惯)训练的过程是一个不断积累模式的过程,而解决问

题的过程最后就变成了对模式进行识别的过程。训练到最后拿到一个问题你可以在0.8秒内

迅速再现头脑中类似的模式并凭借直觉给出解决问题的绝佳方式。那样你就是一个天才(后

天培养的人才)

说明:黑色的程序代表没有问题可以直接用,绿色代代存正缺陷而要改进,紫色代表自创的

程序精华!红色代表要交代的重点内容

4.22

1.%bx代表什么数据类型呢?

2.串口调试时有时会发送和接收不一?

3.直接对P1口取反可以实现灭亮的时间对等,但是通过对P1口赋值则比较复杂!

4.做计数显示于LED上的实验的时候不太明白当按下键后P3.4被拉低但是当松开手的时候

是什么因素导致了此口被抬为高电平呢详见D:\dpj\shiyanji\lessonl_4\计数器实验????

5.在利用单片机进行音乐播放的时候需要注意一下几点:1.对于音乐的编码是遵循音调常数,

节拍常数,音调常数,节拍常数,的顺序进行的数组组合。2.音乐的最小单元是音

符,每个音符又分为音高和音长,其中控制音高的称为音调常数(共21个),控制音长的叫

节拍常数(共7个分别为四分之一拍0x10,半拍0x20,3/4拍0x30,1拍0x40,1又1/2拍0x60,2

拍0x80,4拍0x100),其中这两个常数变量又分别由控制节拍常数变量的定时器中断服务子

程序和控制频率常数变量的延时程序来控制。

6.驱动三极管一般只工作在饱和和截止两种状态下,只有当三极管用在放大电路中时才工作

在放大区。

7.注意DOFLY的板子采用的是:1.利用573锁存器来驱动段,利用三八译码器来驱动位选。

8.松手检测和松手处理不是同一个概念。松手去抖操作一般不进行。硬件按键去抖有:1.滤

波去抖和双稳态去抖!所谓的双稳态即为RS触发器,所谓的滤波即为在按键之后加入一个

滤波器和一个反向器以实现在键按下后输出正规的方波。

9.LCD液晶显示器依据内容分为段式,点阵式,以及字符式其中字符式应用最为简单。进一

步可学习图案式LCD.1602内部的控制驱动器是HD44780.DDRAM:用于存放LCD要显示的

数据,只要将标准的ASCII码送入DDRAM中内部的控制电路将自动将数据送到显示器上

进行显示。

10.总结:要学会使用别人编好的功能程序包!例如LCD显示驱动功能程序包!12c总线驱

动功能程序包。

二.经典程序收集

(1)利用定时计数器0实现计数功能

#include<reg52.h>

voidmain()

{TMOD=0X05;

TH0=0;

TL0=0;

TF0=0;

IE=0;

TR0=l;

//init();

while(l)

{Pl=TL0;

/*if(p34==0)

(

p34=l;

temp++;

Pl=temp;

}*/

问题与思考:谁来讲P3.4口的点评拉高?按键抖动问题在此难道不需要予以考虑吗?为什

么没有加入去抖程序却没有抖动?此处的初值不用反复复是因为默认为0.

(2)定时计数器1的计数功能实验

1#include<reg52.h>

2#defineucharunsignedchar

3//uchartemp;

4//sbitp34=P3A4;

5//voidinit();

6uchari=0;

7voidmain()

8{TMOD=0X60;

91THl=0xfe;

101TLl=0xfe;

111TF1=O;

121TR1=1;

131//init();

141while(l)

151

161(

172while(!TFl);

182TF1=O;

192++i;

202Pl=i;

212/*if(p34==0)

222{

232p34=l;

242temp++;

252Pl=temp;

262}*/

272)

281)

问题与思考一:同上此处的初始值不用反复复由于使用的工作方式2.

(3)串口通信实验:利用P3.0,P3.1实现字符串的发送。

#include<reg52.h>

#include<intrins.h>

#defineucharunsignedchar

#defineuintunsignedint

uchartrdata[]={'8';0,;c,;5,;r,0x0d,0x0a,0x00);

voidmain()

(

uinti,j;

SCON=0X40;

PCON=0;

//REN=1;〃有没有它也是不影响串口通信的因为他只在单片机接收的时候才要求必须置

TMOD=0X20;

TH1=OXE6;

TL1=OXE6;

//TI=1;//说明:有没有这个都不影响串口通信且位为有硬件置一

TR1=1;

while(l)

i=0;

while(trdata[i]!=OxOO)

{

SBUF=trdata[i];

while(TI==O);

TI=O;

i++;

)

for(j=0;j<50000;j++);

)

)

说明:当TI=1且SBUF=,A,时便启动了串口的发送计算机将接受到单片机发过来的数据Ao

REN=1;虽说对于发送而言可有可无但是最好还是加上吧!

(4)数码管的动态十分交替显示123456和050906的规范化程序

#include<reg52.h>

#defineucharunsignedchar

ucharcodedula[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f};

ucharcodewela[]={0x00,0x0i,0x02,0x03,0x04,0x05};

uchara,b,flag,temp;

sbitp37=P3A7;

voiddelay(uchar);

voiddisplay(uchar,uchar);

voidinit();

voidmain()

(

while(l)

(

uchari;

for(i=0;i<90;i++)

(

display(6,l);

delay(2);

display(5,2);

delay(2);

display(4,3);

delay(2);

display(3,4);

delay(2);

display(2,5);

delay(2);

display。,6);

delay(2);

for(i=0;i<90;i++)

{

display(6,0);

delay(2);

display(5,5);

delay(2);

display(4,0);

delay(2);

display(3,9);

delay(2);

display(2,0);

delay(2);

display(l,6);

delay(2);

)

)

)

voiddelay(ucharx)

(

ucharj;

for(;x>0;x-)

for(j=0;j<125;j++);

}

voiddisplay(uchara,ucharnum)

(

switch(a)

(

case6:p37=l,P0=dula[num],P2=wela[0],p37=0;break;

case5:p37=l,P0=dula[num],P2=wela[l],p37=0;break;

case4:p37=l,P0=dula[num],P2=wela[2],p37=0;break;

case3:p37=hP0=dula[num],P2=wela[3],p37=0;break;

case2:p37=l,P0=dula[num],P2=wela[4],p37=0;break;

case1:p37=l,P0=dula[num],P2=wela[5],p37=0;break;

default:break;

)

)

思考:用此程序实现比起我原来写的那个程序要好不必写两个显示函数了减少了程序的篇幅

提高了效率,而且使得整个程序看上去整齐划一非常之规范,利用子函数实现特定的功能实

现模块化程序设计的思路必须得以贯彻,子程序的效率也要必须得以提高!

注意:此程序在延迟时间上并不准确的实现一秒显示,显示123456为480ms显示050906

为480ms因此从一个123456到另一个持续时间为960毫秒小于一秒。

(5)自编的高效矩阵键盘检测程序

#include<reg52.h>

#defineucharunsignedchar

ucharcode

table[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71,0

x76,0x38,0x3e,0x6e,0x00};

uchartemp=0;

//sbitp37=P3A7;

voiddelay(uchar);

voiddisplayO;

ucharkeyscan();

voidmain()

(

P2=0x02;

while(l)

(

display();

)

)

voiddelay(ucharx)

(

ucharj;

for(;x>0;x-)

for(j=0;j<125;j++);

)

ucharkeyscan()

(

P3=0x0f;

temp=P3&0x0f;

if(temp!=0x0f)

(

delay(lO);

temp=P3&0x0f;

if(temp!=0x0f)

(

temp=P3&0x0f;

P3=OxfO;

P3=P3&OxfO;

if(P3!=OxfO)

(

delay(lO);

P3=P3&0xf0;

if(P3!=0xft))

temp=temp+P3;

returntemp;

voiddisplayO

uchartemp;

temp=keyscan();

switch(temp)

case0x7e:P0=table[1];break;

case0x7d:P0=table[2];break;

case0x7b:P0=table[3];break;

case0x77:P0=table[4];break;

case0xbe:P0=table[5];break;

case0xbd:P0=table[6];break;

case0xbb:P0=table[7];break;

case0xb7:P0=table[8J;break;

case0xde:P0=table[9];break;

caseOxdd:PO=table[10];break;

caseOxdb:PO=table[11];break;

case0xd7:P0=table[l2];break;

case0xee:P0=table[13];break;

caseOxed:PO=table[14];break;

caseOxeb:P0=table[15];break;

case0xe7:PO=table[16];break;

说明:其高效体现在:1.代码量少。注意:P3可以作为如变量temp一样使用。另外键盘的

工作方式有三种1.程序控制扫描2.定时扫瞄3.中断扫描。其中前两中方式或多或少对CPU

造成一定的浪费。而方式3则最高效。

(6)LCD驱动程序包

#include<reg52.h>

#include<intrins.h>

#defineucharunsignedchar

#defineuintunsignedint

sbitrs=P2A4;

sbitrw=P2A5;

sbite=P2A6;

#definedataportP0

constucharnodisp=0;〃无显示;

constucharnocur=l;//有显示但无光标;

constucharcurNoFlash=2;//有光标但无闪烁;

constucharcurflash=3;〃有光标且有闪烁;

voidlcdpos(uchar,uchar);〃确定光标的位置;

voidlcdwd(uchar);〃写字符;

voidlcdwc(uchar);〃送控制字且检测忙信号;

voidlcdwcn(uchar);//送控制字但不检测忙信号;

voidmdelay(uchar);//延迟子程序;

voidwaitidle。;//正常读/写操作之前的检测LCD控制状态;

//延迟子程序;

voidmdelay(ucharj)

(

uinti=0;

for(;j>0;j-)

for(i=0;i<125;i++);

)

//实现写字符功能将某个字符显示与ypos行xpos列。

voidwritechar(ucharc,ucharxpos,ucharypos)

(

lcdpos(xpos,ypos);〃调用光标设置子程序;

lcdwd(c);〃调用写字符子程序;

)

//功能在制定的位置显示字符串;

voidwritestring(uchar*s,ucharxpos,ucharypos)

(

uchari;

if(*s==,\O')

return;

for(i=0;;i++)

(

if(*(s+i)=='\O,)

break;

writechar(*(s+i),xpos,ypos);

xpos++;

if(xpos>=15)

break;

//设置光标的功能;

voidsetcur(ucharpara)

mdelay(2);

switch(para)

case0:{lcdwc(0x08);break;}

case1:{lcdwc(0x0c);break;}

case2:{lcdwc(0x0e);break;}

case3:{lcdwc(0x0f);break;}

default:break;

)

)

〃实现清屏功能的子函数

voidclrlcd()

(

Icdwc(0x01);〃调用送控制字子程序;

)

〃正常读写之前的检测led控制状态;

voidwaitidle()

(

uchartmp;

rs=O;

rw=l;

e=l;

_nop_();

for(;;)

(

tmp=dataport;

tmp&=0x80;

if(tmp==0)

break;

)

e=0;

)

〃实现写字符功能;

voidIcdwd(ucharc)

(

waitidle();

rs=l;

rw=0;

dataport=c;

e=l;

_nop_();

_nop_();

e=0;

)

〃送控制字子程序(检测忙信号);

voidledwc(ucharc)

waitidle();

lcdwcn(c);//调用送控制字子程序(不检测忙信号);

)

〃送控制字子程序(不检测忙信号);

voidlcdwcn(ucharc)

(

rs=O;

rw=0;

dataport=c;

e=l;

_nop_();

e=0;

)

〃设置第xpos,ypos光标所在的地址;

voidIcdpos(ucharxpos,ucharypos)

(

uchartmp;

xpos&=0x0f;

ypos&=0x01;

if(ypos==0)

tmp=xpos;

else

tmp=xpos+0x40;

tmp|=0x80;

lcdwc(tmp);

)

//复位LCD控制器;

voidlcdreset()

(

mdelay(15);

lcdwc(0x38);

lcdwc(0x08);

lcdwc(OxOl);

lcdwc(0x06);

lcdwc(OxOc);

)

//----------------------以下是用led实现现实一个字符串的主函数

voidmain()

(

ucharxpos,ypos;

uchar*s="8Oc5I!";

xpos=8;

ypos=0;

lcdreset();

clrlcd();

setcur(curflash);

writestring(s,xpos,ypos);

for(;;)

{;}

---------------------以下实现让字母人围绕着LCD屏转动

voidmain()

charxpos,ypos;

while(l)

p37=0;

ypos=0;

for(xpos=0;xpos<=15;xpos++)

(

lcdreset();

clrlcd();

setcur(nocur);

writechar('A;xpos,ypos);

mdelay(3000);

if(xpos==15)

(

lcdreset();

clrlcd();

setcur(nocur);

ypos=l;

//lcdwc(0xl8);

for(xpos=15;xpos>=0;xpos—)

lcdreset();

clrlcd();

setcur(nocur);

writechar('A',xpos,ypos);

mdelay(3000);

if(xpos==-l)

break;

ypos=0;

----------------实现上行动态显示娄浩很性感,下行静态显示80C51----------------------------

添加以上的LCD显示驱动包。。。。。。。。。

voidmain()

(

uchars[]="louhaoissexy!";

charxpos,ypos;

lcdreset();

clrlcd();

setcur(nocur);

writestring("80c511',6,1);

while(l)

(

p37=0;

ypos=0;

for(xpos=0;xpos<=15;xpos++)

(

writechar(s[xposj,xpos,ypos);

mdelay(5000);

if(xpos==15)

{lcdreset();

clrlcd();

setcur(nocur);

writestring(M80c5

break;

)

}

)

)

说明:LCD显示比起9段数码显示更加高级且由于有了现成的驱动程序包因而用户只需要

把握如何与驱动程序之间建立联系(接口)便可以了!在其他的工程项目应用场合要尽量使

用led来显示,当然是在成本允许的情况下!(用户只需关注以下几点:1.写字符函数

writechar(uchars,ucharxpos,ucharypos)2.写字符串函数writestring(uchar*s,ucharxpos,uchar

ypos)3.setcur(ucharset)在使用时只需对函数中的各个参数作出合理的设置便可其他的程序

则套用周坚老师的模式便可!)

(7)12c总线驱动程序包

启动HC总线

---------------------------------*/

voidstart(void)

sda=l;

_nop_();_nop_();

scl=1;

_nop_();_nop_();_nop_();_nop_();_nop_();

sda=0;

_nop_();_nop_();__nop_();_nop_();_nop_();

scl=0;

)

停止nc总线

--------------------------------------------------*/

voidstop(void)

(

sda=0;

_nop_();

scl=l;

_nop_();_nop_();_nop_();_nop_();_nop_();

sda=1;

_nop_();_nop_();_nop_();_nop_();_nop_();

scl=0;

)

应答IIC总线

--------------------*/

voidack(void)

sda=0;

_nop_();_nop_();_nop_();

scl=l;

_nop_();_nop_();_nop_();_nop_();_nop_();

scl=0;

_nop__();_nop_();

非应答nc总线

-----------------------*/

voidnoack(void)

(

sda=l;

_nop_();_nop_();_nop_();

scl=1;

_nop_();_nop_();_nop_();_nop_();_nop_();

scl=0;

_nop_();_nop_();

发送一个字节

--------------------------------------------------*/

voidsend(unsignedcharc)

(

unsignedcharbitcounter=8;

unsignedchartemp;

temp=c;

scl=0;

_nop.();_nop_();_nop_();_nop_();_nop_();

if((temp&0x80)==0x80)

sda=l;

else

sda=0;

scl=l;

temp=c«l;

c=temp;

bitcounter—;

while(bitcounter);

scl=0;

读入一个字节并返回

--------------------------*/

unsignedcharread(void)

unsignedchartemp=O;

unsignedchartemp1=0;

unsignedcharbitcounter=8;

sda=l;

do

(

scl=0;

_nopj);_nop_();_nop_();_nop_();_nop_();

scl=l;

_nop__();_nop_();_nop_();_nop_();_nop_();

if(sda)

temp=temp|0x01;

else

temp=temp&0xfe;

if(bitcounter-l)

(

templ=temp«l;

temp=temp1;

)

bitcounter—;

)

while(bitcounter);

return(temp);

写入数据

-----------------------------------------*/

voidwr_to_rom(unsignedcharshuju[],unsignedcharaddress,unsignedcharnum)

(

unsignedchari;

unsignedchar*pshuju;

pshuju=shuju;

fbr(i=0;i<num;i4-+)

(

start();

send(addwr);〃写入芯片地址

ack();

send(address+i);〃写入存储地址

ack();

send(*(pshuju+i));〃写数据

ack();

stop();

mdelay(20);

读出数据

--------------------------------------------------*/

voidrd_from_rom(unsignedcharshuju[],unsignedcharaddress,unsignedcharnum)

(

unsignedchari;

unsignedchar*pshuju;

pshuju=shuju;

fbr(i=O;i<num;i++)

(

start();〃写入芯片地址

send(addwr);

ack();

send(address+i);〃写入存储地址

ack();

start();

send(addrd);〃读入地址

ack();

*(pshuju+i)=read();〃读数据

scl=0;

noack();

stop();

)

)

说明:以上程序为I2C总线驱动程序(模拟)用时只需关注其中的两个函数便可:

rd_from_rom(shuzu[],address,num)^nwr_to_rom(shuzu[],address,num).12c总线的应用还需要继

续进行练习我仅仅只是一知半解而己!而且还有周坚老师的一个实验没有完成以后继续

做।I।11।।111

-------------------------以下为利用12c总线实现的对EEPROM的读和写-------------

voidmain()

(

ucharnum[]={0x7f,0x6f,0x77,0x06,0x5b};

uchari;

wp=0;〃关写保护如若开则写不进;

wr_to_rom(num,1,4);

for(i=0;i<5;i++)

num[iJ=0x3f;

P2=0x03;

rd_from_rom(num,1,5);

for(i=0;i<5;i++)

p37=l;

PO=num[i];

mdelay(lOOO);

p37=O;

)

)

注:参考浩豚公司的师访程序!

(8)数码管999数字计数程序(带有消影功能)非定时器应用

#include<reg52.h>

#defineuintunsignedint

#defineucharunsignedchar

voiddelay(uint);

sbitp37=P3A7;

ucharbai,shi,ge;

uintnum=0,a;

ucharwela[J={0x00,0x01,0x02};

ucharcodeshuma[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f};

voidmain()

(

while(l)

(

for(num=0;num<1000;num++)

{

bai=num/100;

shi=num%100/10;

ge=num%10;

for(a=200;a>0;a--)//a的值可以实现数字显示速度的快慢;

(

P2=wela[2];

p37=l;

P0=shuma[ge];

p37=0;

delay(lOO);

PO=Oxff;//消影

P2=wela[l];

p37=l;

PO=shuma[shiJ;

p37=0;

delay(lOO);

PO=Oxff;//消影

P2=wela[0];

p37=l;

PO=shumafbai];

p37=0;

delay(lOO);

PO=Oxff;//消影

voiddelay(uinti)〃用延时程序实现数码管的动态显示;

(

while(i—);

)

注:消影功能即是让数码管的不该亮的部分熄灭;

(9)按键计数程序(待改进不太稳定而且只能计数太5次)〃有待改进的程月:用绿色

#include<reg52.h>

#include<intrins.h>

#defineuintunsignedint

#defineucharunsignedchar

voiddelay(uint);

voidinit();

sbitp37=P3八7;

sbitp34=P3A4;

ucharbai.shi,ge;

uintnum,temp;

ucharwela|]={0x00,0x01,0x02};

ucharcodeshuma[]={0x3f\0x06,0x5b,0x4f,0x66t0x6d.0x7d,0x07,0x7f,0x6f|;

voidmain()

init();

whiled)

temp+=TH0;

temp=_crol_(temp.8):

temp+=TL0;

num=temp;

ge=num%10:

shi=num%100/10;

bai=num/i00;

P2=wela[0];

p37=l;

P()=shuma[baiJ;

p37=0;

PO=Oxff;

delay(250);

P2=wela[l]:

p37=l;

PO=shuma[shi];

p37=O;

PO=Oxff;

delay(250);

P2=wela[2];

p37=l;

PO=shuma[ge];

p37=O;

PO=Oxff;

delay(250);

)

)

voiddelay(uinti)

|

while。一);

)

voidinit()

{

TMOD=0X05;//jishuqi0工作方式1:(16位定时计数器)

//EA=1;

//ET()=I;

THO=255;

TL0=255;

TF0=0;

TRO=1;

num=O;

I

说明:此程序利用到了定时器TO的计数功能,注意在计数功能中一定不能开定时器中断,

定时器中断仅适用于定时器。存在的问题:此处三位数码管只能实现0—255的按键记数,

而且计数值有时不太稳定,即有时下一次P3.4口的按键可能会出现两个甚至两个以上的数

字累加,造成计数不准确,原因是按键没有加入去抖程序和松手检测但是数码管的动态显示

就不能加入这两个因为加后必出现停顿而停顿即意味着有两个数码管不能被点亮。下面的程

序是采用数码管的静态显示,同时使用T0的计数功能,此时可以在程序中加入松手检测和

去抖过程。具体实现如下:

#include<reg52.h>

#include<intrins.h>

#defineuintunsignedint

#defineucharunsignedchar

voiddelay(uint);

voidinit();

sbitp37=P3A7;

sbitp34=P3A4;

//ucharbai,shi,ge;

uintnum;

ucharcodeshuma[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f};

voidmain()

(

init();

while(l)

(

if(p34==0)

(

if(TL0==10)

TL0=0;

num=TL0;

delay(lOOO);

if(p34==0)

(

while(!p34);

num=TL0;

p37=l;

P0=shumafnum];

p37=0;

I

)

voiddelay(uinti)

(

while(i—);

)

voidinit()

(

TMOD=0X05;//jishuqi0工作方式1;(16位定时计数器)

//EA=1;

//ET0=l;

TH0=255;

TL0=255;

TF0=0;

TR0=l;

num=0;

P2=0x00;

说明:这个程序的效果还可以就是有一条计数值只能是从0—9因而限制了其应用!

当然了这个程序还可以利用外部中断来完成。每按一次发生一次中断则计数一次。

以下程序可以实现六位按键计数功能:利用定时器。工作于计数方式1,利用定时器1工作

于定时方式1并能产生1.2—1.3MS的定时中断,以对六位选通的数码管进行轮翻扫描实现

动态显示。程序中的参数是经我一再调试最终产生的无闪烁参数:具体程序如下

#include<reg52.h>

#include<intrins.h>

#defineuintunsignedint

#defineucharunsignedchar

voiddelay(uint);

voidinit();

sbitp37=P3A7;

sbitp34=P3八4;

uintnum;

ucharwei,du,bit_wei[6];

ucharwela[]={0x00,0x01,0x02,0x03,0x04,0x05};

ucharcodeshuma[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f};

voidmain()

(

init();

while(l)

(

num=TH0*256+TL0;

bit_wei[5]=0;

bit_wei[4]=num/10000;

bit_wei[3]=num/1000%10;

bit_wei[2]=num/100%10;

bit_wei[l]=num/10%10;

bit_wei[0]=num%10;

p37=l;

P2=wela[wei];

P0=shuma[bit_wei[du]];

p37=0;

delay⑸;

if(wei==5)

wei=0;

if(du==0)

du=5;

voidinit()

TMOD=OX15;〃定时器1工作于定时方式1,定时器0工作于记数方式1;

EA=1;

ET1=1;

THO=O;

TLO=O;

TH1=(65536-1200)/256;

TL1=(65536-1200)%256;〃定时3毫秒;

TF0=0;

TR0=l;

TR1=1;

num=0;

wei=0;

du=5;

)

voidtimerl()interrupt3

(

TH1=(65536-1200)/256;

TLl=(65536-1200)%256;

wei++;

du-;

voiddelay(uinti)

(

while(i—);

}

说明:其中NUM的值通过按键次数来由定时器0获得。

(10)普通时钟程序(存在问题:调节一个键的时候其他数码管跟着变化!)

#include<reg52.h>

#defineucharunsignedchar

#defineuintunsignedint

sbitp37=P3A7;

sbitpl6=PlA6;

sbitp32=P3八2:

sbitp33=P3A3;

bitdingshi;//是否启动定时功能标识位;在中断服务程序中设置:

ucharcode

huayang[]={0x7f.0xbf.0xdf.0xef,0xf7.0xfb,0xfd.0xfe,0xff.0xff,0x00.0,0x55,0x55.0xaa,0xaa);

ucharcodeshuma[]={0x3f.0x06,0x5b.0x4f,0x66,0x6cL0x7d.0x07,0x7f,0x6f}:

ucharcodewela[]={0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07);

ucharhour,min,sec;//时,分,秒的计数器及用于设置定时时间的中间计数器

ucharflag;〃数码管位选标志

uchara;〃实现1秒定时功能控制寄存器;

ucharj;〃花样流水灯控制;

voidinit()

TMOD=OX11;〃定时器1工作方式1定时功能;定时器0工作方式1定时功能;

TH0=(65536-50000)/256;〃设置各个定时计数器的处置

TL0=(65536-50000)%256;

TH1=(65536-2000)/256;

TLl=(65536-2000)%256;

〃m=o;//电平触发

EA=I;〃开总中断

ET0=l;〃开定时计数器0中断

ET1=1;//开定时计数器1中断

TR0=l;//启动定时器0

TR1=1;//启动定时器1

hour=00;

min=00;

sec=00;

flag=O;

a=0;

i=0;

)

voidmsdelay(uinti)

(

while(i—);

)

voiddisplayO

(

p37=1;P2=wela[0];P0=shuma[hour/l0];p37=0;

p37=l;P2=wela[1];P0=shuma[hour%10];p37=0;

p37=1;P2=wela[2];P0=0x40;p37=0;

p37=1;P2=wela[3];P0=shuma[min/l0];p37=0;

p37=1;P2=wela[4];P0=shuma[min%10];p37=0;

p37=l;P2=wela[5];P0=0x40;p37=0;

p37=1;P2=wela[6];P0=shuma[sec/l0];p37=0;

p37=l;P2=wela[7];P0=shuma[sec%10];p37=0;

)

ucharkeyscan。//行列交叉扫描法检测键盘;

(

uchartemp,tmp;

P3=OxfO;

temp=P3;

temp=temp&0xf0;

if(temp!=OxfO)

msdelay(10000);

temp=P3;

temp=temp&OxfO;

if(temp!=OxfO)

(

temp=P3;

temp=temp&OxfO;

)

)

P3=OxOf;

tmp=P3;

tmp=tmp&OxOf;

if(tmp!=OxOf)

(

msdelay(1OOOO);

tmp=P3;

tmp=tmp&OxOf;

if(tmp!=OxOf)

(

tmp=P3;

tmp=tmp&OxOf;

)

)

temp=temp+tmp;

returntemp;

)

〃定时计数器1中断服务子程序;

voidtimerl()interrupt3

(

TH1=(65536-2000)/256;

TLl=(65536-2000)%256;

switch(flag)//实现对数码管的位选及显示;

{

case0:p37=1;P2=wela[0];PO=shuma[hour/10];p37=0;msdelay(lOO);break;

casel:p37=l;P2=wela[l];PO=shuma[hour%10];p37=0;msdelay(lOO);break;

case2:p37=1;P2=wela[2];P0=0x40;p37=0;msdelay(1OO);break;

case3:p37=l;P2=wela[3];P0=shuma[min/10];p37=0;msdelay(100);break;

case4:p37=1;P2=wela[4];P0=shuma[min%10];p37=0;msdelay(lOO);break;

case5:p37=l;P2=wela[5];P0=0x40;p37=0;msdelay(100);break;

case6:p37=1;P2=wela[6];PO=shuma[sec/l0];p37=0;msdelay(l00);break;

case7:p37=1;P2=wela[7];PO=shuma[sec%10];p37=0;msdelay(lOO);break;

defaulcbreak;

}

flag++;

if(flag==8)

flag=O;

//定时器。中断服务子程序:包括了时间更新,花样流水灯显示,定时器开启控制,扬声器

开启控制;

voidtimer()()interrupt1

(

TH0=(65536-50000)/256;〃设置各个定时计数器的处置

TL0=(65536-50000)%256;

a++;

if(a==20)

(

a=0;

sec++;

if(sec==60)

(

sec=0;

min++;

if(min==60)

(

min=0;

hour++;

if(hour==24)

hour=0;

i++;

if(i==16)

i=0;

Pl=huayang[i];

)

voidmain()

(

ucharnum;

uchartemp;

init();

while(l)

{

num=keyscan();

switch(num)//键值确定及其对应键功能服务程序;

{

case0x7e:hour++;if(hour==24)hour=0;display();break;

case0x7d:{hour—;if(hour==255)hour=23;break;}

case0x7b:{min++;if(min==60)min=0;display();break;)

case0x77:{min—;if(min==255)min=59;display();break:}

caseOxbe:{sec++;if(sec==60)sec=0;display();break;}

caseOxbd:{sec—:if(sec==255)sec=59:display():break:}

caseOxbb:;

caseOxb7:;

caseOxde:;

caseOxdd:;

//caseOxdb:p32=O;break;

//caseOxd7:p33=O;break;

default:break;

)

对以上程序的改进:实现的功能:1.时钟显示。2.定时动作。其中定时到可以无限地做定时

到得动作而不是原来的一分钟!而且定时动作的取消可以通过手动按键来实现!

#include<reg52.h>

#defineucharunsignedchar

#defineuintunsignedint

sbitp37=P3A7;

sbitpl6=PlA6;

sbitp30=P3八0;

sbitp31=P3Al;

sbitp32=P3A2;

sbitp33=P3A3;

//bitdingshi;〃是否启动定时功能标识位;在中断服务程序中设置;

ucharcode

huayang[]={0x7f,0xbf,0xdf,0xef,0xf7,0xfb,0xfd,0xfe,0xff,0xff,0x00,0,0x55,0x55,0xaa,0xaa,0xaa,

Oxaa,0x55,0x55,0,0x00,Oxff,Oxff,Oxfe,Oxfd,Oxfb,Oxf7,Oxef,Oxdf,Oxbf,Ox7f};

ucharcodeshuma[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f};

ucharcodewela[]={0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07);

ucharhour,min,sec,sethour,setmin;〃时,分,秒的计数器及用于设置定时时间的中间计数器

ucharHag;//数码管位选标志

uchara,b,c,d,e;〃实现I秒定时功能控制寄存器;

uchari;//花样流水灯控制;

voidinit()

(

TMOD=OXU;〃定时器1工作方式1定时功能;定时器0工作方式1定时功能;

TH0=(65536-50000)/256;〃设置各个定时计数器的处置

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论