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

news/2024/11/7 21:02:14/

嵌入式开发 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设置

在这里插入图片描述
连接到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中断是用来接收数据, 每次接收个数据,并且在中断中再次开启这个中断
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  pereturn 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标识MAX485_IN();uart2_state_typedef.len = 0;uart2_state_typedef.state = UART_READY;delay_us(10);
}

http://www.ppmy.cn/news/2126.html

相关文章

Verilog入门学习笔记:Verilog基础语法梳理

无论是学IC设计还是FPGA开发,Verilog都是最基本、最重要的必备技能。但任何一门编程语言的掌握都需要长期学习。并不是简简单单的随便读几本书,随便动动脑筋那么简单。Verilog是一门基于硬件的独特语言,由于它最终所实现的数字电路&#xff0…

2023最新SSM计算机毕业设计选题大全(附源码+LW)之java焦作旅游网站q5msq

首先选择计算机题目的时候先看定什么主题,一般的话都选择当年最热门的话题进行组题,就比如说,今年的热门话题有奥运会,全运会,残运会,或者疫情相关的,这些都是热门话题,所以你就可以…

MySQL 数据库的增删查改 (2)

文章目录一. 数据库约束1. 约束类型2.NULL 约束3.UNIQUE 约束4.DEFAULT 约束5. PRIMARY KEY 约束6.FOREIGN KEY 约束二.表的设计三.插入四.查询1.聚合查询2.联合查询3.合并查询本篇文章继承与 MySQL 表的增删改查(1) 一. 数据库约束 1. 约束类型 NOT NULL -- 表示某一行不能…

Python读写文件操作

一、文件编码 1.1 什么是编码? 不变吗就是一种规则集合,记录了内容和二进制相互转换的逻辑,常用的有UTF-5、GBK等编码 1.2 为什么需要编码? 计算机只认识二进制的0和1,所以需要将内容翻译成二进制才能保存在计算机…

免费搜题系统搭建

免费搜题系统搭建 本平台优点: 多题库查题、独立后台、响应速度快、全网平台可查、功能最全! 1.想要给自己的公众号获得查题接口,只需要两步! 2.题库: 题库:题库后台(点击跳转) …

刷爆力扣之1 比特与 2 比特字符

刷爆力扣之1 比特与 2 比特字符 HELLO,各位看官大大好,我是阿呆 🙈🙈🙈 今天阿呆继续记录下力扣刷题过程,收录在专栏算法中 😜😜😜 该专栏按照不同类别标签进行刷题&am…

JAVA毕业设计科普网站计算机源码+lw文档+系统+调试部署+数据库

JAVA毕业设计科普网站计算机源码lw文档系统调试部署数据库 JAVA毕业设计科普网站计算机源码lw文档系统调试部署数据库本源码技术栈: 项目架构:B/S架构 开发语言:Java语言 开发软件:idea eclipse 前端技术:Layui、H…

备忘录模式(Memento)

参考: [备忘录设计模式 (refactoringguru.cn)](https://refactoringguru.cn/design-patterns/mediator) 文章目录一、什么是备忘录模式?二、实现三、优缺点优点缺点四、适用环境一、什么是备忘录模式? 在软件构建过程中,某些对象…