共2条
1/1 1 跳转至页
串口缓冲池的遍历,恳请帮忙改正!(有源码)

问
现在做一通信程序,从串口进来数据以9600bps、500~800bytes/秒的速率进入缓冲区,然后主循环中以环形队列格式进行处理,从数据区中提取出所需的不同格式的消息。部分源码如下:
//-------------------------------------------------------------------------------------
// 队列管理标志
//-------------------------------------------------------------------------------------
bit Overflow(void)
{
return((r_in-r_out)>(MaxSize-1)?1:0);
}
bit Empty(void)
{
return((r_in-r_out)<0?1:0);
}
bit Full(void)
{
if (!Overflow() && !Empty())
return(1);
else return(0);
}
main.c
...
while(1)
{
if (Full())
{
if (GpgsaHeader(&r_buf[r_out&0x7ff]))
{
a_count ++;
iLengthTemp = Ender(&r_buf[r_out&0x7ff]);
GpgsaSol(&r_buf[r_out&0x7ff]);
r_out += iLengthTemp;
}
else if (GpgsvHeader(&r_buf[r_out&0x7ff]))
{
v_count ++;
iLengthTemp = Ender(&r_buf[r_out&0x7ff]);
GpgsvSol(&r_buf[r_out&0x7ff]);
r_out += iLengthTemp;
}
else if ( BinMesHead(&r_buf[r_out&0x7ff]))
{
b_count ++;
iLengthTemp=(r_buf[(r_out+9)&0x7ff] << 8 )+r_buf[(r_out+8)&0x7ff];
if (iLengthTemp>0 && iLengthTemp < 4096)
{
r_out +=iLengthTemp+32;
}
}
r_out ++;
}
}
现在主要有几个问题:
1.如何控制队列的指针,不让r_out > r_in(通过仿真发现确实有超出)?
2.如何等待r_in相对r_out足够大,使得队列中已经正确存贮了一条或多条完整的消息?
3.能否帮忙分析一下以上程序的原理性错误?
4.能否提供一些相关的例程做参考?如有,请发EMAIL:nantiangumo@163.com
先谢谢各位啦!
答 1: 个人见解最好是使用循环队列 他的使用效率是最高的
在线形队列的基础上加上 头 尾 缓冲长度的变量即可 访问时注意地址跨界是的操作即可。 答 2: 这是我在用的一个环形缓冲区byte idata Uart_loop_buff[128];
byte data Uart_read_ptr = 0;
byte data Uart_write_ptr = 0;
byte data Uart_rcv_state = 0;
void Uart_Int(void) interrupt 4
{
if(RI)
{
RI = 0;
TI = 0;
Uart_loop_buff[Uart_write_ptr] = SBUF;
Uart_write_ptr = (Uart_write_ptr++)&0x7F;
}
}
void Uart_rcv_frame(void)
{
static byte step = 0;
static byte rcv_count = 0; /*接收计数*/
word data i = 0;
word data j = 0;
word data crc_temp = 0;
switch(step)
case 0:
if(Uart_read_ptr==Uart_write_ptr)
return;
if(Uart_loop_buff[Uart_read_ptr]!=Msg_head)
{
Uart_read_ptr = (Uart_read_ptr++)&0x7F;
return;
}
Uart_rcv_buff[Uart_rcv_length] = Uart_loop_buff[Uart_read_ptr];
Uart_read_ptr = (Uart_read_ptr++)&0x7F;
Uart_rcv_length++;
step++;
rcv_count++;
Set_Soft_Timer(0,6)
break;
case 1:
while(Uart_read_ptr!=Uart_write_ptr)
{
Uart_rcv_buff[Uart_rcv_length] = Uart_loop_buff[Uart_read_ptr];
Uart_read_prt++;
Uart_rcv_length++;
rcv_count++;
if(!Soft_timer[0])
break;
}
。。。
我的建议缓冲区大小由你的数据流及单片机处理能力决定,最好大些,防止溢出 答 3: ding two... 答 4: 真搞不明白,都是库函数惹的祸找信息头的时候用函数memcmp()来比对就要掉信息,非得一个个字符地比较,基本上解决
//-------------------------------------------------------------------------------------
// 队列管理标志
//-------------------------------------------------------------------------------------
bit Overflow(void)
{
return((r_in-r_out)>(MaxSize-1)?1:0);
}
bit Empty(void)
{
return((r_in-r_out)<0?1:0);
}
bit Full(void)
{
if (!Overflow() && !Empty())
return(1);
else return(0);
}
main.c
...
while(1)
{
if (Full())
{
if (GpgsaHeader(&r_buf[r_out&0x7ff]))
{
a_count ++;
iLengthTemp = Ender(&r_buf[r_out&0x7ff]);
GpgsaSol(&r_buf[r_out&0x7ff]);
r_out += iLengthTemp;
}
else if (GpgsvHeader(&r_buf[r_out&0x7ff]))
{
v_count ++;
iLengthTemp = Ender(&r_buf[r_out&0x7ff]);
GpgsvSol(&r_buf[r_out&0x7ff]);
r_out += iLengthTemp;
}
else if ( BinMesHead(&r_buf[r_out&0x7ff]))
{
b_count ++;
iLengthTemp=(r_buf[(r_out+9)&0x7ff] << 8 )+r_buf[(r_out+8)&0x7ff];
if (iLengthTemp>0 && iLengthTemp < 4096)
{
r_out +=iLengthTemp+32;
}
}
r_out ++;
}
}
现在主要有几个问题:
1.如何控制队列的指针,不让r_out > r_in(通过仿真发现确实有超出)?
2.如何等待r_in相对r_out足够大,使得队列中已经正确存贮了一条或多条完整的消息?
3.能否帮忙分析一下以上程序的原理性错误?
4.能否提供一些相关的例程做参考?如有,请发EMAIL:nantiangumo@163.com
先谢谢各位啦!
答 1: 个人见解最好是使用循环队列 他的使用效率是最高的
在线形队列的基础上加上 头 尾 缓冲长度的变量即可 访问时注意地址跨界是的操作即可。 答 2: 这是我在用的一个环形缓冲区byte idata Uart_loop_buff[128];
byte data Uart_read_ptr = 0;
byte data Uart_write_ptr = 0;
byte data Uart_rcv_state = 0;
void Uart_Int(void) interrupt 4
{
if(RI)
{
RI = 0;
TI = 0;
Uart_loop_buff[Uart_write_ptr] = SBUF;
Uart_write_ptr = (Uart_write_ptr++)&0x7F;
}
}
void Uart_rcv_frame(void)
{
static byte step = 0;
static byte rcv_count = 0; /*接收计数*/
word data i = 0;
word data j = 0;
word data crc_temp = 0;
switch(step)
case 0:
if(Uart_read_ptr==Uart_write_ptr)
return;
if(Uart_loop_buff[Uart_read_ptr]!=Msg_head)
{
Uart_read_ptr = (Uart_read_ptr++)&0x7F;
return;
}
Uart_rcv_buff[Uart_rcv_length] = Uart_loop_buff[Uart_read_ptr];
Uart_read_ptr = (Uart_read_ptr++)&0x7F;
Uart_rcv_length++;
step++;
rcv_count++;
Set_Soft_Timer(0,6)
break;
case 1:
while(Uart_read_ptr!=Uart_write_ptr)
{
Uart_rcv_buff[Uart_rcv_length] = Uart_loop_buff[Uart_read_ptr];
Uart_read_prt++;
Uart_rcv_length++;
rcv_count++;
if(!Soft_timer[0])
break;
}
。。。
我的建议缓冲区大小由你的数据流及单片机处理能力决定,最好大些,防止溢出 答 3: ding two... 答 4: 真搞不明白,都是库函数惹的祸找信息头的时候用函数memcmp()来比对就要掉信息,非得一个个字符地比较,基本上解决
共2条
1/1 1 跳转至页
回复
有奖活动 | |
---|---|
【EEPW电子工程师创研计划】技术变现通道已开启~ | |
发原创文章 【每月瓜分千元赏金 凭实力攒钱买好礼~】 | |
【EEPW在线】E起听工程师的声音! | |
“我踩过的那些坑”主题活动——第001期 | |
高校联络员开始招募啦!有惊喜!! | |
【工程师专属福利】每天30秒,积分轻松拿!EEPW宠粉打卡计划启动! | |
送您一块开发板,2025年“我要开发板活动”又开始了! | |
打赏了!打赏了!打赏了! |
打赏帖 | |
---|---|
【我踩过的那些坑】STM32的硬件通讯调试过程的“坑”被打赏50分 | |
【我踩过的那些坑】晶振使用的问题被打赏100分 | |
【我踩过的那些坑】电感选型错误导致的处理器连接不上被打赏50分 | |
【我踩过的那些坑】工作那些年踩过的记忆深刻的坑被打赏10分 | |
【我踩过的那些坑】DRC使用位置错误导致的问题被打赏100分 | |
我踩过的那些坑之混合OTL功放与落地音箱被打赏50分 | |
汽车电子中巡航控制系统的使用被打赏10分 | |
【我踩过的那些坑】工作那些年踩过的记忆深刻的坑被打赏100分 | |
分享汽车电子中巡航控制系统知识被打赏10分 | |
分享安全气囊系统的检修注意事项被打赏10分 |