嵌入式开发--RS-485通讯的问题

2023-05-16

嵌入式开发 RS-485通讯的问题

  • RS-485说明
  • 接口芯片
  • 硬件连接
  • CubeMX设置
  • 代码编写
    • 引脚定义
    • 使能串口
    • 中断函数
    • 发送数据
    • 接收数据
  • 有一个问题,多收了一个数
  • 数据线上的波形
  • 问题分析
  • 问题解决

RS-485说明

RS-485一般简称485总线,是最常用的工业总线之一,一般采用2线的半双工模式,用差分方式收发信息。最高速度可达10M BPS。

接口芯片

单片机使用485总线时,是用UART或USART接口,通过RS-485收发器完成信号的输入和输出。常用的芯片有MAX485,MAX3485,SP3485等等。

硬件连接

在这里插入图片描述
硬件很简单,RO和DI连接到单片机的UART接口,是数据的收发引脚,RE和DE连通,接到单片机的GPIO,以控制数据流的方向,是输入还是输出。

CubeMX设置

CubeMX教程见这里:嵌入式开发–CubeMX使用入门教程
在这里插入图片描述
连接到UART2,具体设置如下:
在这里插入图片描述
这些参数需要根据你的设置要求进行,异步模式,波特率,位数,奇偶校验,停止位,其他默认即可。开启中断,以方便接收数据。
在这里插入图片描述
UART对波特率要求并不高,误差5%以内即可,所以晶振可以用片内的RC振荡器,当然更建议用外部石英晶振,频率更准,更重要的是可靠性高。

代码编写

引脚定义

#define MAX485_OUT()      HAL_GPIO_WritePin(CTL_485_PORT,CTL_485_PIN, GPIO_PIN_SET)
#define MAX485_IN()       HAL_GPIO_WritePin(CTL_485_PORT,CTL_485_PIN, GPIO_PIN_RESET)

使能串口

  HAL_UART_Receive_IT(&huart2, uart2_state_typedef.data, 1);	//开启串口,接收到的数据放到uart2_state_typedef.data,每次接收1个字节
  __HAL_UART_ENABLE_IT(&huart2, UART_IT_RXNE);	//启动RXNE中断
  __HAL_UART_ENABLE_IT(&huart2, UART_IT_IDLE);	//启动IDLE中断

RXNE中断是用来接收数据, 每次接收1个字节,并且在中断中再次开启这个中断
IDLE是用来做帧结束判断的,485每帧8个字节,总线空闲后会产生一个IDLE中断,进了这个中断,就表示一帧结束。

中断函数

void USART2_IRQHandler(void)
{
  /* USER CODE BEGIN USART2_IRQn 0 */

  /* USER CODE END USART2_IRQn 0 */
  HAL_UART_IRQHandler(&huart2);
  /* USER CODE BEGIN USART2_IRQn 1 */
  //RS485接口
  //收到1个字节的数据
  if(__HAL_UART_GET_FLAG(&huart2, UART_FLAG_RXNE))
  {
    __HAL_UART_ENABLE_IT(&huart2, UART_IT_RXNE);	//启动RXNE中断
    uart2_state_typedef.data[uart2_state_typedef.len] = huart2.Instance->RDR;
    uart2_state_typedef.len++;
  }
  
  //总线空闲时,会发生一次IDLE中断,此时意味着数据接收完成
  //不同的内核,清除IDLEIE的方式不同,请查阅手册
  if(__HAL_UART_GET_FLAG(&huart2, UART_FLAG_IDLE))
  {
    huart2.Instance->ICR |= USART_ICR_IDLECF;	 //向USART_CR1的IDLECF位写1,以清除IDLEIF标志,否则会一直进IDLEIE中断
  }

发送数据

void modbus_send(void)  //发送数据到串口,数据需要事先在modbus_send_array中准备好
 {
  MAX485_OUT();		//转换为输出模式
  delay_us(100); 	//延时,以等待接口芯片切换完成
  HAL_UART_Transmit(MODBUS_PORT, modbus_send_array,8, 100);   //从串口2发送数组命令
  MAX485_IN();  	//转换为输入模式
  delay_us(10);
}

接收数据

u8 modbus_receive(u16 timeout)        //发送指令后,读取伺服回传的数据,超时单位为ms
{
  u8 ret = 255;
  u8 i = 0;

  while(1)
  { 
    HAL_Delay(1);
    i++;
    
    if(i>timeout)
      break;
    if(uart2_state_typedef.state == UART_RECEIVE_OK)
    {
      uart2_state_typedef.state = 0;
      ret = 0;
      huart2.Instance->ICR |= (USART_ICR_EOBCF|USART_ICR_TCCF|USART_ICR_FECF|USART_ICR_PECF);//eobf   txe  tc  fe  pe
      return ret;
      break;
    }
  }
    return ret;
}

如此便可以发送和接收了。

有一个问题,多收了一个数

于是在串口中断内,数据接收,和IDLE处,分别触发了一个电平信号,以便观察。如下图:

数据线上的波形

第1行的波形是发送引脚
第2行的波形是接收引脚
第3行的波形是方向控制引脚
第4行是接收中断,进一次就有一个脉冲
第5行是IDLE中断,进一次就有一个脉冲。
在这里插入图片描述
下图是放大的,一帧数据的波形
在这里插入图片描述
注意红圈的这个脉冲,数据还没有开始接收,却已经进中断开始接收了一次数据,这也就是额外多出来的一个接收字符。
在这里插入图片描述

问题分析

这个脉冲是发生的位置,是在数据发送完成,并且485的方向切换到接收之后5ms处,显然是在那时,又进了一次RXNE中断,进中断的原因也很简单,在因为下图这个低电平跳变。
在这里插入图片描述
也就是说,当485的数据方向从接收变为发送以后,接收端口会检测到一个低电平,这被认为是串口接收数据的起始位,但是后续没有一个高电平的结束位,所以收到的这个数据肯定是错误的,UART2的ISR寄存器FE位也指出了这一点,如下图
在这里插入图片描述

问题解决

知道了问题,也就知道了如何解决,将发送函数略做修改,发送完成后,清一下ISR寄存器的RXNE标识问题解决

void modbus_send(void)  //发送读寄存器的指令到串口
{
  u32 i=0;
  
  
  HAL_UART_AbortReceive_IT(&huart2);
  __HAL_UART_DISABLE_IT(&huart2, UART_IT_RXNE);	//禁用RXNE中断

  MAX485_OUT();
  delay_us(100);
  HAL_UART_Transmit(MODBUS_PORT, modbus_send_array,8, 100);   //从串口2发送数组命令
  huart2.Instance->RQR |= USART_RQR_RXFRQ;	//清除485方向切换导致的RXNE标识
  huart2.Instance->ICR |= USART_ICR_IDLECF;	//清除空闲标识
  huart2.Instance->ICR |= USART_ICR_TCCF;	//清除发送完成标识

  __HAL_UART_ENABLE_IT(&huart2, UART_IT_RXNE);	//启动RXNE中断
  
  MAX485_IN();
  uart2_state_typedef.len = 0;
  uart2_state_typedef.state = UART_READY;
  delay_us(10);
}

在这里插入图片描述

在这里插入图片描述
进了8次接收中断,接收8个字符,进一次IDLE中断,表示这一帧结束,工作正常。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

嵌入式开发--RS-485通讯的问题 的相关文章

随机推荐

  • SK6812驱动入门

    我看数据手册一般是特性 引脚定义 外围电路 时序图以及驱动代码 特性 Top SMD内部集成高质量外控单线串行级联恒流IC xff1b 控制电 与芯片集成在SMD 3528元器件中 xff0c 构成一个完整的外控像素点 色温效果均匀且一致性
  • ESD与TVS的区别

    概念 ESD全称是Electro Static discharge 意思就是 静电释放 国际上习惯将用于静电防护的器材统称为ESD 中文名称为静电阻抗器 TVS全称是Transient Voltage Suppressor 意思是 瞬间电压
  • 开关电源三种控制模式:PWM/PFM/PSM

    1 PWM PFM PSM 三种控制模式的定义 通常来说 开关电源 xff08 DC DC xff09 有三种最常见的调制方式分别为 xff1a 脉冲宽度调制 xff08 PWM xff09 脉冲频率调制 xff08 PFM xff09 脉
  • PCB布线走直角或锐角问题研究

    首先需要说明的一点 xff0c 在正常布线的过程中还是要尽量避免布线走直角和锐角 这里只是研究深入下布线走直角或锐角会有多大的危害性 xff0c 结尾给出答案 无论是教科书还是公司的技术规范都会强调布线避免出现走直角和锐角 xff0c 不过
  • 磁珠基本原理

    概念 磁珠的全称为铁氧体磁珠滤波器 xff0c 是一种抗干扰元件 xff0c 主要功能是滤除高频噪声 xff0c 消除存在于传输线结构 xff08 电路 xff09 中的噪声 工作原理 磁珠通过阻抗吸收并以发热的形式将不需要频段的能量耗散掉
  • BUCK型DC-DC变换器

    前述 DCDC从控制手段上来说分为PWM式 谐振式以及他们的结合式 每 一种方式中从输入与输出之间是否有变压器隔离又可以分为有隔离 无隔离两类 每一类有六种拓扑结构 BUCK Boost BUCK Boost Cuk Sepic和Zeat
  • dubbo服务超时导致的异常org.apache.dubbo.remoting.TimeoutException

    1 dubbo服务超时异常提示信息如下 xff1a cause org apache dubbo remoting TimeoutException Waiting server side response timeout by scan
  • 基于TCP/IP实现串口到网络的通讯转换

    工作模式 通过串口服务器 xff0c 采集到天平的称量值发送到PC端 操作步骤 1 软件测试 测试工具 xff1a USR M0 V2 2 5 8 基础设置 xff1a 模块静态IP 设置成服务器IP xff0c HTTP服务端口 设置成4
  • 结构体的对其规则以及为什么要对其

    结构体的内存对齐规则以及为什么要对齐 内存对齐规则 span class token number 1 span 第一个成员在与结构体变量偏移量为 span class token number 0 span 的地址处 span class
  • 宏定义参数

    宏定义的参数以逗号 xff08 作为分隔符 span class token macro property span class token directive keyword include span span class token s
  • [STM32]关于环形队列的实现

    在程序中使用环形队列判断接收数据格式 xff0c 避免在中断中处理造成程序响应速度慢的问题 直接贴代码 xff1a LoopRxCommu h ifndef LOOPRXCOMMU H define LOOPRXCOMMU H includ
  • C#旅程——串口发送数据

    串口发送数据时可以一个byte一个byte的发送数据 xff0c 也可以一次性丢出 xff0c 分多次丢出的话会导致一段数据被分成多段发出 xff0c 中间的延时可能会超过2ms xff0c 与FW通讯时会出现异常 span class t
  • 【记录】一次51单片机串口乱码问题排查

    记录 一次51单片机串口乱码问题排查 项目场景问题描述原因分析解决方案结语 项目场景 在51串口收发仿真实验中使用两个单片机互相通信 xff0c 程序设定A上电1s后通过串口以16进制给B发送AA 直到B收到AA后回复BB xff0c 当A
  • IO流java基础

    二十四 IO流 24 1 File 1 1 File 类概述和构造方法 File 它是文件和目录路径名的抽象表示 文件和目录是可以通过File封装成对象的 对于File而言 其封装的并不是一个真正存在的文件 仅仅是一个路径名而已 它可以是存
  • TX2上布置vins_fusion_gpu指南

    1 参考链接 如果初次安装 xff0c 新的TX2环境 xff0c 请参考文档 https github com arjunskumar vins fusion gpu tx2 nano 2 问题记录 1 xff0c 自己的环境情况 我的环
  • Ubuntu下安装cmake

    Ubuntu下安装cmake 今天因为项目的原因需要将cmake升级一下 xff0c 原来我是按照链接没有卸载旧版本 xff0c 直接升级 但是出现一些问题 xff0c 然后我全部卸载后 xff0c 重新安装 以下就是我的安装步骤 第一步
  • AUTH:basic认证和digest认证

    Http authentication BASIC In the context of an HTTP transaction basic access authentication is a method for a web browse
  • Quick Audience组织和工作空间功能解读

    简介 xff1a Quick Audience完成了权限系统全面升级 xff0c 可以解决集团企业不同品牌 不同运营组织 xff0c 不同消费者运营的诉求 xff0c 精细化保障企业数据访问安全 xff0c 提升管控的灵活度 更多关于数智化
  • Socket编程基础总结,全网最全

    IP地址 xff1a 可以在网络环境中 xff0c 唯一标识一台主机 端口号 xff1a 可以定位网络的一台主机上 xff0c 唯一标识一个进程 ip地址 43 端口号 xff1a 可以在网络环境中 xff0c 唯一标识一个进程 在TCP
  • 嵌入式开发--RS-485通讯的问题

    嵌入式开发 RS 485通讯的问题 RS 485说明接口芯片硬件连接CubeMX设置代码编写引脚定义使能串口中断函数发送数据接收数据 有一个问题 xff0c 多收了一个数数据线上的波形问题分析问题解决 RS 485说明 RS 485一般简称