搜索
bottom↓
回复: 37

stm32的串口5接485,115200波特率导致死机,9600却没事,求助!!

[复制链接]

出0入0汤圆

发表于 2012-11-22 09:32:25 | 显示全部楼层 |阅读模式
本帖最后由 guxingganyue 于 2012-11-22 09:34 编辑

如题,我用stm32f103VET6的串口5和485通信,串口每次向485发送150字节,上位机每个1秒发一条命令,串口收到后就向485发送150字节

目前的现象是115200波特率的话,单片机会死机(lcd屏幕不刷新了),但是定时器中断还能触发(led灯在闪烁),26秒后内部狗复位,一切恢复正常

上位机继续发命令,不到3分钟的时间单片机死了

但是我用9600的波特率通信,1秒发一次命令,测试了1个晚上机器也没有死机

1、单片机和上位机间的连线不是很长,就2米左右,485芯片为:max3485,贵的那种
2、stm32外接8M晶振,系统跑72M

下面是485的连接图:请高手指教

注:把那个120欧姆的电阻去掉与否现象一样



本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?注册

x

出10入61汤圆

发表于 2012-11-22 09:36:42 | 显示全部楼层
检查下程序里有没死循环等待的语句,如果有加入超时跳出以确认是硬件问题还是软件问题
波特率高了误码率可能高了,程序如果有问题就会出现这种现象

出0入0汤圆

 楼主| 发表于 2012-11-22 09:38:45 | 显示全部楼层
tcm123 发表于 2012-11-22 09:36
检查下程序里有没死循环等待的语句,如果有加入超时跳出以确认是硬件问题还是软件问题
波特率高了误码率可 ...

串口接收程序应该没有问题
9600的波特率没死机就可以证明

我怀疑是硬件上可能处理的不好

出0入0汤圆

发表于 2012-11-22 09:48:47 | 显示全部楼层
中断里做的事情太多了吧?

出0入0汤圆

发表于 2012-11-22 09:51:36 | 显示全部楼层
guxingganyue 发表于 2012-11-22 09:38
串口接收程序应该没有问题
9600的波特率没死机就可以证明

9600的波特率没死机只能证明低速时软件能正常运行,并不能保证115200也能正常使用,还是先查软件比较好,像2楼说的

出0入0汤圆

发表于 2012-11-22 09:56:26 | 显示全部楼层
你应该在串口中断里判断是否为正常接收,如果不是那你要清噪声标志位或错误位,具体是那位你试试,这种现象我在STM8上就遇到过

出0入0汤圆

发表于 2012-11-22 09:57:59 | 显示全部楼层
问题描述不清楚啊,上位机是电脑?还是别的单片机?LCD和LED都是在下位机上?LCD是靠什么刷新的?是接收到数据后刷新?
建议你先不加LCD,就测试下串口看有没问题

出0入0汤圆

 楼主| 发表于 2012-11-22 10:03:26 | 显示全部楼层
zzfei90 发表于 2012-11-22 09:57
问题描述不清楚啊,上位机是电脑?还是别的单片机?LCD和LED都是在下位机上?LCD是靠什么刷新的?是接收到 ...


上位机是电脑,led和lcd在下位机,led每500ms闪烁一次
lcd上显示的是时间,温湿度,每3秒刷新一次

lcd刷新于显示和是否接收到电脑发的命令没有关系

出0入0汤圆

 楼主| 发表于 2012-11-22 10:13:17 | 显示全部楼层
本帖最后由 guxingganyue 于 2012-11-22 12:00 编辑

电脑发送:X2000S1234567Y,其中X Y是协议的头,尾。2000S是固定不变的,1234567是一个机器的7位ID号
串口接收完毕,且判断是本机的ID后把变量Transfer_485_Date_flag置位,while(1)中发现标志置位后就清除标志位,且向电脑发送150字节的数据

我的系统中有4个中断:定时器1中断(25ms中断一次),外部中断,串口4接收中断,串口5接收中断。

其中,外部中断和串口4接收中断几乎是不发生的,只有在特定的时间才发生,如00时00分,其他的情况下这个两个中断不会被触发
只有定时中断是一直开着的,串口5接收中断只有电脑发命令时才触发



下面是串口中断接收函数:
  1. void UART5_IRQHandler(void)
  2. {
  3.   u8 res=0;
  4.   static u8 RX_Count=0;
  5.   static u8 UART_RX_BUF[14]={0};   //接收缓冲,如收到:X2000S1234567Y
  6.   
  7.   if(UART5->SR & (1<<5))               //接收到数据
  8.   {
  9.     res=UART5->DR;
  10.     if(res=='X')       //数据头,2012-11-16
  11.     {
  12.       RX_Count=0;
  13.       UART_RX_BUF[RX_Count]=res;//收数据头,2012-11-18
  14.       RX_Count++;
  15.     }
  16.     else if(res =='Y')//数据尾,2012-11-18
  17.     {
  18.       UART_RX_BUF[RX_Count]=res;//收数据尾,2012-11-18
  19.       RX_Count++;
  20.       if((UART_RX_BUF[0]=='X')&&(RX_Count==14))//判数据头和数据长度
  21.       {
  22.         if((UART_RX_BUF[1]=='2')&&(UART_RX_BUF[2]=='0')&&(UART_RX_BUF[3]=='0')
  23.          &&(UART_RX_BUF[4]=='0')&&(UART_RX_BUF[5]=='S')
  24.          &&(UART_RX_BUF[6]==Menu_B2_ID_Code[0])&&(UART_RX_BUF[7]==Menu_B2_ID_Code[1])
  25.          &&(UART_RX_BUF[8]==Menu_B2_ID_Code[2])&&(UART_RX_BUF[9]==Menu_B2_ID_Code[3])
  26.          &&(UART_RX_BUF[10]==Menu_B2_ID_Code[4])&&(UART_RX_BUF[11]==Menu_B2_ID_Code[5])
  27.          &&(UART_RX_BUF[12]==Menu_B2_ID_Code[6]))
  28.         {
  29.           Transfer_485_Date_flag=1;
  30.         }
  31.       }
  32.     }
  33.     else if(RX_Count<14)
  34.     {
  35.       UART_RX_BUF[RX_Count]=res;
  36.       RX_Count++;
  37.     }
  38.   }
  39. }
复制代码

出0入0汤圆

发表于 2012-11-22 10:13:38 | 显示全部楼层
1.硬件没有问题,STM32串口115200波特率长时间工作的飘过,另,从原理上看,485电路也没有问题.
2.可能串口接收中断里做的事情太多.9600时,有足够的时间处理,115200时,可能处理不过来.建议接收中断里面,只将接收到的数据放到缓冲区,不做其他处理,
3.屏不显示,但定时器还在工作,说明单片没有死机,可能程序卡在某处,或者一直在中断里面出不来.请检查程序的容错能力.
4.485在收发切换时,最好有一小段延时,因为当接收完成后需要发送数据时,如果立刻切换到发送状态并发送,可能导致第一个字节对方收不到.
5.问题描述不够详细,最好贴上代码,大家帮你分析.

出0入0汤圆

发表于 2012-11-22 10:16:13 | 显示全部楼层
把你程序贴出来看看吧,主循环和中断都弄出来看看,帮你找找问题

出0入0汤圆

 楼主| 发表于 2012-11-22 10:19:30 | 显示全部楼层
dadatou 发表于 2012-11-22 10:13
1.硬件没有问题,STM32串口115200波特率长时间工作的飘过,另,从原理上看,485电路也没有问题.
2.可能串口接收 ...

嗯,485接收中断中的语句并不多,但定时器中断中的语句还是比较多的

下面是485串口发送函数:
  1. void UART5_SendString_A(char *Data)
  2. {
  3.   Enable_Tx;
  4.   delay_nms(1);//485延时,测试发现这个延时有没有效果一样,2012-11-18
  5.   char *pBuf = Data;   
  6.   while (*pBuf)
  7.   {
  8.     while (!(UART5->SR & 0x0040));
  9.     UART5->DR = ((*pBuf++) & (uint16_t)0x01FF);
  10.   }
  11.   delay_nms(1);//485延时,不延时的话最后一个字节是发不出去的,2012-11-18
  12.   Enable_Rx;
  13. }
复制代码

出0入0汤圆

 楼主| 发表于 2012-11-22 10:20:36 | 显示全部楼层
zzfei90 发表于 2012-11-22 10:16
把你程序贴出来看看吧,主循环和中断都弄出来看看,帮你找找问题

主程序和定时器程序太多,估计贴出来会让大家看的更乱

出0入0汤圆

发表于 2012-11-22 10:26:09 | 显示全部楼层
接收中断里确实不多,定时器中断和接收中断的优先级哪个高啊

出0入0汤圆

发表于 2012-11-22 10:28:29 | 显示全部楼层
定时器中断里面你干什么了?我感觉你定时器中断优先级设的太高了,一般通信才是比较重要的,因为串口是异步通信,如果被其他中断打断的话,可能会造成接收数据错误
你上位机每次下发的数据都一样没有改变吗?

出0入0汤圆

 楼主| 发表于 2012-11-22 10:35:41 | 显示全部楼层
dadatou 发表于 2012-11-22 10:26
接收中断里确实不多,定时器中断和接收中断的优先级哪个高啊

定时器中断的优先级最高,485串口接收中断的最低

出0入0汤圆

 楼主| 发表于 2012-11-22 10:36:40 | 显示全部楼层
zzfei90 发表于 2012-11-22 10:28
定时器中断里面你干什么了?我感觉你定时器中断优先级设的太高了,一般通信才是比较重要的,因为串口是异步 ...

不一样,我发4个数据,就是有4个机器并联

出0入0汤圆

发表于 2012-11-22 10:43:14 | 显示全部楼层
本帖最后由 dadatou 于 2012-11-22 10:48 编辑
guxingganyue 发表于 2012-11-22 10:35
定时器中断的优先级最高,485串口接收中断的最低


问题就在这里的可能性相当大.你的定时器的优先级比串口还高,当串口的波特率比较高的时候,你如何保证可靠接收呢? 115200的波特别率,字之前的间隔只有几十微秒,STM32的串口是没有FIFO的.在接收过程中,被定时器中断超过这个时间,接收就会出错.串口中断的优先权要最高,并且要可以剥夺其他中断。

出0入0汤圆

发表于 2012-11-22 11:04:44 | 显示全部楼层
我用CM0,定时中断优先级设1,串口中断和滴答中断优先级0,串口设200k速率,没有收发异常!

出0入0汤圆

发表于 2012-11-22 11:07:38 | 显示全部楼层
我感觉你再开个定时器,每次开始接收数据的时候打开定时器开始计数,如果超时还没有接收完的话就把这包数据丢弃了,要不然,可能会使接收到的数据乱

出0入0汤圆

 楼主| 发表于 2012-11-22 12:02:05 | 显示全部楼层
本帖最后由 guxingganyue 于 2012-11-22 12:03 编辑
guxingganyue 发表于 2012-11-22 10:13
电脑发送:X2000S1234567Y,其中X Y是协议的头,尾。2000S是固定不变的,1234567是一个机器的7位ID号
串口 ...


9楼的中断优先级描述的不清楚,下面是清楚的
  1. void NVIC_Configuration(void)
  2. {
  3.     NVIC_InitTypeDef NVIC_InitStructure;
  4.     NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);

  5.     // Enable the Timer1 Interrupt
  6.     NVIC_InitStructure.NVIC_IRQChannel = TIM1_UP_IRQn;         //向量地址设置,定时器1更新中断
  7.     NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;  //设定Timer1的抢占式优先级
  8.     NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;         //设定Timer1的响应优先级
  9.     NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;            //使能
  10.     NVIC_Init(&NVIC_InitStructure);                            //初始化

  11.     //使能串口5接收中断
  12.     NVIC_InitStructure.NVIC_IRQChannel =UART5_IRQn;            //向量地址设置,外部中断
  13.     NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;  //设定外部中断的抢占式优先级
  14.     NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;         //设定外部中断的响应优先级
  15.     NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;            //使能
  16.     NVIC_Init(&NVIC_InitStructure);

  17.     // Enable the PA8 exit Interrupt
  18.     NVIC_InitStructure.NVIC_IRQChannel = EXTI9_5_IRQn;         //向量地址设置,外部中断
  19.     NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;  //设定外部中断的抢占式优先级
  20.     NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2;         //设定外部中断的响应优先级
  21.     NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;            //使能
  22.     NVIC_Init(&NVIC_InitStructure);
  23.    
  24.     //使能串口4接收中断
  25.     NVIC_InitStructure.NVIC_IRQChannel =USART4_IRQn;           //向量地址设置,外部中断
  26.     NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;  //设定外部中断的抢占式优先级
  27.     NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;         //设定外部中断的响应优先级
  28.     NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;            //使能
  29.     NVIC_Init(&NVIC_InitStructure);
  30. }
复制代码

出0入0汤圆

 楼主| 发表于 2012-11-22 12:17:53 | 显示全部楼层
dadatou 发表于 2012-11-22 10:43
问题就在这里的可能性相当大.你的定时器的优先级比串口还高,当串口的波特率比较高的时候,你如何保证可靠 ...

好的,我试试

出0入0汤圆

发表于 2012-11-22 12:32:09 | 显示全部楼层
guxingganyue 发表于 2012-11-22 12:17
好的,我试试

把串口的抢占优先级设成最高.要可以抢占其他中断.

出0入0汤圆

发表于 2012-11-23 10:02:47 | 显示全部楼层
guxingganyue 发表于 2012-11-22 12:17
好的,我试试

怎么样啊?楼主,问题解决了要上来跟大家分享一下啊.

出0入0汤圆

发表于 2012-11-23 10:59:31 | 显示全部楼层
9600能运行说明不是硬件问题了,楼主的程序肯定有问题,需要多加磨练。

出0入0汤圆

发表于 2012-11-23 11:12:17 | 显示全部楼层
典型性问题
串口优先级低于定时中断,造成115200波特率时候,2个数据塞死串口,这是stm32的bug。

办法有很多,1.串口优先级最高 2.用dma接收,你管他数据是啥。收回来了再分析,看你的串口接收部分,蛋疼。

出0入0汤圆

发表于 2012-11-23 11:35:30 | 显示全部楼层
楼主电路设计不合理哦,接多个设备每个设备都有4.7K的上下拉电阻吗?是否考虑过最远端设备是否能得到足够的电压呢?

出0入0汤圆

 楼主| 发表于 2012-11-23 12:08:39 | 显示全部楼层
heky 发表于 2012-11-23 11:12
典型性问题
串口优先级低于定时中断,造成115200波特率时候,2个数据塞死串口,这是stm32的bug。


收数据的程序怎么写才好呢?

请指点

出0入0汤圆

 楼主| 发表于 2012-11-23 12:11:07 | 显示全部楼层
xjjiang 发表于 2012-11-23 11:35
楼主电路设计不合理哦,接多个设备每个设备都有4.7K的上下拉电阻吗?是否考虑过最远端设备是否能得到足够的 ...

嗯,最多接32个设备,,每个上面都有上、下拉电阻,但120欧姆不是每个都有

出0入0汤圆

发表于 2012-11-23 12:26:19 | 显示全部楼层
看到你的发送函数,还有接收函数来的,里的工作那么多,这样怎么会不慢的,要是上一个数据还没有发完的话,你又来数据怎么会不死机的来的,还有一个问题,要是数据在固定的,怎么不用DMA来操作!方便好使,处理器有更多的时间去搞其它的事,不用一直在那里等起1

出0入0汤圆

发表于 2012-11-23 19:24:58 | 显示全部楼层
guxingganyue 发表于 2012-11-23 12:11
嗯,最多接32个设备,,每个上面都有上、下拉电阻,但120欧姆不是每个都有 ...

120ohm电阻,首尾各一个,楼主可能要多看485方面的资料,120ohm电阻用途是什么?485芯片AB线电压范围,接合实际,最多设备(电阻并联)电压是否能达到485芯片的输出,原理上搞明白了,其它就没什么了

出0入0汤圆

 楼主| 发表于 2012-11-24 14:47:52 | 显示全部楼层
xjjiang 发表于 2012-11-23 19:24
120ohm电阻,首尾各一个,楼主可能要多看485方面的资料,120ohm电阻用途是什么?485芯片AB线电压范围,接 ...



多谢,正在仔细看中······

出0入0汤圆

 楼主| 发表于 2012-11-24 14:50:42 | 显示全部楼层


汇报情况:经过楼上几位的热心建议,我把485的优先级提高到最高后现在机器不死机了

但还存在问题:就是电脑有时给机器发数机器不回我,,,,然后永远就不回了,复位后就恢复正常

出0入0汤圆

发表于 2012-12-26 12:57:06 | 显示全部楼层
楼主问题解决了吗?

出0入0汤圆

发表于 2015-8-14 14:58:21 | 显示全部楼层
楼主问题解决了吗?我最近也遇到差不多的问题。

出0入0汤圆

发表于 2016-12-9 12:41:16 | 显示全部楼层
其实,使能后 要延时几十us ~几百us  时间再发送,  RS485转换发送和接收需要一定时间, 9600 肯定够啦, 115200 就影响了! 不延时误码率很高。。。     楼主可能是误码造成的程序死机,   但程序如果写的足够强壮,也不会死机的

出0入0汤圆

发表于 2017-5-31 15:49:07 | 显示全部楼层
一般用9600的多,比如电力行业

出0入0汤圆

发表于 2017-5-31 16:48:59 | 显示全部楼层
程序逻辑问题。
请检查Transfer_485_Date_flag的操作原子性。
回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

手机版|Archiver|amobbs.com 阿莫电子技术论坛 ( 粤ICP备2022115958号, 版权所有:东莞阿莫电子贸易商行 创办于2004年 (公安交互式论坛备案:44190002001997 ) )

GMT+8, 2024-5-1 04:54

© Since 2004 www.amobbs.com, 原www.ourdev.cn, 原www.ouravr.com

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