OpenEdv-开源电子网

 找回密码
 立即注册
正点原子全套STM32/Linux/FPGA开发资料,上千讲STM32视频教程免费下载...
查看: 19898|回复: 12

STM32多串口情况下总是发生过载(ORE)错误

[复制链接]

1

主题

4

帖子

0

精华

新手入门

积分
32
金钱
32
注册时间
2014-9-15
在线时间
0 小时
发表于 2014-9-15 19:44:12 | 显示全部楼层 |阅读模式
5金钱
我的程序需要实现的功能是通过两个串口分别控制WIFI和Zigbee的通讯,WIFI和Zigbee的通讯都是双向的,并且发生的时间是不一定的(也就是说可能会出现Zigbee和WIFI同时接收到数据的情况)。
我在程序中分别用到了USART1和USART3来接收数据,然后在调试的过程中发现程序跑死在了串口中断中,检查相应的串口SR寄存器发现是发生了过载(ORE)错误从而触发串口中断,由于我没有对这种问题进行处理,所以串口中断就不停地触发,从而造成程序跑死在串口中断中了。

情况细节补充:
1.程序中只用到了1个定时器中断和两个串口中断,除此之外没有其他的中断了,同时USART1的中断优先级为0,1(抢占和子优先级),USART3优先级为1,2,定时器中断优先级为3,3;
2.USART1所设波特率为115200,USART3所设波特率为1M,并且USART1和USART3都出现过过载错误;
3.程序源码
/*********************************************************************************************************
    串口1中断服务函数,接收中断,ZigBee
*********************************************************************************************************/
void USART1_IRQHandler(void)
{
    unsigned char i;
    unsigned int data_begin_point = 0;  

    LED0=!LED0;

    if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET)
    {
        Zigbee_Rx_Buf[Zigbee_Rx_Cnt++] = USART_ReceiveData(USART1);

/*********************************************************************************************************
                
*********************************************************************************************************/
        if(API_Rx_Identifier)
        {
            API_Rx_Cnt++;
            API_Rx_Checksum += Zigbee_Rx_Buf[Zigbee_Rx_Cnt-1];
            if(API_Rx_Cnt >=(API_Rx_Len+1))
            {
                Test_Zigbee_Rx_Num++;
                if(API_Rx_Checksum == 0xFF)        //校验和核对正确,接收完成
                {
                    if(Zigbee_Rx_Cnt >= (API_Rx_Len-11) )
                        data_begin_point = Zigbee_Rx_Cnt-API_Rx_Len+11;
                    else
                        data_begin_point = ZIGBEE_RECEIVEBUF_SIZE+Zigbee_Rx_Cnt-API_Rx_Len+11;
    
                    for(i=0;i < (API_Rx_Len-12);i++)
                    {
                        ReceiveData_Zigbee[Zigbee_Rx_Point] = Zigbee_Rx_Buf[data_begin_point];
                        data_begin_point++;
                        if(data_begin_point >= ZIGBEE_RECEIVEBUF_SIZE)
                            data_begin_point = 0;
                    }
    
                    Zigbee_Rx_Num[Zigbee_Rx_Point] = API_Rx_Len-12;

                    Zigbee_Rx_Point++;
                    if(Zigbee_Rx_Point >= ZIGBEE_RECV_SIZE)
                        Zigbee_Rx_Point = 0;
        
                    for(i = 0; i < ZIGBEE_RECEIVEBUF_SIZE; i++)
                    {
                        ReceiveData_Zigbee[Zigbee_Rx_Point] = 0;
                    }
                    
                    Zigbee_Rx_Flag = 1;

                    if((API_Rx_Len-12) == 47)
                        Test_Data_Num++;
                    else if((API_Rx_Len-12) == 63)
                        Test_Para_Num++;
                    else if((API_Rx_Len-12) == 52)
                        Test_Stat_Num++;
                    else if((API_Rx_Len-12) == 9)
                        Test_ACK_Num++;
                }

                API_Rx_Checksum = 0;
                                
                API_Rx_Cnt = 0;
                API_Rx_Identifier = 0;
                API_Rx_Len = 0;

                Zigbee_Rx_Cnt = 0;
                for(i = 0; i < ZIGBEE_RECEIVEBUF_SIZE; i++)
                {
                    Zigbee_Rx_Buf = 0;
                }
            }
        }
        else
        if((Zigbee_Rx_Buf[Zigbee_Rx_Cnt-1] == 0x90) && (Zigbee_Rx_Buf[Zigbee_Rx_Cnt-4] == 0x7E))//接收到API数据的帧头0x7E及接受包标识符0x90
        {
            API_Rx_Identifier = 1;
            API_Rx_Len = (Zigbee_Rx_Buf[Zigbee_Rx_Cnt-3]<<8);
            API_Rx_Len = Zigbee_Rx_Buf[Zigbee_Rx_Cnt-2];
            API_Rx_Cnt++;
            API_Rx_Checksum += 0x90;
        }

        if(Zigbee_Rx_Cnt >= ZIGBEE_RECEIVEBUF_SIZE)
        {
            Zigbee_Rx_Cnt = 0;
        }
    }
}

/*********************************************************************************************************
    串口3中断服务函数,接收中断,WIFI
*********************************************************************************************************/
void USART3_IRQHandler(void)                    //串口3中断服务程序
{
    unsigned char j = 0,k = 0;
    unsigned long i = 0;
    unsigned int code_num=0;
    unsigned short err_usart_sr,err_usart_cr;

    LED0=!LED0;

    if(USART_GetITStatus(USART3, USART_IT_RXNE) != RESET)
    {             
        ReceiveData2[Wifi_RX_Sta++] = USART_ReceiveData(USART3);
        /***************************************
                            WIFI数据解析程序段
        ***************************************/

    }
}
其中USART3接收中断中数据解析程序段程序比较长所以就不全部贴出来了,基本都是些if和switch的判断,我用LED灯的亮灭指示过USART3接收中断的执行时间,最长的情况下是24us

我想请问大神们以下两个问题:
1.我的这种应用情况下采用串口双中断的方式是否可行
2.频繁地发生这种过载错误的原因是什么
谢谢大家了!

最佳答案

查看完整内容[请看2#楼]

1.可行. 2.24us的处理时间早就过载了.
正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

2

主题

1446

帖子

1

精华

金牌会员

Rank: 6Rank: 6

积分
2249
金钱
2249
注册时间
2010-12-16
在线时间
203 小时
发表于 2014-9-15 19:44:13 | 显示全部楼层
1.可行.

2.24us的处理时间早就过载了.
技术讨论请发帖 , 需要我回复请点左下的 < 回复 > 让系统通知我 . 本人不通过其他方式返回任何参数.
回复

使用道具 举报

37

主题

146

帖子

0

精华

新手入门

积分
12
金钱
12
注册时间
2014-6-4
在线时间
90 小时
发表于 2014-9-15 20:58:57 | 显示全部楼层
这个程序不需要清楚接收标志位吗?
一路狂奔!
回复

使用道具 举报

1

主题

4

帖子

0

精华

新手入门

积分
32
金钱
32
注册时间
2014-9-15
在线时间
0 小时
 楼主| 发表于 2014-9-16 09:02:30 | 显示全部楼层
回复【2楼】南帝:
---------------------------------
你是想说清除接收标志位吗?读串口数据寄存器自动清了的啊
回复

使用道具 举报

1

主题

4

帖子

0

精华

新手入门

积分
32
金钱
32
注册时间
2014-9-15
在线时间
0 小时
 楼主| 发表于 2014-9-16 09:03:46 | 显示全部楼层
回复【3楼】shihantu:
---------------------------------
平常情况下处理时间是6us,只有当接受完了一包数据运行解析程序的时候才是24us。
回复

使用道具 举报

4

主题

200

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
236
金钱
236
注册时间
2012-12-19
在线时间
0 小时
发表于 2014-9-16 10:36:32 | 显示全部楼层
为什么不用环形缓冲区?
目前在玩STM32,BBB,RPi
回复

使用道具 举报

1

主题

4

帖子

0

精华

新手入门

积分
32
金钱
32
注册时间
2014-9-15
在线时间
0 小时
 楼主| 发表于 2014-9-16 10:41:21 | 显示全部楼层
回复【6楼】w0rmis20:
---------------------------------
环形缓冲区?没用过啊,STM32的串口有这个东西吗?
回复

使用道具 举报

4

主题

200

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
236
金钱
236
注册时间
2012-12-19
在线时间
0 小时
发表于 2014-9-16 12:16:00 | 显示全部楼层
回复【7楼】cowboyl:
---------------------------------
软件实现的,百度去
目前在玩STM32,BBB,RPi
回复

使用道具 举报

2

主题

26

帖子

0

精华

初级会员

Rank: 2

积分
128
金钱
128
注册时间
2019-4-13
在线时间
34 小时
发表于 2020-12-16 10:30:14 | 显示全部楼层
w0rmis20 发表于 2014-9-16 12:16
回复【7楼】cowboyl:
---------------------------------
软件实现的,百度去

环形缓冲区 照样ore,我也遇到了同样的问题,不知该如何
回复

使用道具 举报

6

主题

45

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
268
金钱
268
注册时间
2014-11-26
在线时间
93 小时
发表于 2021-10-10 11:42:13 | 显示全部楼层
清除ore
回复

使用道具 举报

0

主题

79

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
1928
金钱
1928
注册时间
2018-10-11
在线时间
256 小时
发表于 2021-10-10 11:57:42 | 显示全部楼层
中断服务程序太长了,数据解析大可以放到中断外面来做....
回复

使用道具 举报

0

主题

5

帖子

0

精华

新手入门

积分
17
金钱
17
注册时间
2020-12-7
在线时间
4 小时
发表于 2021-10-10 15:29:05 | 显示全部楼层
    程序设计应该根据最高波特率算出字节时间,你的中断程序运行时间必须远小于字节时间,之间的差值足够把其它所有可能发生的中断都执行上一遍,而且多少给主程序留下点时间,不管什么单片机都是这个道理。建议中断只做接收数据的暂存和即时性要求高的必要处理,协议层面的事都放到主程序去,或者干脆用DMA收串口数据。
    其实我想说的是用STM32干8位、4位机的事可以拷贝开发板例程修修补补,多任务就上操作系统。但如果要干点能体现STM32高速性能的事还是要有编程思想,底层驱动库根据自己的要求重新写,该操作寄存器就操作寄存器。楼主的情况属于对中断的本质完全不了解,本中断就把自己搞溢出了,如果再考虑考虑多种、多级别的中断综合起来基本上就是“STM32-从入门到弃坑”,都说STM32简单易学易用,但那是建立在跑流水灯、处理个按键数码管等没速度要求的情况下,就算刷个TFT小彩屏接个摄像头如果用卖家例程或自己用库写的都远没有用高性能51内核汇编跑得利索。总之,任何东西要用好都要下一番功夫,如果需求简单又允许用高射炮打蚊子就当我没说好了。
    最后,我上述言语不是针对楼主个人,任何人学习都有个过程,引发我有这些感想的是现在有太多人搞个开发板跑跑例程就感觉自己精通啥啥啥了,实际写起程序来到处抄(美其名曰叫移植),遇到性能瓶颈不是怪别人例程不好就是怀疑芯片有BUG,要么就干脆选更高级别的芯片了。
回复

使用道具 举报

0

主题

5

帖子

0

精华

新手入门

积分
17
金钱
17
注册时间
2020-12-7
在线时间
4 小时
发表于 2021-10-10 15:36:45 | 显示全部楼层
hyuxi2005 发表于 2020-12-16 10:30
环形缓冲区 照样ore,我也遇到了同样的问题,不知该如何

环形缓冲区的好处就是中断可以很简练,如果你中断程序照样废话一堆啥缓冲也没用,这个错误的本质就是你还没来得及取出已经在串口寄存器的数据时又有新数据到了,也就是说你本中断的执行时间或结合其它同级(更高)中断的执行时间超过了串口2字节的传输时间。
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则



关闭

原子哥极力推荐上一条 /2 下一条

正点原子公众号

QQ|手机版|OpenEdv-开源电子网 ( 粤ICP备12000418号-1 )

GMT+8, 2025-6-10 10:35

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

快速回复 返回顶部 返回列表