这些小活动你都参加了吗?快来围观一下吧!>>
电子产品世界 » 论坛首页 » 综合技术 » 基础知识 » 请教版主!串口问题?附实际运行的源程序

共2条 1/1 1 跳转至

请教版主!串口问题?附实际运行的源程序

院士
2006-09-17 18:14:16     打赏
请教版主!串口问题?附实际运行的源程序



关键词: 请教     版主     串口     问题     附实     际运     行的     源程序    

院士
2006-12-22 22:43:00     打赏
2楼
问    我在串口中断里面调用了check函数(将得到不确定的返回值),
而在主程序里调用check会得到正确的返回值,有
没有大侠告诉我怎么回事?究竟怎么解决?头痛!!!
   用的是Philips p89c61x2单片机,其中check的返回值是由send
函数向串口调试助手发过去的。
   下面是经过实际运行的完整用于测试的源程序。用的软件是串口调试助手,
当发送任一数值时响应中断。

#include"reg51.h"
#define uchar unsigned char

void init_serialcomm()
{
   TMOD=0X20;  ;设置定时器1工作模式为2
   TH1 =0XFD;  ;设置波特率为9600b
   TL1 =0XFD;
   SCON=0X50;  ;设置串口位方式1
   PCON=0X00;
   TR1=1;
   ES=1;       ;打开串口中断允许
   EA=1;
}

//发送函数
void send(uchar k)
{
   SBUF=k;  
   while(TI==0);
   TI=0;
}

//异或函数
uchar check(uchar k,uchar *m)
{
   uchar i,parity;
   parity=0x00;
   for(i=0;i<k;i++)
   {
      parity=parity^(*(m+i));      
   }
   return(parity);
}


//串口中断?

void serial() interrupt 4 using 3
{
   uchar m[16],i;
   //bit flag;
   if(RI)      //只用于接收中断
   {
      RI=0;    //清接收中断标志位RI,以能便于下次接收中断
      m[0]=0x12;
      m[1]=0xA1;
      m[2]=0x03;
      m[3]=0x00;
      m[4]=0x00;
      m[5]=check(5,m);
      for(i=0;i<6;i++)
         send(m[i]);
   }
}

//主函数
void main()
{
   //uchar m[16]={0x12,0xA1,0X03,0X00,0X00};  
   uchar m[16],i;

   init_serialcomm();

   m[0]=0x12;
   m[1]=0xA1;
   m[2]=0x03;
   m[3]=0x00;
   m[4]=0x00;     
   m[5]=check(5,m);
   for(i=0;i<6;i++)
      send(m[i]);
   //init_serialcomm();
   while(1);
} 1: 没有热心人?没人理我。
可以复制回去看看啊,这是怎么一回事? 2: rt是不是因为主函数中
for(i=0;i<6;i++)
      send(m[i]);
语句改变了*m地址,所以 3: ...........
两个函数里的数组m[]不是一回事 4: 有错误主函数,中断函数,都有问题
for(i=0;i<6;i++)
      send(m[i]);
这是不对的,主函数只发送第一个字节就可以了,其他的在中断中处理较好,否则就要循环监视TI了,
中断中可以这样写
if (RI)
{
    RI = 0;
    revBuff[rCount] = SBUF;
    rCount++;
}
else
{
   TI = 0;
   if (sCount........
   {
     ..
     ..
   }
   else
   {
       SBUF = sndBuff[sCount];
       sCount++;
   }
} 5: 两个数组不一样不会影响返回值吧两个数组的定义都是完全一样的,就算不一样也应该和主函数返回值是一样的。 6: 这两数组都是局部变量局部变量在函数退出后会被清理,如果你在中断函数内部监视返回值,应当是一样的 7: windcity 说的对在发送中断send(m[i]); 中有问题
建议 void send(void)
     {
           SBUF = 0xXX;
           send_length = 0xXX;
      }
来触发TI中断
      void  Uart_int(void) interrupt 4
      {
            if(TI)
            {
               TI = 0;
               if(Send_length--)
                  SBUF = m[XX]
            }
      }
大体的结构应该差不多了吧 8: 终于发现问题的所在  void serial() interrupt 4  using 3--------------第1种方式中断
  void serial() interrupt 4-----------------------第2种方式中断
  非常感谢各位大哥的建议,我今天又重新做了一下,终于发现问题的所在,如果我按照第1种方式做,在串口中断子程序里调用check后的返回函数值就是错的,如果按照第2种方式则是对的。

  具体原因不明!!!!!!!!  我搞不清楚到底有什么问题呢?按道理说这两种
应该是一样的效果,只是第2种方式中断用到的是寄存器区3的R0---R7啊!

   其实这个程序本身没有什么意义,我只是想测试一下在串口中断子程序里调用check函数,看看其返回值是否正确。
   
   再一次谢谢!!

    9: 主程序中用TI=1启动发送效果更佳主程序中设置发送字节数后,用TI=1启动发送.

这样做的好处是所有发送处理都在中断中,即首字节与其后字节处理简化.

TI=1是51的特色,其它MCU或ARM都几乎没有设置TI的功能,而只有清除的功能...

10: 看看信息窗口,肯定会有个MultiCall的警告!   主函数合中断都调用了check函数,有可能在check中调用check,冲毁了数据区(C51不允许递归) 11: 原来是这样的“看看信息窗口,肯定会有个MultiCall的警告”

确实有这个问题。
原来是这样的啊,谢谢提醒!!! 12: 函数重入问题!!c51的函数默认是非可重入的,
因此会出现MultiCall的警告!!
13: 用TI=1就不会出现函数重入问题

共2条 1/1 1 跳转至

回复

匿名不能发帖!请先 [ 登陆 注册 ]