串口通信重发机制

youimisss 2013-11-22 03:23:06
最近在学习提高串口的通信质量,搞了个CRC16,想再弄个重发机制和超时机制却不知道怎么弄了。谁有健硕点的串口通信程序或者相关资料可以发来参考下吗?
...全文
2072 12 打赏 收藏 转发到动态 举报
写回复
用AI写文章
12 条回复
切换为时间正序
请发表友善的回复…
发表回复
Linux-OS 2014-04-15
  • 打赏
  • 举报
回复
使用ModBus RTU协议。相当好!
躺着睡的蜗牛 2014-04-04
  • 打赏
  • 举报
回复
参考XMODEM, 里边有重发机制。
dceacho 2014-04-02
  • 打赏
  • 举报
回复
注意UART中断里面处理的东西比较多,如果速度不够快的话自己想办法优化
dceacho 2014-04-02
  • 打赏
  • 举报
回复


//发送后下位机正常接受
#define ACK_OK   1
//发送后下位机没反应
#define ACK_TIMEOUT  2
//发送后下位机报告校验错误
#define ACK_VERERR  3

//空闲
#define STA_READY   0
//接受到正确的帧
#define STA_SENTOK 1
//状态发送完
#define STA_SENT     2
//状态: 收到一个校验错误的ACK
#define STA_VERERR  3
volatile uchar sta=STA_READY;
uint16 uartcnt=0;
void tx(uchar *pstr,uchar n)	   //didnot send 0x0d to start print
{	
                   uchar i;						   //no format,must \n or enter before use it
	for(i=0;i<n;i++)
	{
		SBUF=*pstr++;
		while(TI==0);
		TI=0;	
	}
}
uchar sendmsg(uchar *pstr,uchar n)
{
       uchar *buf="Hi,Girl!";
       uchar ver[2]={0x55,0xaa};//假设校验是0x55aa
      txbuf(buf,8);//发送起始标记8字节
     txbuf(pstr,8);//发送内容8字节
     txbuf(ver,2);//发送校验2字节
    sta=STA_SENT;
    uartcnt=0;
    while(sta==STA_SENT)
   {
          if(sta==STA_VERERR){sta=STA_READY;return ACK_VERERR;}
         if(sta==STA_SENTOK){sta=STA_READY;return ACK_OK;}
          //假设TIMER0中断10次算超时
          if(uartcnt>10){STA=sta_ready;return ACK_TIMEOUT;}
    }
}
void main(void)
{
   uchar temp;
   Timer0初始化;
   UART初始化
LOOP1:
  temp=sendmsg("Hello,world!",8);
   if(temp==ACK_OK)
   {

   }
  else if(temp==ACK_TIMEOUT)
  {
     //超时处理,如果再发的话
   goto LOOP1;
  }
 else if(temp==ACK_VERERR)
  {
     //校验错误处理,如果再发的话
   goto LOOP1;
  } 
  while(1);
}
void Timer0(void) interrupt 1
{
  uartcnt++;
}
uchar rxbuf[32];
//假设下位机收到数据后并确认数据是正确后返回"Hi,Girl!"的前8个字节和2个字节的校验(0x55aa)
void Uart0(void) interrupt ? //主机接收中断,下位机的自己想
{
  uchar i;
  if(RI==0)return;
  for(i=0;i<31;i++)rxbuf[i]=rxbuf[i+1];
  rxbuf[31]=SBUF;
  RI=0;
  for(i=0;i<31-18;i++)
  {
    if(rxbuf[i]=='H')
   {
     if(rxbuf[i+1]=='i' && rxbuf[i+2]==',' && rxbuf[i+3]=='G' ......)//这里其实是要检查帧的起始标记
     {
            //检查到有效的起始标记
      if(rxbuf[i+8]==0x55&&rxbuf[i+9]==0xaa)
          {
            //校验正确
       for(i=0;i<31;i++)rxbuf[i]=0;
            return STA_SENTOK;
         }
       else
      {
            //校验错误
       for(i=0;i<31;i++)rxbuf[i]=0;
            return STA_VERERR;
      }
     }
  }
  }
}
dceacho 2013-11-22
  • 打赏
  • 举报
回复
引用
“接收方返回ACK”需要校验吗?如果校验且校验不对,那不是进入死循环了吗?

要求很高的话需要校验,发送方必须有一个最大重试次数,超过次数报告给用户就行了
youimisss 2013-11-22
  • 打赏
  • 举报
回复
引用 6 楼 wangfan027 的回复:
如何CRC校验错误就重发呢?从机接收到的CRC与从机计算出的CRC比较,如果不相等则通知主机重发数据?这样不就成了一问一答的通信方式吗? 要可靠的话必须要有ACK,类似你说的一问一答 分两种情况,一种是下位机超时没收到,另一种是下位机收到了但校验不对 发送完毕--->状态:发送完等待接收,计时器置零--->等待接收方返回ACK --->接收方返回校验错误--->重发 --->没有任何返回超时---->重发
“接收方返回ACK”需要校验吗?如果校验且校验不对,那不是进入死循环了吗?
dceacho 2013-11-22
  • 打赏
  • 举报
回复


如何CRC校验错误就重发呢?从机接收到的CRC与从机计算出的CRC比较,如果不相等则通知主机重发数据?这样不就成了一问一答的通信方式吗?

要可靠的话必须要有ACK,类似你说的一问一答
分两种情况,一种是下位机超时没收到,另一种是下位机收到了但校验不对

发送完毕--->状态:发送完等待接收,计时器置零--->等待接收方返回ACK
--->接收方返回校验错误--->重发

--->没有任何返回超时---->重发
诶呦 2013-11-22
  • 打赏
  • 举报
回复
引用 2 楼 youimisss 的回复:
[quote=引用 1 楼 echoyin59 的回复:] crc校验错误就重发 搞个定时器,超时了重发 先把这两个基本的实现,剩下的就是协议和细节了。
如何CRC校验错误就重发呢?从机接收到的CRC与从机计算出的CRC比较,如果不相等则通知主机重发数据?这样不就成了一问一答的通信方式吗?[/quote] 是啊,一问一答,很符合正常思维。 你的想法是?
youimisss 2013-11-22
  • 打赏
  • 举报
回复
引用 3 楼 of123 的回复:
需要自己搞一个数据链路层协议。串口协议本身是物理层的,有奇偶校验。但没有规定错误处理的方法。
这如何搞啊?有没有什么资料推荐学习下?
of123 2013-11-22
  • 打赏
  • 举报
回复
需要自己搞一个数据链路层协议。串口协议本身是物理层的,有奇偶校验。但没有规定错误处理的方法。
youimisss 2013-11-22
  • 打赏
  • 举报
回复
引用 1 楼 echoyin59 的回复:
crc校验错误就重发 搞个定时器,超时了重发 先把这两个基本的实现,剩下的就是协议和细节了。
如何CRC校验错误就重发呢?从机接收到的CRC与从机计算出的CRC比较,如果不相等则通知主机重发数据?这样不就成了一问一答的通信方式吗?
诶呦 2013-11-22
  • 打赏
  • 举报
回复
crc校验错误就重发 搞个定时器,超时了重发 先把这两个基本的实现,剩下的就是协议和细节了。

27,521

社区成员

发帖
与我相关
我的任务
社区描述
硬件/嵌入开发 单片机/工控
社区管理员
  • 单片机/工控社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧