打印

怎么尽可能保证串口数据全接收,长时间接收

[复制链接]
10143|20
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
yzmvv|  楼主 | 2013-3-21 11:09 | 只看该作者 |只看大图 回帖奖励 |倒序浏览 |阅读模式
想请教个问题。 今天做了个串口环形缓冲测试,PC用115200速度对STM32F103发数据,一次发20字节,板子接收以后在返回到PC,结果测试几分钟之后,出现了一次乱码,PC接收到的数据量显示比发送的少了一个字节。
怎么才能保证发送给STM32串口的数据100%被接收下来呢, 从软件 程序上考虑, 缓冲区怎么设计, 我用的是环形缓冲。没开DMA,  个人感觉,开了DMA的话,原理跟没开DMA是一样的,只不过是减少了中断次数而已,但是在长时间接收时,也不一定能保证全部接收吧,尤其是还有其他任务要处理,比如数据写到sd卡?
沙发
IJK| | 2013-3-21 11:50 | 只看该作者
115200这个波特率其实对STM32F103来说不快,不可能收不下来。
用环形缓冲也是个好办法。如果担心,可以把buffer开大点,个人觉得128个字节就足够了。不开DMA也没有问题,中断出来完全来得及,长时间接收也没问题的。
个人觉得即使1M的串口波特率,STM32F103也来得及处理,因为LZ只需要收到就发出

使用特权

评论回复
板凳
yzmvv|  楼主 | 2013-3-21 13:31 | 只看该作者
IJK 发表于 2013-3-21 11:50
115200这个波特率其实对STM32F103来说不快,不可能收不下来。
用环形缓冲也是个好办法。如果担心,可以把bu ...

恩,我也听别人说过,是这个样子的。可是我今天这个测试还是失败了,估计是程序上的问题,求懂的帮我看看这个环形缓冲有没有问题。BUFFERSIZE 开始设置的5,后来设置的25, 测试时是1ms间隔循环发送20个字节。现在准备把buffer改成128试试
static u8 ReceiveBuffer[BUFFERSIZE];
static u8 WrBuf=0;
static u8 ReBuf=0;

void USART1_IRQHandler(void)
{
        uint8_t ReceiveDate;                                                                //定义一个变量存放接收的数据
        if(!(USART_GetITStatus(USART1,USART_IT_RXNE)));         //读取接收中断标志位USART_IT_RXNE
                                                                                                               
        {
           USART_ClearITPendingBit(USART1,USART_IT_RXNE);        //清楚中断标志位
           WriteBuffer();
        }  
}
void WriteBuffer( void)
{
    if (WrBuf==ReBuf-1)
        {
                return;
        }
        ReceiveBuffer[WrBuf++]=USART_ReceiveData(USART1);
        WrBuf=WrBuf%BUFFERSIZE;
}
u8 ReadBuffer(u8 *data)
{
        if(ReBuf==WrBuf)
        {
                return 0;
        }
        *data=ReceiveBuffer[ReBuf];
        ReBuf++;
        ReBuf=ReBuf%BUFFERSIZE;
        return 1;

}
int main(void)
{
        u8 data=0;
        SystemInit();                                        //系统时钟配置
        Init_NVIC();                                        //中断向量表注册函数
        Init_LED();                                                //各个外设引脚配置
        Init_Usart();                                        //串口引脚配置
        Usart_Configuration(115200);        //串口配置 设置波特率为115200  
        while(1)                                                                                                       
        {  
                if (ReadBuffer(&data))
                {
                        USART1_Send_Byte(data);
                }
        }
}

使用特权

评论回复
地板
buaaszb| | 2013-3-21 13:45 | 只看该作者
WriteBuffer()中有对WrBuf,ReBuf变量的操作,ReadBuffer()函数也操作了这2个变量。WriteBuffer()在中断中调用,ReadBuffer()在主循环调用。这肯定会出问题,你应该在ReadBuffer()中关闭中断。

使用特权

评论回复
5
yueliangruying| | 2013-3-21 13:51 | 只看该作者
1ms内stm32处理的字符数115200/1000/8=14个字符,你1ms间隔循环发送20个字节太快了吧

使用特权

评论回复
6
yzmvv|  楼主 | 2013-3-21 14:44 | 只看该作者
buaaszb 发表于 2013-3-21 13:45
WriteBuffer()中有对WrBuf,ReBuf变量的操作,ReadBuffer()函数也操作了这2个变量。WriteBuffer()在中断中 ...

循环缓冲区,
WriteBuffer()和ReadBuffer()函数虽然里面都有WrBuf,ReBuf两个变量,但是WrBuf变量只在WriteBuffer()函数中进行了操作,同理,另一个也是,没有同时操作,两个变量只是比较了一下而已。在ReadBuffer()中关闭中断,那主循环再执行Read的时候,数据不是无法接收下来了?  我是这么想的,不知道对不对

使用特权

评论回复
7
yzmvv|  楼主 | 2013-3-21 14:52 | 只看该作者
yueliangruying 发表于 2013-3-21 13:51
1ms内stm32处理的字符数115200/1000/8=14个字符,你1ms间隔循环发送20个字节太快了吧 ...

感觉说的很有道理。那应该是 在串口固定波特率发送的时候, 单位时间发送的字节数过多,就会超过这个波特率的本身速度,从而导致发送端 出问题,

使用特权

评论回复
8
yzmvv|  楼主 | 2013-3-21 15:36 | 只看该作者
缓冲区设置128字节,1ms间隔循环发送13个字符,测试一段时间后,又出现问题。从发送 和接收字节看 似乎数据没没有丢失现象,但是为什么会乱码呢

QQ截图20130321153414.png (36.31 KB )

QQ截图20130321153414.png

使用特权

评论回复
9
buaaszb| | 2013-3-21 15:56 | 只看该作者
当程序执行ReadBuffer()时,发生中断,WrBuf,ReBuf在中断里会被修改,中断返回后,ReadBuffer()面对的是已经被修改的WrBuf,ReBuf,所以会发生错误。所以,你在ReadBuffer()里,先关中断,最末尾再打开中断。

使用特权

评论回复
10
yzmvv|  楼主 | 2013-3-21 16:12 | 只看该作者
学习了,多谢。但是如果关中断这段时间,来了数据,就无法接收了啊?  如果把WrBuf,ReBuf这两个变量定义为volatile类型,是不是也能解决这个问题?

使用特权

评论回复
11
yzmvv|  楼主 | 2013-3-21 16:13 | 只看该作者
buaaszb 发表于 2013-3-21 15:56
当程序执行ReadBuffer()时,发生中断,WrBuf,ReBuf在中断里会被修改,中断返回后,ReadBuffer()面对的是已 ...


学习了,多谢。但是如果关中断这段时间,来了数据,就无法接收了啊?  如果把WrBuf,ReBuf这两个变量定义为volatile类型,是不是也能解决这个问题?

使用特权

评论回复
12
yzmvv|  楼主 | 2013-3-21 16:14 | 只看该作者
buaaszb 发表于 2013-3-21 15:56
当程序执行ReadBuffer()时,发生中断,WrBuf,ReBuf在中断里会被修改,中断返回后,ReadBuffer()面对的是已 ...


学习了,多谢。但是如果关中断这段时间,来了数据,就无法接收了啊?  如果把WrBuf,ReBuf这两个变量定义为volatile类型,是不是也能解决这个问题?

使用特权

评论回复
13
buaaszb| | 2013-3-21 16:24 | 只看该作者
ReadBuffer()执行时间很短,估计不超过50个指令周期,这点时间不会影响中断接收的

使用特权

评论回复
14
yzmvv|  楼主 | 2013-3-21 17:21 | 只看该作者
buaaszb 发表于 2013-3-21 16:24
ReadBuffer()执行时间很短,估计不超过50个指令周期,这点时间不会影响中断接收的 ...

这下明白了,以后写中断程序这点必须注意。    不过我又读了遍程序,就我这个程序而言,ReadBuffer函数只对ReBuf变量操作,WriteBuffer函数只对WrBuf操作,唯一可能出错的是 主循环调用ReadBuffer时,关于WrBuf和ReBuf的比较时, 中断导致WrBuf的变化,也就是再中断里面的 WrBuf++。 我这里即使发生了这种情况 ,其本身并不影响逻辑判断的结果, 这样的话,是否还有必要加上开关中断这一过程。问的比较多了,麻烦知道的话讲一下,谢谢。

使用特权

评论回复
15
ifpga| | 2013-3-22 10:03 | 只看该作者

使用特权

评论回复
16
xuanzhuan360| | 2013-3-26 23:46 | 只看该作者
换其他串口助手试试呢  

使用特权

评论回复
17
yzmvv|  楼主 | 2013-3-30 10:15 | 只看该作者
是板子出了问题,严格说是板子的串口模块出了问题,所以才会这样,因为这个程序测试时间长了,大约两个小时,关掉板子电源,向板子发送的数据  竟然也返回到了电脑上,但是是乱码。  正常断电情况下,串口不应该是断路才对吗, 怎么还能将电脑发回的数据返回去呢?

使用特权

评论回复
18
yzmvv|  楼主 | 2013-3-30 10:16 | 只看该作者
反正换了一块板子,测试了一晚上,都很正常,没有乱码,数据接收的跟发送的 一样多。

使用特权

评论回复
19
hawksabre| | 2013-3-30 17:30 | 只看该作者
呵呵  问题解决了就好   呵呵     多逛21ic   没有搞不定的问题   呵呵   顶一个

使用特权

评论回复
20
yzmvv|  楼主 | 2013-3-31 19:54 | 只看该作者
对21ic确实比较满意,个人感觉这里比其他论坛热情。

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

3

主题

25

帖子

0

粉丝