OpenEdv-开源电子网

 找回密码
 立即注册

扫一扫,访问微社区

正点原子新作:阿波罗STM32F767&F429&探索者STM32F4开发板&赶快来下载资料哦。

查看: 164|回复: 8

【求助】多个STM32相连的冲突问题

[复制链接]

  离线 

1

主题

5

帖子

0

精华

新手入门

积分
18
金钱
18
注册时间
2018-3-14
在线时间
3 小时
发表于 2018-3-14 14:38:41 | 显示全部楼层 |阅读模式
1金钱
目前架构:
PC下连了两个STM32模块,用STM32的UART通过RS485模块互连。

实现功能:
只是想实现正常通讯(简单读写寄存器),两个STM32烧录同样的东西(除了ID)。
UART使用DMA收发,IDLE中断。
在正常写寄存器后,应答“AAAA”(字符)

问题描述:
    正常时:此时两片的代码都插入了一些printf,从UART2中打印出调试信息,可以清楚看到:电脑发送1号STM32的写命令,1号识别ID进行写操作,2号ID不匹配,不应答。然后1号回复了“AAAA”。重复多次操作无异常。之后同时去掉了两片中的printf,运行变快,也无异常。
    异常时:只去掉1号的printf,保留2号的printf(1号快,2号慢)。进行写操作,第一遍正常,1号完成了写操作(是从点灯看出来的),2号的调试信息表示ID不匹配,不应答。1号回复“AAAA”。但从第二次开始,1号仍然正常工作,但2号收到的数据就不对了。

以下是2号收到正常与异常的数据:
A857A857001F00295732570B040134300100000049884AC4
57A857411F0029A832570B000134305700000004884AC40100000049

我用示波器看了UART线上的数据,是正常的。而二号中断后收到的很奇怪,多出来一些数据,而且头一个“A8”不见了,中间还有错的。

===========================================现象就是这样↑

我非常怀疑是1号回复的"AAAA"被2号收到后影响的。平时两片同时开或关printf,使得两片速度一样,同时接受数据后触发IDLE中断,开始处理,2号早早处理完了,等1号发“AAAA”时,2号是空闲的,可以正常接受一次,做不应答处理。
但当1号快2号慢时,2号还未处理完第一条命令,1号的“AAAA”就来了,这时我感觉就出了问题,但不知道为啥。

我本意是2号处理时,不再接受其它东西,但显然还是有影响的,下面是代码:

_it.c
[C] 纯文本查看 复制代码
void USART1_IRQHandler(void)
{
  /* USER CODE BEGIN USART1_IRQn 0 */
	uint32_t temp;
	/*        如果是串叿1中断        */
	if(USART1 == huart1.Instance)
	{        /* 如果是串叿1IDLE中断        */
		if(RESET != __HAL_UART_GET_FLAG(&huart1,UART_FLAG_IDLE))
		{
			/*        清除中断标志        */
			__HAL_UART_CLEAR_IDLEFLAG(&huart1);
			/*        停止DMA接收        */
			HAL_UART_DMAStop(&huart1);
			/*        获取DMA当前还有多少未填兿        */
			temp = __HAL_DMA_GET_COUNTER(&hdma_usart1_rx);
			/*        计算串口接收到的数据个数        */
			Rx_len = BUFFERSIZE - temp; 
			recv_end_flag = 1;
		}
	}

  /* USER CODE END USART1_IRQn 0 */
  HAL_UART_IRQHandler(&huart1);
  /* USER CODE BEGIN USART1_IRQn 1 */
  /* USER CODE END USART1_IRQn 1 */
}


main.c

main函数中就是普通的循环:
[C] 纯文本查看 复制代码
__HAL_UART_CLEAR_FLAG(&huart1, UART_CLEAR_IDLEF | UART_CLEAR_NEF);  
  __HAL_UART_ENABLE_IT(&huart1, UART_IT_IDLE);  /*        使能串口1 IDLE中断        */
	HAL_UART_Receive_DMA(&huart1,pR,BUFFERSIZE);
  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
  /* USER CODE END WHILE */

  /* USER CODE BEGIN 3 */
		uartdmaget();
  }
  /* USER CODE END 3 */


uartdmaget这个函数处理所有东西:
[C] 纯文本查看 复制代码
void uartdmaget(void)
{
	if(recv_end_flag ==1)
	{
		memset(LocalBuff,0,sizeof(LocalBuff));
		memcpy(LocalBuff,ReceiveBuff,sizeof(ReceiveBuff));
		Local_len = Rx_len;
		
		if(Local_len>=21)	//只对完整命令译码,否则会出错
		{
			if(decode()==1)
			{
				opcode();
			}
		}	
		
		/*        清空接收缓存匿        */
		for(int i = 0; i < Rx_len ; i++) 
				ReceiveBuff[i]=0;
		
		/*        接收数据长度清零        */
		Rx_len=0;
		recv_end_flag=0;
		
		/*        开启下次接收        */
		HAL_UART_Receive_DMA(&huart1,pR,BUFFERSIZE);
	}
}


我刚接触STM32不久,对DMA和中断的用法不是很熟,不知道为什么上次没处理的数据会影响下次,或者是我没有完全关闭DMA的接收或是没清缓存?请大牛指点我的问题所在,谢谢!

回复

使用道具 举报

  离线 

0

主题

283

帖子

0

精华

高级会员

Rank: 4

积分
666
金钱
666
注册时间
2018-2-7
在线时间
71 小时
发表于 2018-3-14 14:57:40 | 显示全部楼层
要多台机器组网的话要轮询的方式通信,和一号单片机一问一答通信完成之后,再和二号单片机通信。否则总线上高地电平不一致容易乱码。
回复

使用道具 举报

  离线 

1

主题

5

帖子

0

精华

新手入门

积分
18
金钱
18
注册时间
2018-3-14
在线时间
3 小时
 楼主| 发表于 2018-3-14 15:09:26 | 显示全部楼层
HXYDJ 发表于 2018-3-14 14:57
要多台机器组网的话要轮询的方式通信,和一号单片机一问一答通信完成之后,再和二号单片机通信。否则总线上 ...

您好,感谢您的回复

流程上我的确是用轮询的方式进行的,以ID区分,轮询不同的ID以访问每片单片机。但是目前的问题是当访问1号过后,1号的回答被2号听到,好像造成了影响。

我一直有个问题不明白,假如2号单片机在不该接收时接收到信号,并且不去读。那么这个信号会被忽略从而消失,还是会存在2号的接收缓冲区内呢?
回复

使用道具 举报

  离线 

0

主题

283

帖子

0

精华

高级会员

Rank: 4

积分
666
金钱
666
注册时间
2018-2-7
在线时间
71 小时
发表于 2018-3-14 15:59:03 | 显示全部楼层
newton64 发表于 2018-3-14 15:09
您好,感谢您的回复

流程上我的确是用轮询的方式进行的,以ID区分,轮询不同的ID以访问每片单片机。但 ...

那就要用协议来规定,每次串口中有数据进来,先判断是不是发给自己的,如果不是发给自己的则不接收,如果是发给自己的数据再去接收处理。
回复

使用道具 举报

  离线 

1

主题

5

帖子

0

精华

新手入门

积分
18
金钱
18
注册时间
2018-3-14
在线时间
3 小时
 楼主| 发表于 2018-3-14 16:03:27 | 显示全部楼层
正点原子公众号
HXYDJ 发表于 2018-3-14 15:59
那就要用协议来规定,每次串口中有数据进来,先判断是不是发给自己的,如果不是发给自己的则不接收,如果 ...

您好,感谢您的回复

我确实已经用协议判断了,当发指令给1号片时,2号片也会受到无用数据,通过比较ID得知不是自己的,从而丢掉。

但这种比较ID的操作也是在单片机空闲时才会正常运转的,我怀疑在2号处理上一条的过程中,来了垃圾信息,这个垃圾信息没被处理,而是被缓存了。从而与下一条信息合并,影响工作。

有没有这种可能呢?
回复

使用道具 举报

  离线 

0

主题

283

帖子

0

精华

高级会员

Rank: 4

积分
666
金钱
666
注册时间
2018-2-7
在线时间
71 小时
发表于 2018-3-14 16:44:02 | 显示全部楼层
newton64 发表于 2018-3-14 16:03
您好,感谢您的回复

我确实已经用协议判断了,当发指令给1号片时,2号片也会受到无用数据,通过比较ID ...

一般不再接收过程中处理数据,如果是发送给自己的数据,就把数据存下来,然后设置标志位。就退出接收过程,然后在检查标志位去执行相应动作。中断里面执行的代码越少越好,这样就不会漏掉数据。
回复

使用道具 举报

  离线 

1

主题

5

帖子

0

精华

新手入门

积分
18
金钱
18
注册时间
2018-3-14
在线时间
3 小时
 楼主| 发表于 2018-3-14 16:49:55 | 显示全部楼层
HXYDJ 发表于 2018-3-14 16:44
一般不再接收过程中处理数据,如果是发送给自己的数据,就把数据存下来,然后设置标志位。就退出接收过程 ...

您好,

刚其它论坛有人说我“你应该每次发送完就清空从机的接收缓冲区,以免把上次的信息当成本次的信息”,是不是我第二片收到垃圾信息后应该清掉?但那个缓存我不明白,是硬件自带的缓存吗?我并没有写缓存出来,是用专用命令清么?
回复

使用道具 举报

  离线 

0

主题

283

帖子

0

精华

高级会员

Rank: 4

积分
666
金钱
666
注册时间
2018-2-7
在线时间
71 小时
发表于 2018-3-14 16:53:40 | 显示全部楼层
newton64 发表于 2018-3-14 16:49
您好,

刚其它论坛有人说我“你应该每次发送完就清空从机的接收缓冲区,以免把上次的信息当成本次的信 ...

代码没时间看,你可以打断点自己慢慢试。
回复

使用道具 举报

  离线 

1

主题

5

帖子

0

精华

新手入门

积分
18
金钱
18
注册时间
2018-3-14
在线时间
3 小时
 楼主| 发表于 2018-3-14 17:03:05 | 显示全部楼层
HXYDJ 发表于 2018-3-14 16:53
代码没时间看,你可以打断点自己慢慢试。

谢谢,

可是我发现我调试时读到的错误和正常运行的错误不太一样(虽然都不对),是因为调试时运行慢么?(毕竟我这错误产生的原因就是运行的时间差问题)
回复

使用道具 举报

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

本版积分规则




QQ|联系我们|手机版|官方淘宝店|新浪微博|微信公众平台|OpenEdv-开源电子网 ( 粤ICP备12000418号-1 )

GMT+8, 2018-6-20 08:07

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

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