#include<reg52h>
#include<defineh>
void delay(uint z)
{
uint x,y;
for(x=z;x>0;x--)
for(y=110;y>0;y--);
}
void didi()
{
beep=0;
delay(50);
beep=1;
delay(100);
beep=0;
delay(50);
beep=1;
}
void write_com(uchar com)
{
rs=0;
lcden=0;
P0=com;
delay(5);
lcden=1;
delay(5);
lcden=0;
}
void write_date(uchar date)
{
rs=1;
lcden=0;
P0=date;
delay(5);
lcden=1;
delay(5);
lcden=0;
}
void init()
{
uchar num;
EA=1;
EX0=1;
IT0=1;
dula=0;
wela=0;
lcden=0;
// set_time();
set_alarm(14,13,10);
write_ds(0x0B,0x26);
read_ds(0x0c);
// fen=59;
// miao=53;
// shi=23;
write_com(0x38);
write_com(0x0c);
write_com(0x06);
write_com(0x01);
write_com(0x80);
for(num=0;num<15;num++)
{
write_date(table[num]);
delay(5);
}
write_com(0x80+0x40);
for(num=0;num<12;num++)
{
write_date(table1[num]);
delay(5);
}
}
void write_sfm(uchar add,uchar date)
{
uchar shi,ge;
shi=date/10;
ge=date%10;
write_com(0x80+0x40+add);
write_date(0x30+shi);
write_date(0x30+ge);
}
void keyscan()
{
rd=0;
if(flag1==1)
{
if(s2==0)
{
delay(5);
if(s2==0)
{
while(!s2);
flag1=0;
}
}
if(s3==0)
{
delay(5);
if(s3==0)
{
while(!s3);
flag1=0;
}
}
}
if(s1==0)
{
delay(5);
if(s1==0)
{ s1num++;
flag=1;
flag1=0;
while(!s1);
if(s1num==1)
{
TR0=0;
write_com(0x80+0x40+10);
write_com(0x0f);
}
}
if(s1num==2)
{
write_com(0x80+0x40+7);
}
if(s1num==3)
{
write_com(0x80+0x40+4);
}
if(s1num==4)
{
s1num=0;
write_com(0x0c);
flag=0;
write_ds(0,miao);
write_ds(2,fen);
write_ds(4,shi);
}
}
if(s1num!=0)
{
if(s2==0)
{
delay(1);
if(s2==0)
{
while(!s2);
if(s1num==1)
{
miao++;
if(miao==60)
miao=0;
write_sfm(10,miao);
write_com(0x80+0x40+10);
}
if(s1num==2)
{
fen++;
if(fen==60)
fen=0;
write_sfm(7,fen);
write_com(0x80+0x40+7);
}
if(s1num==3)
{
shi++;
if(shi==24)
shi=0;
write_sfm(4,shi);
write_com(0x80+0x40+4);
}
}
}
if(s3==0)
{
delay(1);
if(s3==0)
{
while(!s3);
if(s1num==1)
{
/ if(miao==0)
{
miao=59;
write_sfm(10,miao);
write_com(0x80+0x40+10);
}/
miao--;
if(miao==-1)
miao=59;
write_sfm(10,miao);
write_com(0x80+0x40+10);
}
if(s1num==2)
{
fen--;
if(fen==-1)
fen=59;
write_sfm(7,fen);
write_com(0x80+0x40+7);
}
if(s1num==3)
{
shi--;
if(shi==-1)
shi=23;
write_sfm(4,shi);
write_com(0x80+0x40+4);
}
}
}
}
}
void write_ds(uchar add,uchar date)
{
dscs=0;
dsas=1;
dsds=1;
dsrw=1;
P0=add;
dsas=0;
dsrw=0;
P0=date;
dsrw=1;
dsas=1;
dscs=1;
}
uchar read_ds(uchar add)
{
uchar ds_date;
dsas=1;
dsds=1;
dsrw=1;
dscs=0;
P0=add;
dsas=0;
dsds=0;
P0=0xff;
ds_date=P0;
dsds=1;
dsas=1;
dscs=1;
return ds_date;
}
void set_time()
{
write_ds(4,10);
write_ds(2,32);
}
void set_alarm(uchar ashi,uchar afen,uchar amiao)
{
write_ds(1,amiao);
write_ds(3,afen);
write_ds(5,ashi);
}
void main()
{
init();
while(1)
{
keyscan();
if(flag1==1)
didi();
if(flag==0)
{
miao=read_ds(0);
fen=read_ds(2);
shi=read_ds(4);
write_sfm(10,miao);
write_sfm(7,fen);
write_sfm(4,shi);
}
}
}
void exter() interrupt 0
{ uchar c;
flag1=1;
c=read_ds(0x0c);
}
用的是DS12C887液晶
外部中断与晶振无关,只与INT0和INT1的电平有关。下降沿和低电平触发是根据IT0和IT1的设置来判断的,当使用的是外部中断0,如果IT0=1,则当INT0的电平由高电平变为低电平那一瞬间(即下降沿)产生中断。如果IT0=0,则当INT0的电平是低电平时产生中断。当使用的是外部中断1,分析和外部中断0一样
下降沿触发是锁存中断信号——D触发器记忆的,意即:即使当时CPU来不及响应中断,外部中断信号撤消后,由于D触发器的记忆作用,消失的中断信号仍然有效,直到被响应并进入中断ISR,记忆的中断信号才会由硬件清除;
而低电平触发是即时的,当外部中断信号撤消时,中断申请信号随之消失。也就是:如果在外部中断信号作用申请期间,CPU来不及响应此中断,那么有可能,这次中断申请就漏掉了。——显然下降沿触发不会漏掉短暂的中断申请信号。
低电平触发信号低电平宽度显然不能大于ISR响应执行时间,否则,当ISR完成,RETI退出中断时,将再次被低电平触发,如此反复响应中断。因此我们习惯用下降沿触发,以保证不会有中断信号的遗漏
关于51单片机外部中断0触发方式,边沿触发方式和电平触发方式不同,边沿触发方式只在触发信号下降沿(现在有单片机也可以设置上升沿触发)触发一次。所以在设置好相关外部中断以后,等待触发就可以了,不需要额外处理。
IT0=1;//边沿触发方式,还要置位外部中断0允许位及总中断位
进入外部中断0程序的方式是由外部中断触发信号控制的。
//if(达到某条件)//不需要判断,否则就失去中断的意义了
//{
//P32=0;//不需要这样处理
//}//然后就进入外部中断0了//进入终端是随机的
void exter0()
{
P32=1;//不需要这样处理
…………
}
电平触发就是说只有这个信号为低电平的时候,才会发出有效信号,而边沿触发(下降沿有效)的意思是只有在发生由高电平向低电平变化的时候,此时发出的才是有效信号。假如说,你的51单片机的p32和33分别外接两个可调节高低电平的开关A和B,32是边沿触发,33是电平触发。按下A键的那一刹那,就是还没有按到底,这个过程发出的是有效信号。按下B的时候,只有按到最底部,就是实实在在的低电平的时候,才会发出有效信号。
89C51/52的中断系统有5个中断源 ,2个优先级,可实现二级中断嵌套 。
1、(P32)可由IT0(TCON0)选择其为低电平有效还是下降沿有效。当CPU检测到P32引脚上出现有效的中断信号时,中断标志IE0(TCON1)置1,向CPU申请中断。
2、(P33)可由IT1(TCON2)选择其为低电平有效还是下降沿有效。当CPU检测到P33引脚上出现有效的中断信号时,中断标志IE1(TCON3)置1,向CPU申请中断。
3、TF0(TCON5),片内定时/计数器T0溢出中断请求标志。当定时/计数器T0发生溢出时,置位TF0,并向CPU申请中断。
4、TF1(TCON7),片内定时/计数器T1溢出中断请求标志。当定时/计数器T1发生溢出时,置位TF1,并向CPU申请中断。
5、RI(SCON0)或TI(SCON1),串行口中断请求标志。当串行口接收完一帧串行数据时置位RI或当串行口发送完一帧串行数据时置位TI,向CPU申请中断。
IE寄存器:
中断允许控制寄存器分为两层结构,第一级结构为中断允许总控制EA,只有当EA处于中断允许状态,中断源中断请求才能够得到允许;当EA处于不允许状态时,无论IE寄存器中其他位处于什么状态,中断源中断请求都不会得到允许。第二级结构为5个中断允许控制位,分别对应5个中断源的中断请求,当对应中断允许控制位为1时,中断源中断请求得到允许。
EX0:外部中断0允许位。EX0=1,允许外部中断0中断;EX0=0,禁止外部中断0中断。当EX0=1( SETB EX0 )时,同时单片机P32引脚上出现中断信号时,单片机中断主程序的执行而“飞”往中断服务子程序,执行完后通过中断返回指令RET 动返回主程序。当EX0=0( CLR EX0)时,即使单片机P32引脚上出现中断信程序也不会从主程序“飞” 出去执行,因为此时单片机的CPU相当于被“堵上了耳朵”,根本接收不到P32引脚上的中断信号,但是这并不表示这个信号不存在。如果单片机的CPU有空查一下TCON中的IE0位,若为1就说明有中断信号出现过。
ET0:T0溢出中断允许位。ET0=1,允许T0中断;ET0=0,禁止T0中断。
EX1:外部中断1允许位。EX1=1,允许外部中断1中断;EX1=0,禁止外部中断1中断。当EX1=1( SETB EX1)时,并且外部P33引脚上出现中断信号时,单片机CPU会中断主程序而去执行相应的中断服务子程序;当EX1=0( CLR EX1)时使外部P33引脚上即使出现中断信号,单片机的CPU也不能中断主程序转而去行中断服务子程序。 [3] 因此,可以这样认为,EX0和EX1是决定CPU能否感觉到外部引脚P32P33上的中断信号的控制位。
ET1:T1溢出中断允许位。ET1=1,允许T1中断;ET1=0,禁止T1中断。
ES:串行中断允许位。ES=1,允许串行口中断;ES=0,禁止串行口中断。
EA:中断总允许位。EA=1,CPU开放中断;EA=0,CPU禁止所有的中断请求。总允许EA好比一个总开关。EA就相当于每家水管的总闸,如果总闸不开,各个龙头即使开了也不会有水;反过来,如果总闸开了而各个分闸没开也不会有水,所当我们想让P32和P33引脚上的信号能够中断主程序则必须将EA位设置为0(CLR EA)。
TCON寄存器:
各位的标识如下:
TF1:定时器1溢出标志位。当定时器1计满溢出时,由硬件使TF1置1,并且申请中断,进入中断服务程序,有硬件自动清0 ,在查询方式下用软件清0
TR1:定时器运行控制位,TR1置1是开启定时器1,TR1置0时关闭定时器1
TF0:定时器0溢出标志位。当定时器0计满溢出时,由硬件使TF0置1,并且申请中断,进入中断服务程序,有硬件自动清0 ,在查询方式下用软件清0
TR0:定时器运行控制位,TR0置1是开启定时器0,TR0置0时关闭定时器0
IE1:外部中断1请求标志位。
IT1:外部中断1触发方式选择位。当IT1置0时,为低电平触发;当IT1置1时,为下降沿触发。
IE0:外部中断0请求标志位。
IT0:外部中断0触发方式选择位。当IT0置0时,为低电平触发;当IT0置1时,为下降沿触发。
51单片机外部中断响应条件:
1、中断源有中断请求;
2、中断源的中断允许位为1(设置IE寄存器相关位);
3、CPU开中断(设置IE寄存器开中断,即EA=1)
CPU时序的有关知识:
振荡周期:为单片机提供定时信号的振荡源的周期(晶振周期或外加振荡周期)
状态周期:2个振荡周期为1个状态周期,用S表示。
机器周期:1个机器周期含6个状态周期,12个振荡周期。
指令周期:完成1条指令所占用的全部时间,它以机器周期为单位。
定时器的其他知识点:
1、51单片机有两组定时器/计数器,因为既可以定时,又可以计数,故称之为定时器/计数器。
2、定时器/计数器和单片机的CPU是相互独立的。定时器/计数器工作的过程是自动完成的,不需要CPU的参与。
3、51单片机中的定时器/计数器是根据机器内部的时钟或者是外部的脉冲信号对寄存器中的数据加1。
4、有了定时器/计数器之后,可以增加单片机的效率,一些简单的重复加1的工作可以交给定时器/计数器处理。CPU转而处理一些复杂的事情。同时可以实现精确定时作用。
与定时器/计数器有关的寄存器:
1、TMOD寄存器
2、TCON寄存器
3、IE寄存器
4、THx/TL寄存器
工作方式寄存器TMOD:
工作方式寄存器TMOD用于设置定时/计数器的工作方式,低四位用于T0,高四位用于T1。其格式如下:
M1M0:工作方式设置位。定时/计数器有四种工作方式。一般我们厅方式1和方式2:
控制寄存器TCON:
TCON的低4位用于控制外部中断,已在前面介绍。TCON的高4位用于控制定时/计数器的启动和中断申请。其格式如下:
TF1(TCON7):T1溢出中断请求标志位。T1计数溢出时由硬件自动置TF1为1。CPU响应中断后TF1由硬件自动清0。T1工作时,CPU可随时查询TF1的状态。所以,TF1可用作查询测试的标志。TF1也可以用软件置1或清0,同硬件置1或清0的效果一样。
TR1(TCON6):T1运行控制位。TR1置1时,T1开始工作;TR1置0时,T1停止工作。TR1由软件置1或清0。所以,用软件可控制定时/计数器的启动与停止。
TF0(TCON5):T0溢出中断请求标志位,其功能与TF1类同。
TR0(TCON4):T0运行控制位,其功能与TR1类同。
IE中断开关寄存器:
用于开启cpu中断和对应的中断位。
THx和TL定时/计数存储寄存器:
THx存储高8位数据,TLx存储低8位数据。
定时器/计算器初值计数公式:
计数个数与计数初值的关系为:X=2^n-N
N是需要计数的值;n与设置定时器/计数器的工作方式有关(可能为8、13、16);X是需要设置在THx和TLx的初值。
使用定时器/计算器的初始化流程:
1、对TMOD赋值,以确定T0和T1的工作方式。
2、计算初值,并将其写入TH0、TL0或TH1、TL1。
3、中断方式选择,则对EA赋值,开放定时器中断。
4、使TR0或TR1置位,启动定时/计数器定时或计数。
可以打个比方,每天上班你都随时需要知道你同事的工作进度情况,你是希望你不停地打个电话去问“你做完了吗”,还是希望他做完了主动打个电话给你讲“我做完了,我们谈谈吧”。这就是中断的意义,在不需要的时候不影响处理 器做其它的事情,提高效率,增强程序的实时性。
51单片机外部中断使用方法:
1、51单片机的外部中断int0对应的引脚为p32。
2、设置寄存器,打开终端并选择中断的触发方式。
EA为整体中断允许位,首先要将EA置1,打开中断。
EX0为外部中断INT0,置1开启。
IT0寄存器:置0为低电平触发,置1为下降沿触发。
3、编写中断函数,int0的中断编号为0,这里使用中断控制led的点亮与熄灭。
中断函数格式一般为:
void 函数名称(void) interrupt 中断编号 using 寄存器组编号{语句;}
4、编译程序,并导入单片机对程序进行测试。
以上就是关于51单片机c语言全部的内容,包括:51单片机c语言、单片机外部中断是不是和晶振有关 下降沿和低电平触发是根据谁判断的、51单片机外部中断0触发方式等相关内容解答,如果想了解更多相关内容,可以关注我们,你们的支持是我们更新的动力!
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)