查看: 160|回复: 6
收起左侧

[STC单片机] 新手求助 stc89c52单片机 DS1302中的中断响应一些问题 大家对此有什么看法

[复制链接]
     

1

主题

4

帖子

22

积分

实习生

 楼主| 发表于 2017-4-19 20:04 | 显示全部楼层 |返回版面||阅读模式
在原来的ds1302实时时钟程序中引入其他控制模块,实时时钟原本就有定时器t2中断, 引入定时器t0中断后得不到响应,导致无法在定时器t0中断进行相应的控制,大家看这个该怎样解决,求助各位。(内容有些多)
/*------------------------------------------------*/
#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();//舵机控制
  }
}
21ic公开课,21ic网友共同的学习圈子!学单片机、嵌入式、模拟、电源……就看这里 http://open.21ic.com 移步更多21ic独家微课:http://open.21ic.com/list/3/0/0
     

4871

主题

1万

帖子

2万

积分

版主

发表于 2017-4-20 09:16 | 显示全部楼层 |返回版面
实时时钟和T2有什么关系?
T0和T2有什么关联?

T0不响应是不是T0的中断控制位没置位?
21ic公开课,21ic网友共同的学习圈子!

45

主题

1209

帖子

4339

积分

中级工程师

发表于 2017-4-20 10:19 | 显示全部楼层 |返回版面
初学者常犯的错误,中断里干的事情太多。
21ic公开课,21ic网友共同的学习圈子!学单片机、嵌入式、模拟、电源……就看这里 http://open.21ic.com 移步更多21ic独家微课:http://open.21ic.com/list/3/0/0
     

1

主题

4

帖子

22

积分

实习生

 楼主| 发表于 2017-4-20 13:46 | 显示全部楼层 |返回版面
ningling_21 发表于 2017-4-20 09:16
实时时钟和T2有什么关系?
T0和T2有什么关联?

T2获取实时时间 T0用于产生控制信号   
21ic公开课,21ic网友共同的学习圈子!学单片机、嵌入式、模拟、电源……就看这里 http://open.21ic.com 移步更多21ic独家微课:http://open.21ic.com/list/3/0/0
     

4871

主题

1万

帖子

2万

积分

版主

发表于 2017-4-20 16:29 | 显示全部楼层 |返回版面
呼哈呼哈 发表于 2017-4-20 13:46
T2获取实时时间 T0用于产生控制信号

检查T0 中断的控制开关 ET0
21ic公开课,21ic网友共同的学习圈子!

0

主题

2

帖子

6

积分

实习生

发表于 2017-4-20 17:32 | 显示全部楼层 |返回版面
中断比较复杂,应该多检查。
21ic公开课,21ic网友共同的学习圈子!学单片机、嵌入式、模拟、电源……就看这里 http://open.21ic.com 移步更多21ic独家微课:http://open.21ic.com/list/3/0/0
     

1

主题

4

帖子

22

积分

实习生

 楼主| 发表于 2017-4-20 18:34 | 显示全部楼层 |返回版面
ningling_21 发表于 2017-4-20 16:29
检查T0 中断的控制开关 ET0

就因为关闭了ET0 所以T0中断不起作用。
21ic公开课,21ic网友共同的学习圈子!学单片机、嵌入式、模拟、电源……就看这里 http://open.21ic.com 移步更多21ic独家微课:http://open.21ic.com/list/3/0/0
您需要登录后才可以回帖 登录 | 注册

本版积分规则

关闭

热门推荐上一条 /2 下一条

分享 快速回复 返回顶部 返回列表