打印

串口接收数据时 如何跳出正在执行的函数

[复制链接]
2689|12
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
LIUXRUI2010|  楼主 | 2013-5-23 11:46 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
大家好: 在接收数据的时候
while(1)
{

     if(!串口有数据) //串口有数据的时候
    {
          display();  //在执行的时候时间大概3 s

     }
    if()         //判断接收串口标志
   {
           执行串口接收数据,// buffer 比较小,接收一个处理一个
  }
}
问题:不用    display();  这个函数时, 发送接收数据 正常,
          但用     display();  后 发现 不能接收数据, 我想接收数据的时候buffer满了后 还在执行    display();  没及时跳出    display();  现在想接收一个数据的时候 如何跳出    display(); 函数 直接在while(1) 里等待 。
沙发
airwill| | 2013-5-23 12:29 | 只看该作者
最简单的办法是 把 display() 搬出中断函数.
中断函数只是接受数据, 然后给 display() 消息, 告诉它有新数据需要更新.

使用特权

评论回复
板凳
LIUXRUI2010|  楼主 | 2013-5-23 12:56 | 只看该作者
airwill 发表于 2013-5-23 12:29
最简单的办法是 把 display() 搬出中断函数.
中断函数只是接受数据, 然后给 display() 消息, 告诉它有新数 ...

我是在主函数里面的
main(void)
{
   各种初始化
while(1)
{

     if(!串口有数据) //串口有数据的时候
    {
          display();  //在执行的时候时间大概3 s

     }
    if()         //判断接收串口标志
   {
           执行串口接收数据,// buffer 比较小,接收一个处理一个
  }
}
}

使用特权

评论回复
地板
airwill| | 2013-5-23 12:57 | 只看该作者
那就接收数据采用中断
中断函数只是接受数据, 然后给 display() 消息, 告诉它有新数据需要更新.

使用特权

评论回复
5
LIUXRUI2010|  楼主 | 2013-5-23 13:11 | 只看该作者
airwill 发表于 2013-5-23 12:57
那就接收数据采用中断
中断函数只是接受数据, 然后给 display() 消息, 告诉它有新数据需要更新. ...

谢谢 aiwill
我是采用中断的,但是中断收完满BUFFER之后,程序还在display()  函数里面,因为我收的收据比较大,这样后面的数据,串口就接收不到, 我是想接收满buffer之后 就跳出整个display()  函数,这样 我可以完全去处理buffer串口的收据(接收一个处理一个)。 不知道你明白意思没有。或者有更好的处理方法?

使用特权

评论回复
6
香水城| | 2013-5-23 13:40 | 只看该作者
中断接收填满buffer之后,就调用Display()显示;如果在display的过程中,接收buffer又满了,难道也还要调用Display()?那么你的这个display函数能够重入?

使用特权

评论回复
7
LIUXRUI2010|  楼主 | 2013-5-23 14:03 | 只看该作者
香水城 发表于 2013-5-23 13:40
中断接收填满buffer之后,就调用Display()显示;如果在display的过程中,接收buffer又满了,难道也还要调用 ...

我准备写入外部FALSH当中,假如写完了之后我  重启单片机, 然后读取相应的配置文件,然后再显示 香水城 有妙招没
程序如下 没有调用显示函数时 串口正常,但调用显示函数时就 读取不了数据  显示函数时间 大约在3S钟 所以想跳出显示函数
while(1)
{
       if(UartData标志寄存器==0)
    {
   Display(1,0,0,0,0,0);  //调用显示函数
    }
  SYN_标志寄存器 = checksyn();  //同步字节检测
  if(SYN_标志寄存器 == 1)            //如果成功
  {
   uart1_get(&tmp);
   switch(tmp)
   {
   
    case 0x01:
     
     if(Parameter_Set())     //参数设置正确
     {
      goto Prog_start;   //重新读取配置信息
     }
     else
     {
      break;   
     }
     for(i=0;i<count; i++)
     {
     // while(UART1_GetFlagStatus(UART1_FLAG_TXE)==RESET); //check whethe is empty of the Tx buff
     // UART1->DR = (u8) read_eeprom(address+i);
     //  count--;
     }
     break;
    case 0x02:  
    // UART1_ITConfig(UART1_IT_RXNE_OR, ENABLE);    //串口1接收使能
     break;
    case 0x03:
     UartData标志寄存器 = 0;
    // SYN_标志寄存器=0;
     goto Prog_start;
     break;
    case 0x04:
     uart1_get(&tmp);
     DataLen = tmp;                 //接收数据长度 32b  
     DataLen = DataLen<<8;
     uart1_get(&tmp);
     DataLen |= tmp;     
     DataLen = DataLen<<8;
     uart1_get(&tmp);
     DataLen |= tmp;      
     DataLen = DataLen<<8;   
     uart1_get(&tmp);
     DataLen |= tmp;   
     count = DataLen;
     i=0;
     while(DataLen>0)               //将数据读出来并且存入到flash CRC校验
     {
      while(!uart1_get(&tmp));  //等待串口下一个数据 需要加一个跳出语句 不然后果不堪设想
      // break;
      gWRFlash_Buffer[k++] = tmp;
      DataLen--;
      
      if((count<256)&&(k==count))         //如果接收长度小于一个256即小于写入的一页flash
      {
       SPI_Flash_BufferToMainMemoryPageProgram_Built_inErase(0x01,0x00,0x00,gWRFlash_Buffer,count);
       k = 0;
      }
      if(k==256)
      {
       SPI_Flash_BufferToMainMemoryPageProgram_Built_inErase(0x01,WRPageAddress,0x00,gWRFlash_Buffer,k);
       k=0;
       WRPageAddress++;
       if(WRPageAddress==1024)
       {
       // ExternFlashOver标志寄存器 = 1;   //外部FLASH已写满标志
       }                  
      }
     // delay_ms(10); flash 可以读到264BYTE
     }  // end while(DataLen>0)
     SPI_Flash_ContinuousArrayRead(0x00,0x00,gTXBuffer,count);
     
     for(i=0;i<count; i++)
     {
      while(UART2_GetFlagStatus(UART2_FLAG_TXE)==RESET); //check whether is empty of the Tx buff
      //  UART1_ClearFlag(UART1_FLAG_TC);
      UART2->DR =  gTXBuffer;
           //delay_ms(100); 此延时不能设置太长时间 即会出先串口输出太慢
     }  
    // UartData标志寄存器 = 0;
    // goto Prog_start;     
     break;
     
    case 0x05:
     break;
   // case 0x06:  
   // default :
   // goto Prog_start;
   //  break;
   }
   
  }
        
}
  

使用特权

评论回复
8
香水城| | 2013-5-23 14:31 | 只看该作者
由于你的buffer已满了的时候,并没有读取数据,因为你还在做Display的操作。那么后续USART端口再来的数据就发生overrun了,那么后续来的数据就全部丢掉了

使用特权

评论回复
9
LIUXRUI2010|  楼主 | 2013-5-23 14:39 | 只看该作者
香水城 发表于 2013-5-23 14:31
由于你的buffer已满了的时候,并没有读取数据,因为你还在做Display的操作。那么后续USART端口再来的数据就 ...

是的,所以我想收到 中断数据后 跳出来 Display,然后再while(1) 循环,直到收完数据处理完后,我再重启单片机,香水城 有什么好的方法没,或者别人是怎么处理大量串口数据,然后再显示函数的。

使用特权

评论回复
10
LIUXRUI2010|  楼主 | 2013-5-23 17:59 | 只看该作者
有谁告诉下我思路也可以啊,比较急啊、、、

使用特权

评论回复
11
hawksabre| | 2013-5-23 19:50 | 只看该作者
这一块不是很了解  楼主  帮你顶一个   看看别人的意见   顶一个

使用特权

评论回复
12
jeckboy| | 2013-5-24 23:47 | 只看该作者
你把接收缓冲区长度设为2倍甚至更多,当你接收到一个完整帧或者包以后需要设定处理标志,同时在DISPLAY()里间隔小于接收1个完整帧时间内检查该标志,如果查到立即跳出该函数,同时你的接收缓冲区可以继续接收数据,且你必须保证在接收缓冲区填满之前处理完前面收到的完整帧;这种办法有点类似追击

使用特权

评论回复
13
LIUXRUI2010|  楼主 | 2013-5-25 09:52 | 只看该作者
jeckboy 发表于 2013-5-24 23:47
你把接收缓冲区长度设为2倍甚至更多,当你接收到一个完整帧或者包以后需要设定处理标志,同时在DISPLAY()里 ...

谢谢jeckboy:
我后面用了在DISPLAY() 用goto 来跳出,可以实现,但是网上说goto 慎用,这种方法不太好,DISPLAY()因为有很多循环,有没更好的方式直接跳出几个循环。

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

11

主题

38

帖子

0

粉丝