51单片机串口接收不定长数据
请教大神,单片机串口如何接收不定长数据啊 ,比如 0x01+0x03+len+data0....datan CRC_HCRC_L 写了一下午没啥成果 本帖最后由 xpstudio2011 于 2015-12-15 20:35 编辑去看下DIY版的3D打印机固件里的串口通讯程序。相当好的。
Marlin或者 较早的Sprinter 都是用一差不多的程序。
包括了CRC校验之类的操作。 下位机这边一字节一字节的接收,判断起始字节是不是0x01和0x03,是的话就接着判断,不是的话就把数据扔了重新判断
如果上一步判断接收到的事起始字节,那么第三字节就是数据长度n,然后接下来接收n字节的数据字节,之后接收的两字节是校验字节,如果校验没有问题则数据有效,如果校验有问题则数据丢掉
一堆if else 或者case 2种方法,1实时地进行if else 2 fifo缓冲区接收 main中进行测量,这种实时性稍微差些,但是用着也不错。 这不是modbus吗?用时间间隔来区分帧的 myin4 发表于 2015-12-15 20:53
这不是modbus吗?用时间间隔来区分帧的
第一次搞 能不能给源码分析一下? prow 发表于 2015-12-15 20:38
下位机这边一字节一字节的接收,判断起始字节是不是0x01和0x03,是的话就接着判断,不是的话就把数据扔了重 ...
我就是用else if 写的不好用 xpstudio2011 发表于 2015-12-15 20:33
去看下DIY版的3D打印机固件里的串口通讯程序。相当好的。
Marlin或者 较早的Sprinter 都是用一差不多的程 ...
打印机的没有看到,有没有链接,嘿嘿 上网一搜modbus就出来了呀,
多用个定时器,串口接收中断里面开定时器,T35之后就是一帧了 随便帮写了段,仅供参考!!! 接收状态机变量step初始化为0 浮生莫若闲 发表于 2015-12-15 21:24
接收状态机变量step初始化为0
我字节写了一个感觉串口反应缓慢点串口调试助手的发送点好几下才能收到一帧数据 请问大神这事什么问题
1328616904 发表于 2015-12-15 21:34
我字节写了一个感觉串口反应缓慢点串口调试助手的发送点好几下才能收到一帧数据 请问大神这事什么 ...
我不是什么大神哦,想查问题,就上你的代码,不然我只能掐指头算。我要能掐指算的话,早就买彩票去咯 建立缓冲区接收数据, main中进行帧判断. 这样容易移植 用缓冲区接受,超时从缓冲区取数据判断,这样做通用性很强。 talkingbeast 发表于 2015-12-15 22:36
用缓冲区接受,超时从缓冲区取数据判断,这样做通用性很强。
超时从缓冲区取数据判断这个怎么理解? 还请指点 浮生莫若闲 发表于 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
} vjcmain 发表于 2015-12-15 22:40
超时从缓冲区取数据判断这个怎么理解? 还请指点
1.接收数据存放在缓冲区中;当接收字节超时发生时,调用数据处理函数;
2.数据处理:从缓冲区中获取接收到的数据流,判断是否符合modbus协议或者自定义协议格式,然后判断;
这样的架构可以处理多种协议格式,比如没有包头包尾结构的modbus协议;或者有包头包尾的协议;接收数据长度固定和可变都可以处理,通用性很好。 就是判断相邻两个数据之间的间隔。比如超过10ms就判定接收完成一帧数据。 miaoguoqiang 发表于 2015-12-21 09:14
就是判断相邻两个数据之间的间隔。比如超过10ms就判定接收完成一帧数据。
谢谢,我解决了我延时20毫秒 {:titter:}{:victory:} 遵循 学习 下标准 modbus 就会明白了 1328616904 发表于 2015-12-22 14:03
谢谢,我解决了我延时20毫秒
楼主是怎么解决的,20毫秒是在哪里调的啊? modbus的程序网上有很多,下载一个看看就懂了 河图洛书 发表于 2015-12-22 14:20
楼主是怎么解决的,20毫秒是在哪里调的啊?
在发送度寄存器命令之后就开始延时,20ms足够从机返回数据了,20ms内读到就读到了 读不到也执行下面的程序,这样也能防止死机,不知道这样是否妥当 间隔20ms那是超时处理,这个显然是modbus协议,只要在读取字长字节时改变整个命令的长度就可以了,光处理超时显然不行 czzhouyun 发表于 2015-12-23 12:03
间隔20ms那是超时处理,这个显然是modbus协议,只要在读取字长字节时改变整个命令的长度就可以了,光处理超 ...
对,我根据需要接受命令的长度,控制串口的接收计数器和延时处理,这样既能保证数据的准确性又可以方式死机 设置定时器,串口接收中断重置定时器,定时器溢出中断设置标志位,判断标志位,处理 楼主可以把这个程序发上来学习下吗? mailyyg@163.com 发表于 2015-12-23 13:57
设置定时器,串口接收中断重置定时器,定时器溢出中断设置标志位,判断标志位,处理 ...
差不多吧
最近也在写串口不定长接收,学习了。谢谢楼主 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;}
} hongguan 发表于 2018-3-9 14:48
void ComInINT(void) interrupt 4 //using 1//串口接收-中断函数
{
uchar xdata comm_dat;//串 ...
谢谢,学习了!
页:
[1]