1328616904 发表于 2015-12-15 20:31:15

51单片机串口接收不定长数据

请教大神,单片机串口如何接收不定长数据啊 ,比如 0x01+0x03+len+data0....datan CRC_HCRC_L 写了一下午没啥成果

xpstudio2011 发表于 2015-12-15 20:33:58

本帖最后由 xpstudio2011 于 2015-12-15 20:35 编辑

去看下DIY版的3D打印机固件里的串口通讯程序。相当好的。
Marlin或者 较早的Sprinter 都是用一差不多的程序。
包括了CRC校验之类的操作。

prow 发表于 2015-12-15 20:38:23

下位机这边一字节一字节的接收,判断起始字节是不是0x01和0x03,是的话就接着判断,不是的话就把数据扔了重新判断

如果上一步判断接收到的事起始字节,那么第三字节就是数据长度n,然后接下来接收n字节的数据字节,之后接收的两字节是校验字节,如果校验没有问题则数据有效,如果校验有问题则数据丢掉

一堆if else 或者case

10xjzheng 发表于 2015-12-15 20:51:35

2种方法,1实时地进行if else 2 fifo缓冲区接收 main中进行测量,这种实时性稍微差些,但是用着也不错。

myin4 发表于 2015-12-15 20:53:37

这不是modbus吗?用时间间隔来区分帧的

1328616904 发表于 2015-12-15 20:54:51

myin4 发表于 2015-12-15 20:53
这不是modbus吗?用时间间隔来区分帧的

第一次搞 能不能给源码分析一下?

1328616904 发表于 2015-12-15 20:56:44

prow 发表于 2015-12-15 20:38
下位机这边一字节一字节的接收,判断起始字节是不是0x01和0x03,是的话就接着判断,不是的话就把数据扔了重 ...

我就是用else if 写的不好用

霸气侧漏 发表于 2015-12-15 21:01:25

xpstudio2011 发表于 2015-12-15 20:33
去看下DIY版的3D打印机固件里的串口通讯程序。相当好的。
Marlin或者 较早的Sprinter 都是用一差不多的程 ...

打印机的没有看到,有没有链接,嘿嘿

myin4 发表于 2015-12-15 21:02:30

上网一搜modbus就出来了呀,
多用个定时器,串口接收中断里面开定时器,T35之后就是一帧了

浮生莫若闲 发表于 2015-12-15 21:14:43

随便帮写了段,仅供参考!!!

浮生莫若闲 发表于 2015-12-15 21:24:04

接收状态机变量step初始化为0

1328616904 发表于 2015-12-15 21:34:51

浮生莫若闲 发表于 2015-12-15 21:24
接收状态机变量step初始化为0

我字节写了一个感觉串口反应缓慢点串口调试助手的发送点好几下才能收到一帧数据   请问大神这事什么问题

浮生莫若闲 发表于 2015-12-15 21:48:19

1328616904 发表于 2015-12-15 21:34
我字节写了一个感觉串口反应缓慢点串口调试助手的发送点好几下才能收到一帧数据   请问大神这事什么 ...

我不是什么大神哦,想查问题,就上你的代码,不然我只能掐指头算。我要能掐指算的话,早就买彩票去咯

fchen2 发表于 2015-12-15 21:59:12

建立缓冲区接收数据, main中进行帧判断. 这样容易移植

talkingbeast 发表于 2015-12-15 22:36:26

   用缓冲区接受,超时从缓冲区取数据判断,这样做通用性很强。

vjcmain 发表于 2015-12-15 22:40:14

talkingbeast 发表于 2015-12-15 22:36
用缓冲区接受,超时从缓冲区取数据判断,这样做通用性很强。

超时从缓冲区取数据判断这个怎么理解? 还请指点

1328616904 发表于 2015-12-16 08:18:57

浮生莫若闲 发表于 2015-12-15 21:48
我不是什么大神哦,想查问题,就上你的代码,不然我只能掐指头算。我要能掐指算的话,早就买彩票去咯 ...

voidUART2_IRQHandler (void)
{
    static unsigned char count;
   UART_MemMapPtr uartPtr = UART2_BASE_PTR;                           /* ·¢ËÍÖжϴ¦Àí³ÌÐò             */
   #if UART2_SEND_IRQ                                                   /* Óû§¶¨Òå                     */
   #endif
   
   #if UART2_RECEIVE_IRQ
if (UART_S1_REG(uartPtr) & UART_S1_RDRF_MASK)
   {                  /* Çå³ýÖжϱêÖ¾               */
      
   // uart0SendChar ( UART_D_REG(uartPtr));
   tab = UART_D_REG (uartPtr );
   if(tab == 0x01 && count == 0x00)
   {
      count = 1;
   }
   else if(tab == 0x03 && count == 1)
   {
      count = 2;
   }
   
   else if(count >= 2 && count < 8)
   {
      count ++;
   }
   else if(count == 8)
   {
      count = 0;
//      for(i=0;i<8;i++)
//         {
//            uart0SendChar (tab);
//         }
         //printf("size=%d\n",sizeof(tab));
      //datalen = 0x00;   
         uart0SendChar (crc16(tab,7)>>8);
         uart0SendChar (crc16(tab,7)&0xff);
         
         
   }
   else
   {
         count = 0;
         //datalen = 0;
   }
      
   }   
   #endif   
}

talkingbeast 发表于 2015-12-16 09:35:46

vjcmain 发表于 2015-12-15 22:40
超时从缓冲区取数据判断这个怎么理解? 还请指点

1.接收数据存放在缓冲区中;当接收字节超时发生时,调用数据处理函数;
2.数据处理:从缓冲区中获取接收到的数据流,判断是否符合modbus协议或者自定义协议格式,然后判断;
这样的架构可以处理多种协议格式,比如没有包头包尾结构的modbus协议;或者有包头包尾的协议;接收数据长度固定和可变都可以处理,通用性很好。

miaoguoqiang 发表于 2015-12-21 09:14:36

就是判断相邻两个数据之间的间隔。比如超过10ms就判定接收完成一帧数据。

1328616904 发表于 2015-12-22 14:03:29

miaoguoqiang 发表于 2015-12-21 09:14
就是判断相邻两个数据之间的间隔。比如超过10ms就判定接收完成一帧数据。

谢谢,我解决了我延时20毫秒

wkman 发表于 2015-12-22 14:14:51

{:titter:}{:victory:} 遵循 学习 下标准 modbus 就会明白了

河图洛书 发表于 2015-12-22 14:20:49

1328616904 发表于 2015-12-22 14:03
谢谢,我解决了我延时20毫秒

楼主是怎么解决的,20毫秒是在哪里调的啊?

xiaobendan 发表于 2015-12-23 08:30:28

modbus的程序网上有很多,下载一个看看就懂了

1328616904 发表于 2015-12-23 10:17:14

河图洛书 发表于 2015-12-22 14:20
楼主是怎么解决的,20毫秒是在哪里调的啊?

在发送度寄存器命令之后就开始延时,20ms足够从机返回数据了,20ms内读到就读到了 读不到也执行下面的程序,这样也能防止死机,不知道这样是否妥当

czzhouyun 发表于 2015-12-23 12:03:34

间隔20ms那是超时处理,这个显然是modbus协议,只要在读取字长字节时改变整个命令的长度就可以了,光处理超时显然不行

1328616904 发表于 2015-12-23 13:41:21

czzhouyun 发表于 2015-12-23 12:03
间隔20ms那是超时处理,这个显然是modbus协议,只要在读取字长字节时改变整个命令的长度就可以了,光处理超 ...

对,我根据需要接受命令的长度,控制串口的接收计数器和延时处理,这样既能保证数据的准确性又可以方式死机

mailyyg@163.com 发表于 2015-12-23 13:57:30

设置定时器,串口接收中断重置定时器,定时器溢出中断设置标志位,判断标志位,处理

chen849928055 发表于 2015-12-23 14:05:58

楼主可以把这个程序发上来学习下吗?

1328616904 发表于 2015-12-23 17:17:40

mailyyg@163.com 发表于 2015-12-23 13:57
设置定时器,串口接收中断重置定时器,定时器溢出中断设置标志位,判断标志位,处理 ...

差不多吧

ypc168k 发表于 2018-1-22 17:54:28

最近也在写串口不定长接收,学习了。谢谢楼主

hongguan 发表于 2018-3-9 14:48:42

void ComInINT(void) interrupt 4 //using 1//串口接收-中断函数
{   
        uchar xdata comm_dat;//串口接收
        uchar dat,i;
       
    if(RI)
    {
      RI=0;
      dat=SBUF;
                                switch (step)
                                {
                                        case 1:
                                        {
                                                Count=0;
                                                if(dat=='/')step=2;
                                                else step=1;
                                        }
                                        break;

                                        case 2:
                                        {
                                                comm_dat=dat;
                                                if(comm_dat==0x0d)step=3;
                                                else step=2; Count++;                                       
                                                if(Count>64){Count=0;step=2;}
                                        }
                                        break;
                                        case 3:
                                        {                                                                               
                                                    for(i=0;i<Count;i++)chs=comm_dat;
                                                for(i=0;i<64;i++)comm_dat=0;
                                                read_flag=1; step=0; dat=0;
                                        }
                                        break;
                                       
                                        default:{}break;
                                }                                                               
    }
    if(TI)
                        {TI = 0;busy = 0;}
}

ypc168k 发表于 2018-8-6 15:36:05

hongguan 发表于 2018-3-9 14:48
void ComInINT(void) interrupt 4 //using 1//串口接收-中断函数
{   
        uchar xdata comm_dat;//串 ...

谢谢,学习了!
页: [1]
查看完整版本: 51单片机串口接收不定长数据