不显示删除回复 显示所有回复 显示星级回复 显示得分回复 只显示楼主 收藏



yudewen0128

yudewen0128 等级:

结帖率:0%

楼主                          发表于:            2009-09-14 21:36:11         



            [size=14px]这是我的程序:当定时器打开后就接收不到数据了,屏蔽掉定时器就可以了!请大侠指教原因所在!


/*************************************************************/       
 /*本设计采用STC89C52单片机                                   */       
 /*                                                           */       
 /*晶振为11.0592M                                             */       
 /*************************************************************/       
 #include<reg52.h>       
 #include<absacc.h>       

 #define uchar unsigned char       
 /***************************变量定义***************************/       
 int timecount=0;            //定时器计数       
 uchar flag=0;               //是否超时未取走电池标志       
 uchar state=0;              //状态标志       
 uchar rec=0x00;             //接收数据       
 uchar f_rec=0;            //接收标志       
 /***************************端口定义***************************/       
 sbit Battery=P1^0;               // 有无电池       
 sbit Hand=P1^1;                  //有无手阻挡       
 sbit Output=P1^2;                //夹具松开或闭合       
 /*************************************************************/       
 /*函数功能:初始化定时器0,定时时间设置为50ms                 */       
 /*入口参数:无                                               */       
 /*出口参数:无                                               */       
 /*************************************************************/       
 void init_timer0(void)       
 {       
 TMOD=0x01;               //定时器工作在方式1       
 TH0=0x04;                //定时初值设置为定时50ms       
      TL0=0xBF;       
      ET0=1;       
 }        
 /*************************************************************/       
 /*函数功能:定时器0中断服务程序                              */       
 /*入口参数:无                                               */       
 /*出口参数:无                                               */       
 /*************************************************************/       
 void timer0() interrupt 1                             
 {       
 TR0=0;       
 timecount++;       
 if(timecount==400)     //当从CTS接收停止信号1时或夹具关闭到达20s       
 {       
 Output=1;          //松开夹具       
                    TR0=0;             //关闭定时器       
 timecount=0;       //定时计数清零       
 flag=1;            //置位超时标志       
 }       
 else       
    {       
     init_timer0();       
 TR0=1;       
 }       

 }       

 /*************************************************************/       
 /*函数功能:串行接收中断服务程序                             */       
 /*入口参数:无                                               */       
 /*出口参数:无                                               */       
 /*************************************************************/       
 void uart( ) interrupt 4       
 {       
 if(RI)       
 {       
   RI=0;       
                     rec=SBUF; //接收一个数据       
   if(rec==0x01)       
            f_rec=1;       
         
 }       
 }       
 /*************************************************************/       
 /*函数功能:延时函数,最小延时单位1ms                        */       
 /*入口参数:延时时间                                         */       
 /*出口参数:无                                               */       
 /*************************************************************/       
 void delay(int t)       
 {       
      int i=0,j=0,k=0;       
 for(;t>0;t--)       
 for(;i<100;i++)       
 for(;i<120;i++);       
 }       

 void main()       
 {       
 TMOD=0x20;//设置定时器1为工作方式2       
 TH1=0xfd;       
 TL1=0xfd;       
 TR1=1; //开定时器       
 SCON=0x50;       
 PCON=0x80;       
 EA=1;//总中断       
 ES=1;//串口中断允许位       
 //IP=0x10;                               //设置串行中断为高优先级       
 P1=0x03;                               //置平P1.0及P1.1为输入模式       
 Output=1;       
 init_timer0( );                      //默认情况下,夹具松开       
      while(1)       
 {       

 if(Battery==1&&Hand==0)         
                      {       
 delay(500);                 //延时500ms以防止误判                                       
                            if(Battery==1&&Hand==0)       //当夹具上有电池且手已经拿开,闭合夹具       
 {       
                        
 while(flag)              //有超时未取走的电池时,等待将电池拿走           
 {       
 if(Battery==0&&Hand==0) //超时电阻已经取走       
 {       
 flag=0;       
 state=1;       
 f_rec=0;//清零f_rec       
 }       
 }       
 if(state==0)       
 {       
 TR0=1;       
         
 if(f_rec==1)       

                      {       
          
                        ES=0;       
                        Output=1;          //松开夹具       
                                                   TR0=0;             //关闭定时器       
                                 timecount=0;       //定时计数清零       
                                 flag=1;       
                    
      delay(10);       
      SBUF=rec;       
                                                  while(!TI);       
                                                   TI=0;       
                                                   ES=1;       
                                                   }       
    else  Output=0;               
 }       
 else       
 {       
 state=0;            //清状态标志       
 Output=1;       
 }       
 }       
 else Output=1;       
 }       
 else Output=1;       
 }       
 }



分享到:




对我有用[0] 丢个板砖[0] 引用 |    举报 |   

编辑 删除



回复次数:18



duojinian

DISINHUI 等级:

结帖率:100%

#1得分:0            回复于:            2009-09-15 09:57:11         



定时器中断占用CPU资源太多,应该只在定时器服务代码中设置计时标志字,在主代码中计时判断动作,否则定时器中断服务代码影响串口通信.         


参与Linux应用有奖调查,赢取MAC笔记本、HTC One手机!



对我有用[0] 丢个板砖[0] 引用 |    举报 |   

编辑 删除




changingfu

changingfu 等级:

结帖率:0%

#2得分:0            回复于:            2009-09-17 20:08:25         



我没看你的程序
中断优先级是不是有问题?       


【话题讨论】聊聊正版软件那点事儿



对我有用[0] 丢个板砖[0] 引用 |    举报 |   

编辑 删除




zhoushunda960

zhoushunda960 等级:

结帖率:100%

#3得分:0            回复于:            2009-09-18 10:14:24         



问题出在你的init_timer0函数里,每次启动定时器中断后会执行init_timer0中的TMOD=0x01,这样定时器1的模式就不是串口模式下所需模式了,自然串口接收不到数据。应该成 TMOD |= 0x01;
另外在你的串口接收中断函数中,跳入中断时最好把EA关掉,处理完后在将EA置位。


百度云技术论坛有奖讨论第一期



对我有用[0] 丢个板砖[0] 引用 |    举报 |   

编辑 删除




huqiming588

huqiming588 等级:

结帖率:0%

#4得分:0            回复于:            2009-12-14 00:11:23         



学习了!       





对我有用[0] 丢个板砖[0] 引用 |    举报 |   

编辑 删除




ZEROLELOUCH

ZEROLELOUCH 等级:

结帖率:87.5%

#5得分:0            回复于:            2010-10-20 22:04:31         



我暑假做一个单片机控制串口和一个舵机角度的东西,结果加入串口后对舵机角度的控制很不稳定。
最好不要那么用       





对我有用[0] 丢个板砖[0] 引用 |    举报 |   

编辑 删除




ningshao1945

ningshao1945 等级:

结帖率:100%

#6得分:0            回复于:            2010-10-21 11:10:51         



正解,这是最基本的操作啊。
引用 3 楼 zhoushunda960 的回复:

问题出在你的init_timer0函数里,每次启动定时器中断后会执行init_timer0中的TMOD=0x01,这样定时器1的模式就不是串口模式下所需模式了,自然串口接收不到数据。应该成 TMOD |= 0x01;另外在你的串口接收中断函数中,跳入中断时最好把EA关掉,处理完后在将EA置位。






对我有用[0] 丢个板砖[0] 引用 |    举报 |   

编辑 删除




yangminghua6

yangminghua6 等级:

结帖率:100%

#7得分:0            回复于:            2010-10-22 22:10:38         




该回复于2010-10-23 10:01:44被版主删除           






对我有用[0] 丢个板砖[0] 引用 |    举报 |   

编辑 删除




dereckgail

dereckgail 等级:

结帖率83.33%

#8得分:0            回复于:            2010-10-22 22:26:30         



支持一楼和六楼,串口用定时器1设置波特率,在中断程序中应该尽量简洁,设置一下标志位就行了       





对我有用[0] 丢个板砖[0] 引用 |    举报 |   

编辑 删除




AjunlintianxiaA

AjunlintianxiaA 等级:

结帖率:100%

#9得分:0            回复于:            2011-02-11 13:51:25         



引用 5 楼 zerolelouch 的回复:

我暑假做一个单片机控制串口和一个舵机角度的东西,结果加入串口后对舵机角度的控制很不稳定。最好不要那么用


我现在也正急需做一个这样的东西,电脑通过串口给单片机数据,控制舵机角度,不知道您当时怎么做的,为什么我同时开串口和定时器,定时器就不受控制呢?51串口占用计数器1,定时占用计数器0,是不是相互影响了?       







对我有用[0] 丢个板砖[0] 引用 |    举报 |   

编辑 删除




cgsoftware

cgsoftware 等级:

结帖率:0%

#10得分:0            回复于:            2012-10-26 23:19:50         



问题找到了,定时器0的重装计数值千万不能太大。
也就是说把定时器0的中断时间拉长一点,让程序有足够的时间去处理相应的指令。这些指令可能是串口中断里的,也可能是定时器里的。       





对我有用[0] 丢个板砖[0] 引用 |    举报 |   

编辑 删除




cgsoftware

cgsoftware 等级:

结帖率:0%

#11得分:0            回复于:            2012-10-26 23:57:38         



又试了一个多小时,关键还是在中断里的程序不能太大。一定要把大的处理程序(非即时的)放到主循环里去。       





对我有用[0] 丢个板砖[0] 引用 |    举报 |   

编辑 删除




aydf1

aydf1 等级:

结帖率:0%

#12得分:0            回复于:            2012-10-27 10:06:46         



问题出在你的init_timer0函数里,每次启动定时器中断后会执行init_timer0中的TMOD=0x01,这样定时器1的模式就不是串口模式下所需模式了,自然串口接收不到数据。应该成 TMOD |= 0x01;
另外在你的串口接收中断函数中,跳入中断时最好把EA关掉,处理完后在将EA置位       





对我有用[0] 丢个板砖[0] 引用 |    举报 |   

编辑 删除




gaopeng090610

gaopeng090610 等级:

结帖率:0%

#13得分:0            回复于:            2012-10-27 11:00:47         




该回复于2012-10-27 11:13:18被版主删除           






对我有用[0] 丢个板砖[0] 引用 |    举报 |   

编辑 删除




ymm198606

ymm198606 等级:

结帖率:66.67%

#14得分:0            回复于:            2012-11-01 17:22:55         



定时器的定时时间太短了,程序跑进定时中断程序太频繁,导致其占用时间太多,无法执行UART的相应程序了;把定时时间调长点看看       





对我有用[0] 丢个板砖[0] 引用 |    举报 |   

编辑 删除




of123

of123 等级:



7





6


#15得分:0            回复于:            2012-11-02 09:00:56         



定时器的长短不是关键,它只能改变两种中断冲突的概率。

如果你的两个中断优先级相同,当定时中断比串口接收中断稍早一点触发,串口中断就被挂起。但串口是异步传输,发送端并不会停下来等你,因此会丢失数据。

如果定时中断比串口中断优先级高,则它会随时打断串口中断服务。

如果你的芯片能够设置中断级别,将串口中断设置得更优先就可以了。

如果没有这样的条件,就要更改协议。

1 主机端先发送一个 Test Ready 查询字符,转入接收模式。

2 如果设备端正常进入中断,正确收到此查询字符,关闭全局中断使能或定时器中断使能,转入发送,回送一个 Ready 标志字符。并转回接收模式。

3 主机端接收到 Ready 标志字符,则继续发送应发数据;否则随机延时之后,回到步骤 1 重试。

4 设备端接收完毕,退出服务时,重新打开关闭的中断。       





对我有用[0] 丢个板砖[0] 引用 |    举报 |   

编辑 删除




fang098

fang等级:

结帖率:100%

#16得分:0            回复于:            2012-11-02 11:31:06         



引用 15 楼  的回复:

定时器的长短不是关键,它只能改变两种中断冲突的概率。


怎么定时器的时间长短不是关键想不明白,如果中断处理过程的处理时间要长过于定时器所设的时间,那问题不就来了啊。还请楼上的帮忙解释解释。       







对我有用[0] 丢个板砖[0] 引用 |    举报 |   

编辑 删除




of123

of123 等级:



7





6


#17得分:0            回复于:            2012-11-02 14:18:19         



实际上,没有影响接收实时性的,是串口发生接收事件时,无法正常进入串口中断服务,也就是说它被“挂起”了,因为另外一个中断正在服务中。而此时,主机端传输是照样进行的。因此丢失数据了。如果丢失的是协议的起始字符,就失去了这次事务。

延长定时,只能是降低两个中断冲突的概率。还是有可能遇到定时中断先于串口中断来到的情况的,仍有概率使串口中断服务挂起。当然,如果定时中断服务执行的很快,远低于串口接收一个字节的时间,也是可以避过去的。串口通讯毕竟是超低速的。

中断处理过程的处理时间长过于定时器所设的时间间隔的情况,对于一个正常的应用几乎不可能发生。这样不仅是串口通讯不能工作,任何过程都停了,永远挂在定时中断服务中。用极端的情况来考虑问题,是不是有点那个了。

这个问题的关键,应该是中断优先级的问题。

另外,串口通讯是否需要同一个定时器?两者是否有冲突?也要考虑。       





对我有用[0] 丢个板砖[0] 引用 |    举报 |   

编辑 删除




cyymycc

cyymycc 等级:

结帖率:100%

#18得分:0            回复于:            2012-11-02 17:41:05         


void init_timer0(void)       
 {       
 TMOD=0x01; //定时器工作在方式1       
 TH0=0x04; //定时初值设置为定时50ms       
   TL0=0xBF;       
   ET0=1;       
 }


应为
TMOD=0x21; //定时器0工作在方式1,定时器1工作在方式2





对我有用[0] 丢个板砖[0] 引用 |    举报 |   

编辑 删除