新手求助 stc89c52单片机 DS1302中的中断响应一些问题 大家对此有什么看法
/*------------------------------------------------*/
#include<reg52.h>
#include<intrins.h>
#define uchar unsigned char
#define uint unsigned int
uchar dis_time_buf[16]={0};
sbit pwm_v=P0^7;//水平方向信号
sbit pwm_h=P1^7;//垂直方向信号
uchar sev;
uchar seh;
uchar count;//t0中断次数
//LCD引脚定义
sbit RS = P1^0; //定义端口
sbit RW = P1^1;
sbit EN = P2^5;
#define RS_CLR RS=0
#define RS_SET RS=1
#define RW_CLR RW=0
#define RW_SET RW=1
#define EN_CLR EN=0
#define EN_SET EN=1
#define DataPort P0
//DS1302引脚定义
sbit RST=P2^0;
sbit IO=P2^1;
sbit SCK=P2^2;
//DS1302地址定义
#define ds1302_sec_add 0x80 //秒数据地址
#define ds1302_min_add 0x82 //分数据地址
#define ds1302_hr_add 0x84 //时数据地址
#define ds1302_date_add 0x86 //日数据地址
#define ds1302_month_add 0x88 //月数据地址
#define ds1302_day_add 0x8a //星期数据地址
#define ds1302_year_add 0x8c //年数据地址
#define ds1302_control_add 0x8e //控制数据地址
#define ds1302_charger_add 0x90
#define ds1302_clkburst_add 0xbe
//初始时间定义
uchar time_buf[8] ={0x20,0x17,0x04,0x08,0x21,0x38,0x55,0x06};//初始时间2017年4月6号19点18分55秒 星期四
/*------------------------------------------------
uS延时函数,含有输入参数unsigned char t,无返回值
unsigned char 是定义无符号字符变量,其值的范围是
0~255 这里使用晶振12M,精确延时请使用汇编,大致延时
长度如下 T=tx2+5uS
------------------------------------------------*/
void DelayUs2x(unsigned char t)
{
while(--t);
}
/*------------------------------------------------
mS延时函数,含有输入参数unsigned char t,无返回值
unsigned char 是定义无符号字符变量,其值的范围是
0~255 这里使用晶振12M,精确延时请使用汇编
------------------------------------------------*/
void DelayMs(unsigned char t)
{
while(t--)
{
//大致延时1mS
DelayUs2x(245);
DelayUs2x(245);
}
}
//判忙函数
bitLCD_Check_Busy(void)
{
RS_CLR;
RW_SET;
EN_CLR;
_nop_();
EN_SET;
return (bit)(DataPort & 0x80);//0x80;0x00
}
//写入命令函数
voidLCD_Write_Com(unsigned char com)
{
while(LCD_Check_Busy()); //忙则等待
RS_CLR;
RW_CLR;
EN_SET;
DataPort= com;
_nop_();
EN_CLR;
}
//写入数据函数
voidLCD_Write_Data(unsigned char Data)
{
while(LCD_Check_Busy());//忙则等待
RS_SET;
RW_CLR;
EN_SET;
DataPort= Data;
_nop_();
EN_CLR;
}
//清屏函数
voidLCD_Clear(void)
{
LCD_Write_Com(0x01);
DelayMs(5);
}
//写入字符函数
voidLCD_write_char(unsigned char x,unsigned char y,unsigned char Data)
{
if(y == 0) //设置坐标
{
LCD_Write_Com(0x80 + x);
}
else
{
LCD_Write_Com(0xC0 + x);
}
LCD_Write_Data( Data);
}
//LCD初始化函数
voidLCD_Init(void)
{
LCD_Write_Com(0x38); /*显示模式设置*/
DelayMs(5);
LCD_Write_Com(0x38);
DelayMs(5);
LCD_Write_Com(0x38);
DelayMs(5);
LCD_Write_Com(0x38);
LCD_Write_Com(0x08); /*显示关闭*/
LCD_Write_Com(0x01); /*显示清屏*/
LCD_Write_Com(0x06); /*显示光标移动设置*/
DelayMs(5);
LCD_Write_Com(0x0C); /*显示开及光标设置*/
}
//DS1302初始化函数
void ds1302_init(void)
{
RST=0; //RST脚置低
SCK=0; //SCK脚置低
}
//向DS1302写入一字节数据
void ds1302_write_byte(uchar addr, uchar d)
{
uchari;
RST=1; //启动DS1302总线
//写入目标地址:addr
addr= addr & 0xFE; //最低位置零,寄存器0位为0时写,为1时读
for(i = 0; i < 8; i ++) {
if(addr & 0x01) {
IO=1;
}
else{
IO=0;
}
SCK=1; //产生时钟
SCK=0;
addr= addr >> 1;
}
//写入数据:d
for(i = 0; i < 8; i ++) {
if(d & 0x01) {
IO=1;
}
else{
IO=0;
}
SCK=1; //产生时钟
SCK=0;
d= d >> 1;
}
RST=0; //停止DS1302总线
}
//从DS1302读出一字节数据
uchar ds1302_read_byte(uchar addr) {
uchari,temp;
RST=1; //启动DS1302总线
//写入目标地址:addr
addr= addr | 0x01; //最低位置高,寄存器0位为0时写,为1时读
for(i = 0; i < 8; i ++) {
if(addr & 0x01) {
IO=1;
}
else{
IO=0;
}
SCK=1;
SCK=0;
addr= addr >> 1;
}
//输出数据:temp
for(i = 0; i < 8; i ++) {
temp= temp >> 1;
if(IO) {
temp|= 0x80;
}
else{
temp&= 0x7F;
}
SCK=1;
SCK=0;
}
RST=0; //停止DS1302总线
returntemp;
}
//向DS1302写入时钟数据
void ds1302_write_time(void)
{
ds1302_write_byte(ds1302_control_add,0x00); //关闭写保护
ds1302_write_byte(ds1302_sec_add,0x80); //暂停时钟
//ds1302_write_byte(ds1302_charger_add,0xa9); //涓流充电
ds1302_write_byte(ds1302_year_add,time_buf[1]); //年
ds1302_write_byte(ds1302_month_add,time_buf[2]); //月
ds1302_write_byte(ds1302_date_add,time_buf[3]); //日
ds1302_write_byte(ds1302_hr_add,time_buf[4]); //时
ds1302_write_byte(ds1302_min_add,time_buf[5]); //分
ds1302_write_byte(ds1302_sec_add,time_buf[6]); //秒
ds1302_write_byte(ds1302_day_add,time_buf[7]); //周
ds1302_write_byte(ds1302_control_add,0x80); //打开写保护
}
//从DS302读出时钟数据
void ds1302_read_time(void)
{
time_buf[1]=ds1302_read_byte(ds1302_year_add); //年
time_buf[2]=ds1302_read_byte(ds1302_month_add); //月
time_buf[3]=ds1302_read_byte(ds1302_date_add); //日
time_buf[4]=ds1302_read_byte(ds1302_hr_add); //时
time_buf[5]=ds1302_read_byte(ds1302_min_add); //分
time_buf[6]=(ds1302_read_byte(ds1302_sec_add))&0x7f;//秒,屏蔽秒的第7位,避免超出59
time_buf[7]=ds1302_read_byte(ds1302_day_add); //周
}
void Display(void)
{
LCD_write_char(3,0,dis_time_buf[0]+'0');
LCD_write_char(4,0,dis_time_buf[1]+'0');
LCD_write_char(5,0,dis_time_buf[2]+'0');
LCD_write_char(6,0,dis_time_buf[3]+'0');
LCD_write_char(7,0,'/');
LCD_write_char(8,0,dis_time_buf[4]+'0');
LCD_write_char(9,0,dis_time_buf[5]+'0');
LCD_write_char(10,0,'/');
LCD_write_char(11,0,dis_time_buf[6]+'0');
LCD_write_char(12,0,dis_time_buf[7]+'0');
LCD_write_char(15,0,dis_time_buf[14]+'0');
//第2行显示
LCD_write_char(3,1,dis_time_buf[8]+'0');
LCD_write_char(4,1,dis_time_buf[9]+'0');
LCD_write_char(5,1,':');
LCD_write_char(6,1,dis_time_buf[10]+'0');
LCD_write_char(7,1,dis_time_buf[11]+'0');
LCD_write_char(8,1,':');
LCD_write_char(9,1,dis_time_buf[12]+'0');
LCD_write_char(10,1,dis_time_buf[13]+'0');
}
//定时器0初始化
void t0( )
{
TMOD=0x01;
TH0=0xfe;
TL0=0x33;//装初值0.5ms
EA=1;
ET0=1;
PT0=1;//设置T0中断为优先级
TR0=1;
}
//定时器0中断函数
void Time0( )interrupt 1
{
TH0=0xfe;
TL0=0x33;//装初值0.5ms
if(count<sev)//水平方向舵机
pwm_v=1;
else
pwm_v=0;
if(count<seh)//垂直方向舵机
pwm_h=1;
else
pwm_h=0;
count=(count+1);
count=count%40;//周期为20ms
}
//定时器2中断函数
void Timer2() interrupt 5 //定时器2是5号中断
{
static uchar t;
TF2=0;
t++;
if(t==4) //间隔200ms(50ms*4)读取一次时间
{
t=0;
ds1302_read_time(); //读取时间
dis_time_buf[0]=(time_buf[0]>>4); //年
dis_time_buf[1]=(time_buf[0]&0x0f);
dis_time_buf[2]=(time_buf[1]>>4);
dis_time_buf[3]=(time_buf[1]&0x0f);
dis_time_buf[4]=(time_buf[2]>>4); //月
dis_time_buf[5]=(time_buf[2]&0x0f);
dis_time_buf[6]=(time_buf[3]>>4); //日
dis_time_buf[7]=(time_buf[3]&0x0f);
dis_time_buf[14]=(time_buf[7]&0x07); //星期
//第2行显示
dis_time_buf[8]=(time_buf[4]>>4); //时
dis_time_buf[9]=(time_buf[4]&0x0f);
dis_time_buf[10]=(time_buf[5]>>4); //分
dis_time_buf[11]=(time_buf[5]&0x0f);
dis_time_buf[12]=(time_buf[6]>>4); //秒
dis_time_buf[13]=(time_buf[6]&0x0f);
}
}
//定时器2初始化
void Init_timer2(void)
{
RCAP2H=0x3c ;//赋T2初始值0x3cb0,溢出20次为1秒,每次溢出时间为50ms
RCAP2L=0xb0;
TR2=1; //启动定时器2
ET2=1; //打开定时器2中断
EA=1; //打开总中断
}
//舵机控制
//跟据当前的时参数 进行T0中断函数进行下一步
void duoji_ctrl()
{
switch(time_buf[4])//时参数
{
case 0x08: //8:00 东
{
EA=1;
ET0=1;
sev=5;
seh=1;
count = 0; //占空比参数t改变,让定时器重新计数
ET0=0;
break;
}
case 0x09: //9:00东偏南
{
EA=1;
ET0=1;
sev=4;
seh=2;
count = 0;
ET0=0;
break;
case0x17://西
{
EA=1;
ET0=1;
sev=1;
seh=2;
count = 0;
ET0=0;
break;
}
default:
{
break;
}
}
}
//主函数
void main(void)
{
DelayMs(60);//等待系统稳定
LCD_Init(); //LCD初始化
LCD_Clear();//清屏
t0();//定时器0初始化
ET0=0;//关闭定时器0中断,以免产生干扰
DelayMs(15);
ds1302_write_time(); //写入初始值
Init_timer2(); //定时器2初始化
while(1)
{
Display();
duoji_ctrl();//舵机控制
}
}
那你现在的问题是什么呢,是T2中断时,进不了T0,还是T0中断时,进不了T2,对你的流程不太清楚,不知道你现在的问题是什么
这个代码太乱了
不太明白你的问题,如果要在T0发生中断进行中断处理时仍能响应T2中断,那T2中断的优先级要高于T0,如果在T0没有中断相应时,T2也不响应中断,那就是其他的问题了
是有些乱
T0中断的优先级高于T2中断,所以T2中断进行时,由于T0中断优先级高,cpu会去做T0中断里的事。
问题找到了,因为进入T0中断后,中断程序还未执行完,我就关了T0中断,所以就出现了T0中断不起作用。