微波EDA网,见证研发工程师的成长!
首页 > 研发问答 > 嵌入式设计讨论 > MCU和单片机设计讨论 > 新手求助 stc89c52单片机 DS1302中的中断响应一些问题 大家对此有什么看法

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

时间:10-02 整理:3721RD 点击:
在原来的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();//舵机控制

  }

}


那你现在的问题是什么呢,是T2中断时,进不了T0,还是T0中断时,进不了T2,对你的流程不太清楚,不知道你现在的问题是什么

这个代码太乱了

不太明白你的问题,如果要在T0发生中断进行中断处理时仍能响应T2中断,那T2中断的优先级要高于T0,如果在T0没有中断相应时,T2也不响应中断,那就是其他的问题了

是有些乱

T0中断的优先级高于T2中断,所以T2中断进行时,由于T0中断优先级高,cpu会去做T0中断里的事。

问题找到了,因为进入T0中断后,中断程序还未执行完,我就关了T0中断,所以就出现了T0中断不起作用。

Copyright © 2017-2020 微波EDA网 版权所有

网站地图

Top