这些小活动你都参加了吗?快来围观一下吧!>>
电子产品世界 » 论坛首页 » 综合技术 » 基础知识 » 请教斑竹:模拟串口丢包的问题

共3条 1/1 1 跳转至

请教斑竹:模拟串口丢包的问题

院士
2006-09-17 18:14:16     打赏
请教斑竹:模拟串口丢包的问题



关键词: 请教     斑竹     模拟     串口     丢包     问题    

院士
2006-12-22 22:43:00     打赏
2楼
问 请问斑竹:再用你们用T0模拟串口的C程序的时候,再接收数据包的时候,会有丢包的情况,一帧7字节,接收时,会丢2个包,然后接收正确一次,又会丢2帧,有规律,丢两包,收一包,请问这可能是什么原因造成的啊??
#include "Stc_Simulate_Rs232.h"
sfr16    DPTR = 0x82;  
INT8U   bdata rs_BUF;  //串行收、发时用的移位暂存器。   
sbit rs_BUF_bit7 = rs_BUF^7;        //移位暂存器的最高位。
INT8U bdata rsFlags;
sbit rs_f_TI=rsFlags^0;    //0:正在发送; 1: 一个字符完毕  
sbit rs_f_RI_enable= rsFlags^1;   //0:禁止接收; 1:允许接收  
sbit rs_f_TI_enable = rsFlags^2; //0:禁止发送; 1:允许发送   

#ifdef TIMER_0
void timer0 (void) interrupt 1
{
  if (rs_RXD == 0 | rs_shift_count > 0)
  {
    soft_rs232_interrupt();
   }
   else
     {
        rs_timerH = rs_TEST_H;
        rs_timerL = rs_TEST_L;
        }
  }
#endif

/****************************************************/
void soft_rs232_init (void)            //串口初始化  
{
    TCON_ENABLE_TIMER = 0;             //停止定时器  
    rs_RXD = 1;                        //接收脚置成高电平  
    rs_TXD = 1;                        //发射脚置成高电平  
    IE_ETx = 1;                        //允许定时器中断
     EX0 = 1;                //允许外部中断0中断
}
void soft_receive_init()               //监测起始位  
{
    TCON_ENABLE_TIMER = 0;             //停止定时器  
    rs_timerH = rs_TEST_H;
    rs_timerL = rs_TEST_L;
    rs_shift_count = 0;
    TCON_ENABLE_TIMER = 1;             //启动定时器  
}


void soft_receive_begin()             //接收开始  
{
   gbv_RxdEnable = 1;
   rs_f_RI_enable = 1;                //允许接收  
   rs_f_TI_enable = 0;                //禁止发送
   soft_receive_init(); //监测起始位, RXD 下降沿触发接收字节过程.   
   IE_ETx = 1;                        //允许定时器中断      
}

void soft_receive_disable()           //禁止接收
{
   EX0 = 0;    //INT0中断禁止
   IE_ETx = 0;                        //禁止定时器中断
   TCON_ENABLE_TIMER = 0;             //停止定时器
   rs_RXD = 0;         //通知对方单片机 不能发送
  gbv_RxdEnable = 0;
rs_f_RI_enable = 0;                //禁止接收  
rs_f_TI_enable = 1;               //允许发送  
}
void soft_receive_enable()     // 允许接收中断  
{
  IE_ETx = 0;                        //禁止定时器中断
  TCON_ENABLE_TIMER = 0;             //停止定时器
  rs_f_TI_enable = 0;                //禁止发送
  gbv_RxdEnable = 1;
  rs_f_RI_enable = 1;                //允许接收  
  rs_RXD = 1; //通知通信对方单片机可以发送     
  EX0 = 1;//INT0中断允许(放在最后以免函数中被中断)
}

void soft_send_enable (void)           //允许发送  
{
  EX0 = 0;    //发送时INT0中断禁止                 
  TCON_ENABLE_TIMER = 0;             //停止定时器
  rs_RXD = 0;     //通知通信对方单片机 不能发送
  gbv_RxdEnable = 0;
  rs_f_TI_enable = 1;                //允许发送  
  rs_f_RI_enable = 0;                //禁止接收
  rs_shift_count = 0;                //清移位计数器  
  rs_f_TI   = 1;                     //发送一个字符完毕标志
  IE_ETx = 1;                        //允许定时器中断  
  TCON_ENABLE_TIMER = 1;             //启动定时器
}
void soft_rs232_interrupt( void )
{
   INT8U i=3;
   static INT8U sucv_BootCount = 0;
/************************ 接收 ****************************/
    if (rs_f_RI_enable == 1)
    {
      if (rs_shift_count == 0) //移位计数器==0, 表示检测到起始位的起点   
        {
          if ( rs_RXD == 1 )
          {
       sucv_BootCount++;
       if(sucv_BootCount < 6)//6次仍无启始位说明是干扰
       {
              soft_receive_begin();    //起始位错, 从新开始   
        }
       else          
           {
        sucv_BootCount = 0;
        TCON_ENABLE_TIMER = 0;      //停止定时器  
        soft_receive_enable();
            }
            }
            else
            {
                //下次中断在数据位或停止位中的某时刻发生    
                rs_timerL += rs_FULL_BIT_L + 0x10;
                rs_timerH = rs_FULL_BIT_H;
                rs_shift_count++;              
                rs_BUF = 0;      //清移位缓冲变量   
            }
        }
        else
        {
            rs_timerL += rs_FULL_BIT_L; //下次中断在数据位或停止位中发生    
            rs_timerH = rs_FULL_BIT_H;
                                       
            rs_shift_count++;   //2--9:数据位           
            if ( rs_shift_count == 9)
            {
                rs_BUF = rs_BUF >> 1;  //接收第8位   
                rs_BUF_bit7 = rs_RXD;
    /**********************************/
    
    /**********************************/
    //收到停止位,继续检测 PC 机发出的下一个起始位
    if( ReceivePoint < rs_RECEIVE_MAX)
        {         
     if(1 == RecCheck(&ReceivePoint, guca_RxdPack)) //接收检查    {
          gbv_RxdOKDown = 1;
    soft_receive_disable();
    }
}
else
{
  ReceivePoint = 0;//soft_receive_disable();//缓冲区满, 禁止接收  }
}
   else
            {
                if (rs_shift_count < 9 )             //收到的是数据位 1 -- 7  
                {
                    rs_BUF = rs_BUF >> 1;
                    rs_BUF_bit7 = rs_RXD;
                }
                else
                {
                    soft_receive_enable();          // 允许接中断
                }
            }
        }
        TCON_TFx = 0;                                      //清定时器中断标志   

    }
    else
    {
        /************************ 发送 ****************************/  
       if (rs_f_TI_enable == 1)
        {
            rs_timerL += rs_FULL_BIT_L;//下次中断在数据位的末尾时刻   
            rs_timerH = rs_FULL_BIT_H;

            rs_shift_count--;                          //0:停止位末尾时刻到  
                                                       //1:发送停止位  
                                                       //2--9:发送数据位  
            if (rs_shift_count > 9)                    //错误状态  
            {
                rs_shift_count = 9;
                rs_BUF = 0xFF;
            }

            if (rs_shift_count > 1)                    //2--9:发送数据位  
            {
                ACC = rs_BUF;
                ACC = ACC >> 1;
                rs_TXD = CY;
                rs_BUF = ACC;
            }
            else
            {
                if (rs_shift_count == 0)                 //0:停止位末尾时刻到  
                {
                    rs_TXD = 1;
                    rs_f_TI = 1;                           //已发送完毕一个字节  
                }
                else
                {
                    rs_TXD = 1;                            //1:发送停止位  
                }
            }
        }
    }
}


//由收转到发时,要先调用 soft_send_enable ()  
void rs_send_byte(INT8U SendByte)        //发送一个字节  
{
  gbv_SndByteTWait = 1;
  gucv_SndByteTCount = 0;
    while ( rs_f_TI == 0)         //等待发送完毕前一个字节  
   {
    if (!gbv_SndByteTWait)    //避免死循环
    {
     rs_f_TI = 1;
     }
   }


    rs_TXD = 1;
    rs_timerL=rs_START_BIT_L;//下次中断在起始位的末尾时刻   
    rs_timerH = rs_START_BIT_H;
    rs_BUF = SendByte;
    rs_shift_count = 10;
    rs_TXD = 0;       //发送起始位  
    rs_f_TI = 0; //清已发送完毕一个字节的标志   

}

//INT0中断服务子程,用于模拟串口接收起始位触发
void Extern0_ISR() interrupt 0            
{    
  EX0 = 0;    //INT0中断禁止
  soft_receive_begin();             //开始接收  
    
}

INT8U RecCheck(INT8U *lucv_RxdCount, INT8U luca_RxdPack[]) //接收检查
{  
  INT16U TmpCrc = 0;

   putbf(rs_BUF);    //打印数据,在串口调试助手中观察到每隔两包收一包
  if (!((*lucv_RxdCount) < rs_RECEIVE_MAX))
  {
    *lucv_RxdCount = 0;
   }
   switch (*lucv_RxdCount)
  {
    case 0:    
       if (HEADCHAR != rs_BUF)//头标志错误则抛弃包
       {
    (*lucv_RxdCount) = 0;
    return 0;
       }
      break;
   case 1:
     break;
  case 2:
   if (rs_BUF > rs_RECEIVE_MAX - 2)//最多接收字节(不包括crc)
   {
     (*lucv_RxdCount) = 0;
     return 0;
    }
   else
   break;
default:
//到指定接收长度.gucv_RxdCount与下标位相同,因此比实际字节数少1
  if ((*lucv_RxdCount) >= (luca_RxdPack[2] +2 - 1))//到指定接收长度
  {
     luca_RxdPack[*lucv_RxdCount] = rs_BUF;
    if (TAILCHAR == luca_RxdPack[(*lucv_RxdCount)] )    //结束标志正确?
    {
      (*lucv_RxdCount) = 0;
      if(!(Cal_Crc(&luca_RxdPack[1],luca_RxdPack[2])))
      {
        return 1;
       }
     }
    (*lucv_RxdCount) = 0;
    return 0;
    }
}
luca_RxdPack[*lucv_RxdCount] = rs_BUF;
(*lucv_RxdCount)++;
return 2;

}

void SendSimula(const INT8U luca_Dataes[])
{
   INT8U n = 0;
   INT8U lucv_Leng = 0;
   INT8U xdata luca_Pack[rs_SEND_MAX];
   lucv_Leng = luca_Dataes[1] + 4;
  Pack_Dataes(luca_Pack, luca_Dataes);
  for (n = 0; n < lucv_Leng; n++)
  {
   rs_send_byte(luca_Pack[n]);
   }
  gbv_SndByteTWait = 1;
  gucv_SndByteTCount = 0;
  while( rs_f_TI == 0)       //等待发送完毕前一个字节  
  {
     if (!gbv_SndByteTWait)          //避免死循环
     {
     rs_f_TI = 1;
      }
   }    // 等待最后一个字节发送完毕   
        
    
}
1: 肯定你软件的原因喽 2: OK解决了,自己的失误 3: 恭喜,我们只是写个样例程序,供大家参考,帮大家省些宝贵时间恭喜,我们只是写个样例程序,供大家参考,帮大家省些宝贵时间

高工
2022-08-10 23:01:26     打赏
3楼

Ziperello


共3条 1/1 1 跳转至

回复

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