为啥无法进中断?
#include <intrins.h>
#define uchar unsigned char
#define uint unsigned int
sbit jw=P1^3; //继电器开关
sbit beep=P2^6; //蜂鸣器
sbit PWM_OUT = P2^7; //PWM输出接口(p2.7连接舵机的信号线)
sbit sck=P2^3; //ds1302
sbit io = P2^4;
sbit res = P2^5;
sbit rs=P1^2; //rs1602
sbit rw=P1^1; //rw
sbit en=P1^0; //en
bit OUT; //高低电平切换标志位
uchar tmp;
uchar SG1; //舵机角度
uint a;
uint d=0;
uchar time_date[7] ={15,5,22,5,17,38,00};//年,yue ,日,星期, 时,分,秒
uchar write_add[7] ={0x8c,0x88,0x86,0x8a,0x84,0x82,0x80}; //写的地址
uchar read_add[7] ={0x8d,0x89,0x87,0x8b,0x85,0x83,0x81}; //读的地址 年 月 日 星期 时 分 秒
uchar disp[16],dispb[16];
uchar nian,nian1,nian2,yue,yue1,yue2,ri,ri1,ri2,zhou1,zhou2,shi,shi1,shi2,fen1,fen2,miao1,miao2;
uchar openri1,openri2,openshi1,openshi2,openfen1,openfen2,openmiao1,openmiao2;
//void init(); //串口初始化
// void ctrl(); //接收处理函数
// void write_ds1302_byte(uchar date);
// uchar read_ds1302(uchar add); //返回的为十六进制数
// void read_rtc();
// void time_pros();
// void time_pros0();
// void display1();
// void ini1602();
// void baocun();
void delay(int z)
{
int x,y;
for(x=z;x>0;x--)
for(y=110;y>0;y--);
}
void write_cmd(uchar cmd) //1602
{
rs=0;
P0=cmd;
delay(5);
en=1;
delay(5);
en=0;
}
void write_date(uchar date) //1602
{
rs=1;
P0=date;
delay(5);
en=1;
delay(5);
en=0;
}
void ini1602() //1602初始化
{
rw=0 ;
rs=0 ;
en=0;
write_cmd(0x38); //16X2
write_cmd(0x0c); //
write_cmd(0x06); //
write_cmd(0x01); //清屏
}
void init() //串口初始化
{
SCON = 0x50; // REN=1允许串行接受状态,串口工作模式1,
TMOD = 0x21; // 定时器1工作于方式2,8位自动重载模式, 用于产生波特率
PCON &= 0x7f; // 波特率不倍增
// EA = 0;//中断总开关
TH0 = 0xFF; //16位计数寄存器T0高8位
TL0 = 0xF5; //16位计数寄存器T0低8位
ET0 = 1; //T/C0中断开关
TH1=TL1=0xFD; // 波特率9600 (本次测试采用晶振为11.0592)
ET1 = 0; //T/C0中断开关
EA=1;
TR1 = 1; //定时器1开始工作,产生波特率
TI=0;//发送标志位置0
RI=0; //接收标志位置0
ES=1;
}
void write_ds1302_byte(uchar date) //单字节写
{
uchar i;
for(i=0;i<8;i++ )
{
sck=0;
io=date&0x01;
date=date>>1;
sck=1;
}
}
uchar read_ds1302(uchar add)
{
uchar i,value;
res = 0;
_nop_();
sck = 0;
_nop_();
res = 1;
_nop_();
write_ds1302_byte(add);
for(i = 0;i<8;i++ )
{
value = value>>1; //value是字符型
sck = 0;
if(io == 1)
value = value|0x80;
sck = 1;
}
res = 0;
_nop_();
sck = 0;
_nop_();
sck = 1;
io = 0;
_nop_();
return value;
}
void read_rtc() //读出时间,存入数组中,十六进制形式
{
uchar i;
for(i= 0;i<7;i++)
{
time_date[i]=read_ds1302(read_add[i]);
}
}
void time_pros0() //把读出的时间转化十位个位
{
nian1=time_date[0]/16;
nian2=time_date[0]%16;
nian=nian1*10+nian2;
yue1=time_date[1]/16;
yue2=time_date[1]%16;
yue=yue1*10+yue2;
ri1=time_date[2]/16;
ri2=time_date[2]%16;
ri=ri1*10+ri2;
zhou1=time_date[3]/16;
zhou2=time_date[3]%16;
shi1=time_date[4]/16;
shi2=time_date[4]%16;
shi=shi1*10+shi2;
fen1=time_date[5]/16;
fen2=time_date[5]%16;
miao1=time_date[6]/16;
miao2=time_date[6]%16;
}
void baocun()
{
openri1=ri1;
openri2=ri2;
openshi1=shi1;
openshi2=shi2;
openfen1=fen1;
openfen2=fen2;
openmiao1=miao1;
openmiao2=miao2;
}
void time_pros() //存入数组
{
//年
disp[0]=nian1+'0'; //十位
disp[1]=nian2+'0'; //个位
disp[2]='-';
//月
disp[3]=yue1+'0'; //十位
disp[4]=yue2+'0'; //个位
disp[5]='-';
disp[6]=ri1+'0'; //日
disp[7]=ri2+'0';
disp[8]=shi1+'0';
disp[9]=shi2+'0';
disp[10]=':';
disp[11]=fen1+'0';
disp[12]=fen2+'0';
disp[13]=':';
disp[14]=miao1+'0';
disp[15]=miao2+'0';
dispb[0]='O';
dispb[1]='P';
dispb[2]='E';
dispb[3]='N';
dispb[4]=':';
dispb[5]=openri1+'0';
dispb[6]=openri2+'0'; //miao
dispb[7]=' ';
dispb[8]=openshi1+'0';
dispb[9]=openshi2+'0';
dispb[10]='-';
dispb[11]=openfen1+'0';
dispb[12]=openfen2+'0';
dispb[13]='-';
dispb[14]=openmiao1+'0';
dispb[15]=openmiao2+'0';
}
void display1() //
{
uchar i;
write_cmd(0x80); //第一行 实时时间 格式:年-月-日时-分-秒
for(i=0;i<16;i++)
{
write_date(disp[i]);
delay(30);
}
write_cmd(0x80+0x40); //第二行 开门时间记录
for(i=0;i<16;i++)
{
write_date(dispb[i]);
delay(10);
}
delay(20);
}
void T_C0 (void) interrupt 1 //定时器0中断子程序
{
EA=0;
d++ ;
if(d==300)
{SG1=90;beep=1;} //舵机归位
if(d==400)
{d=0;TR0=0;jw=1;} //关中断,继电器断开
if(OUT==0) //判断高低脉冲标志//
{
a= 0x0A*SG1+0x01F3;//0x0A是1度的时间长,0x01F3是0.5mS时间长。
a= 0xFFFF - a;//算出定时开始值
TH0 = a/0xFF; //16位计数寄存器T0高8位
TL0 = a%0xFF; //16位计数寄存器T0低8位
OUT = 1;//标志切换
PWM_OUT=1;//PWM输出高电平
}
else
{
a= 0x4E1F - (0x0A*SG1+0x01F3);//0x4E1F是20mS的时间长
a= 0xFFFF - a;//算出定时开始值
TH0 = a/0xFF;
TL0 = a%0xFF;
OUT = 0;
PWM_OUT=0;//PWM输出低电平
}
EA=1;
}
void ctrl(void) //接收处理函数
{
switch(tmp)
{
case '1':
jw=0;
beep=1;
SG1=130;//角度为130度
TR0 = 1; //T/C0启动开关(定时器)
// delay(100);
break;
case '2':
jw=0;
beep=1;
SG1=90;//角度为90度
TR0 = 1; //T/C0启动开关
delay(200);
break;
default: //其他
break;
}
}
void main()
{
init();
ini1602(); //1602初始化
while(1)
{
if(RI==1) // 是否有数据到来
{
EA=0;
RI = 0;
tmp = SBUF; // 暂存接收到的数据
EA=1;
ctrl();
}
read_rtc();
time_pros0();
baocun();
time_pros();
display1();
}
}
没看到有TR0=1这句话啊…………没让定时器0开始计时吧。
进入定时器0的时候你不要把总中断EA给关了,只关定时器0的中断就可以了!
main函数的定时器0中断没有打开。
感觉没有中断服务函数呢
中断服务程序是有的!
开中断是在ctrl函数里的!
在ctrl函数里面有!
调试过程中你可以在特定的地方加入让LED灯闪烁的语句(比如LED^=1,其中LED为某个I/O口的位定义),比如你的这个程序可以在ctrl函数的case0和case1中分别让不同的灯闪烁,通过观察LED灯有没有闪烁就可以直观的发现有没有执行这段程序。我觉得没进中断的原因就是没打开定时器,也就是说每次检测tmp都是执行default那段,也就没执行到TR0=1这句。
你把TH1=TL1=0XFD这句程序分开写,TH1=0XFD,TL1=0XFD。我觉得是这句有问题
主函数中,我只留那么if语句,其他都注释掉,可以进中断,不注释就不进中断
除了if语句就剩下6个函数,这六个函数你每次仅打开一个,看看能不能进中断,也可以试出是哪个函数导致的进不了中断。
现在发现可以进中断,但是进入中断再出来1602显示就不正常了,第一行全亮!第二行全灭!
看了一下不知道什么问题。不过我建议中断函数中不要执行那么长的程序,如果对OUT的状态判断确实要在中断发生时才检测,那可以定义一个标志位在中断函数中置位,然后在主函数的while(1)中检测这个标志位是否置位,如果是,就说明中断发生,然后执行对OUT的状态判断程序。
问题已解决,串口接收将查询法改成了中断法,可以进中断了,谢谢!
嗯。恭喜你!继续加油!
恩,那再看看是不是别的地方写错了