STM32CUBUMX配置RS485(中断接收)--保姆级教程

news2025/1/10 17:36:09

————————————————————————————————————
⏩ 大家好哇!我是小光,嵌入式爱好者,一个想要成为系统架构师的大三学生。
⏩最近在开发一个STM32H723ZGT6的板子,使用STM32CUBEMX做了很多驱动,包括ADC、UART、RS485、EEPROM(IIC)、FLASH(SPI)等等。
⏩本篇文章对STM32CUBEMX配置RS485做一个详细的使用教程。
⏩感谢你的阅读,不对的地方欢迎指正。
————————————————————————————————————

一.RS485工作原理

简介

RS-485是美国电子工业协会(EIA)在1983年批准了一个新的平衡传输标准(balanced transmission standard),EIA一开始将RS(Recommended Standard)做为标准的前缀,不过后来为了便于识别标准的来源,已将RS改为EIA/TIA。目前标准名称为TIA-485,但工程师及应用指南仍继续使用RS-485来称呼此标准。

RS-485仅是一个电气标准,描述了接口的物理层,像协议、时序、串行或并行数据以及链路全部由设计者或更高层协议定义。 RS-485定义的是使用平衡(也称作差分)多点传输线的驱动器(driver)和接收器(receiver)的电气特性。

关键特性

差分传输增加噪声抗扰度,减少噪声辐射
长距离链路,最长可达4000英尺(约1219米)
数据速率高达10Mbps(40英寸内,约12.2米)
同一总线可以连接多个驱动器和接收器
宽共模范围允许驱动器和接收器之间存在地电位差异,允许最大共模电压-7-12V

信号电平

RS-485能够进行远距离传输主要得益于使用差分信号进行传输,当有噪声干扰时仍可以使用线路上两者差值进行判断,使传输数据不受噪声干扰。
在这里插入图片描述
RS-485差分线路包括以下2个信号:

  • A:非反向(non-inverting)
  • 信号 B:反向(inverting)信号

也可能会有第3个信号,为了平衡线路正常动作要求所有平衡线路上有一个共同参考点,称为SC或者G。该信号可以限制接收端收到的共模信号,收发器会以此信号作为基准值来测量AB线路上的电压。RS-485标准中提到:

  • 若是MARK(逻辑1),线路B信号电压比线路A高
  • 若是SPACE(逻辑0),线路A信号电压比线路B高

注:不同的IC使用的信号标示方式不同,不过EIA的标准中只使用A和B的名称。数据为1时,信号B会比信号A要高。不过因为标准其中也提到信号A是“非反向信号”,信号B是“反向信号”。因此信号A、B的定义就更容易混淆了,许多组件制造商(错误的)依循了这个A/B的命名原则,所以具体定义需要实际参考设计厂家芯片手册。
为了不引起分歧,一种常用的命名方式是:

  • TX+ / RX+ 或D+来代替B(信号1时为高电平)
  • TX- / RX- 或D-来代替A(信号0时为低电平)

下图列出在RS-485利用“异步开始-停止”方式发送一个字符(0xD3,最低比特先发送)时,U+端子及 U−端子上的电压变化。
在这里插入图片描述
更多原理讲解可以看看参考

实验环境

软件环境

STM32CUBEMX -6.9.0
KEIL 5.38

硬件环境

串口转485电路
在这里插入图片描述
串口/RS485转USB转换器(方便调试)与串口转485接线:

  • A - A
  • B - B
  • VCC - 5V
  • GND - GND

STM32H723ZGT6开发板与串口转485接线:

  • PB6 - RXD
  • PB7 - TXD
  • PB5 - 485T/R

MX配置

板子、时钟、调试之类的配置就不说了,具体可以看看这篇:
STM32CUBEMX配置ADC(多通道轮询)(STM32H7)–保姆级教程
这里只说一下RS485的具体配置
在这里插入图片描述
1.配置USART1作为我们连接RS485的接口
在这里插入图片描述
2.配置PB5为我们RS485收发的控制引脚
在这里插入图片描述
3.打开串口中断,并配置优先级

驱动编写

usart.h
加入接收缓冲区

/* USER CODE BEGIN Private defines */
#define USART1_RXBUFFERSIZE 1 //每次接收1个数据进入一次中断
#define USART1_REC_LEN 200  	 //定义最大接收字节数 200

#define RS485DIR_TX HAL_GPIO_WritePin(GPIOB,GPIO_PIN_5,GPIO_PIN_SET);//定义我们的控制引脚为发送状态
#define RS485DIR_RX HAL_GPIO_WritePin(GPIOB,GPIO_PIN_5,GPIO_PIN_RESET);//定义我们的控制引脚为接收状态
/* USER CODE END Private defines */

usart.c

/* USER CODE BEGIN 0 */
#include <stdio.h>
#include <stdarg.h>
extern unsigned char USART1_aRxBuffer[USART1_RXBUFFERSIZE];//HAL库使用的串口接收缓冲
extern unsigned char USART1_RX_BUF[USART1_REC_LEN];     //接收缓冲,最大USART_REC_LEN个字节.
/* USER CODE END 0 */

在这里插入图片描述
在初始化中加入:

HAL_UART_Receive_IT(&huart1, (unsigned char *)USART1_aRxBuffer, USART1_RXBUFFERSIZE);//此处为添加的

这是为了将接收到的数据放到我们的数组中,USART1_aRxBuffer:存入的数组, USART1_RXBUFFERSIZE:一次存入的大小

stm32h7xx_it.c
编写中断和回调函数:

unsigned short USART1_RX_STA = 0;       //接收状态标记	
unsigned char USART1_aRxBuffer[USART1_RXBUFFERSIZE];//HAL库使用的串口接收缓冲
unsigned char USART1_RX_BUF[USART1_REC_LEN];     //接收缓冲,最大USART_REC_LEN个字节.

void USART1_IRQHandler(void)
{
  /* USER CODE BEGIN USART1_IRQn 0 */
	unsigned int timeout=0;
  unsigned int maxDelay=0x1FFFF;
  /* USER CODE END USART1_IRQn 0 */
  HAL_UART_IRQHandler(&huart1);
  /* USER CODE BEGIN USART1_IRQn 1 */
	timeout=0;
  while (HAL_UART_GetState(&huart1)!=HAL_UART_STATE_READY)//等待就绪
  {
		timeout++;//超时处理
		if(timeout>maxDelay) break;		
  }
  timeout=0;
  while(HAL_UART_Receive_IT(&huart1,(unsigned char *)USART1_aRxBuffer, USART1_RXBUFFERSIZE)!=HAL_OK)//一次处理完成之后,重新开启中断并设置RxXferCount为1
  {
    timeout++; //超时处理
		if(timeout>maxDelay) break;	
  }
  /* USER CODE END USART1_IRQn 1 */
}

void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
	if(huart->Instance==USART1)//如果是串口1
	{
		if((USART1_RX_STA&0x8000)==0)//接收未完成
		{
			if(USART1_RX_STA&0x4000)//接收到了0x0d
			{
				if(USART1_aRxBuffer[0]!=0x0a)USART1_RX_STA=0;//接收错误,重新开始
				else USART1_RX_STA|=0x8000;	//接收完成了 
			}
			else //还没收到0X0D
			{	
				if(USART1_aRxBuffer[0]==0x0d)USART1_RX_STA|=0x4000;
				else
				{
					USART1_RX_BUF[USART1_RX_STA&0X3FFF]=USART1_aRxBuffer[0] ;
					USART1_RX_STA++;
					if(USART1_RX_STA>(USART1_REC_LEN-1))USART1_RX_STA=0;//接收数据错误,重新开始接收	  
				}		 
			}
		}
	}
}

main.c
编写测试代码:

//RS485串口
extern unsigned short USART1_RX_STA;       //接收状态标记	
extern unsigned char USART1_RX_BUF[USART1_REC_LEN];//接收字符串缓冲区
extern unsigned char USART1_aRxBuffer[USART1_RXBUFFERSIZE];//HAL库使用的串口接收缓冲
while(1)
{
		if(USART1_RX_STA&0x8000)
		{					   
			len=USART1_RX_STA&0x3fff;//得到此次接收到的数据长度
			RS485DIR_TX;//拉高PB5,更改RS485模式为发送
			HAL_UART_Transmit(&huart1,(uint8_t*)message,sizeof(message),1000);	//发送提示信息
			while(__HAL_UART_GET_FLAG(&huart1,UART_FLAG_TC)!=SET);		//等待发送结束
			HAL_UART_Transmit(&huart1,(uint8_t*)USART1_RX_BUF,len,1000);	//发送接收到的数据
			while(__HAL_UART_GET_FLAG(&huart1,UART_FLAG_TC)!=SET);		//等待发送结束
			RS485DIR_RX;//拉低PB5,更改RS485模式为接收
			USART1_RX_STA=0;
			if(USART1_RX_BUF[0] == '1') 
				HAL_GPIO_TogglePin(GPIOA,GPIO_PIN_10);
		}
}

调试结果

在这里插入图片描述
这里就简单实现了一个发什么收什么,然后再把收到的数据发回来的实验,代码的编写和普通的串口没有什么区别,只是多了一个串口转485的模块,一般的USB转串口是用不了的,得用USB转串口/485才行。

参考

RS485-详解

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/786218.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

python selenium爬虫自动登录实例

拷贝地址&#xff1a;python selenium爬虫自动登录实例_python selenium登录_Ustiniano的博客-CSDN博客 一、概述 我们要先安装selenium这个库&#xff0c;使用pip install selenium 命令安装&#xff0c;selenium这个库相当于机器模仿人的行为去点击浏览器上的元素&#xff0…

24 ==比较的是地址在.equals比较的是内容

public class Demo1 {public static void main(String[] args) {byte[] arr {97,98,99};String s1 new String(arr);String s2 new String(arr);System.out.println(s1s2);System.out.println(s1.equals(s2));} }

pgvector 源码分析

简介 pgvector 库是一种用于计算向量距离的库&#xff0c;它的核心是提供了聚类索引&#xff0c;棸类索引使用的算法是 kmeans&#xff08;相对于 kmeans 最主要的区别是初始化起点的位置&#xff09;。 pgvector 索引的存储结构 meta page → list page → entry page inse…

vue2和vue3关于class类的绑定以及style的绑定的区别

本篇为个人笔记 1.对于class类的绑定的区别 vue2:对于vue2而言&#xff0c;所有类的绑定都是基于对象{}来进行的 例如&#xff1a;单个类绑定 <div :class"{active:isActive}"></div> 多个类绑定&#xff1a; <div :class"{active,hasError…

CNN(卷积神经网络)的实现过程详解

概要 在图像处理领域&#xff0c;CNN(卷积神经网络)处于绝对统治地位&#xff0c;但对于CNN具体是如何用神经网络实现的&#xff0c;能找到的介绍要么是一大堆数学公式&#xff0c;要么是大段晦涩的文字说明&#xff0c;读起来很是辛苦&#xff0c;想写好一片完整的而且有深度的…

【java安全】RMI

文章目录 【java安全】RMI前言RMI的组成RMI实现Server0x01 编写一个远程接口0x02 实现该远程接口0x03 Registry注册远程对象 Client 小疑问RMI攻击 【java安全】RMI 前言 RMI全称为&#xff1a;Remote Method Invocation 远程方法调用&#xff0c;是java独立的一种机制。 RM…

软件检测报告CMA/CNAS标识加盖和不加盖的区别在哪?

在生活中&#xff0c;我们经常会听到CMA(中国计量认证)和CNAS(中国合格评定国家认可委员会)这两个标识&#xff0c;尤其在软件检测领域更是如此。那么&#xff0c;软件检测报告CMA/CNAS标识加盖和不加盖有哪些区别呢CMA和CNAS认可的软件测评机构又有什么样的好处呢?本文将为您…

各电商平台api接口开发系列(数据分享)接口封装高并发

淘宝API接口就是第三方公司&#xff0c;通过淘宝开放平台接入淘宝数据&#xff0c;并进行再开发&#xff0c;将功能封装打包成函数&#xff0c;客户只需要传入参数&#xff0c;接收返回值就可以实现具体功能&#xff0c;其他1688&#xff0c;京东&#xff0c;拼多多以及海外跨境…

[Android 13]Input系列--触摸事件在应用进程的分发和处理

hongxi.zhu 2023-7-21 Android 13 前面我们已经梳理了input事件在native层的传递&#xff0c;这一篇我们接着探索input事件在应用中的传递与处理&#xff0c;我们将按键事件和触摸事件分开梳理&#xff0c;这一篇就只涉及触摸事件。 一、事件的接收 从前面的篇幅我们知道&…

STM32CubeMX v6.9.0 BUG:FLASH_LATENCY设置错误导致初始化失败

背景 今天在调试外设功能时&#xff0c;发现设置了使用外部时钟之后程序运行异常&#xff0c;进行追踪调试并与先前可以正常运行的项目进行对比之后发现这个问题可能是由于新版本的STM32CubeMX配置生成代码时的BUG引起的。 测试环境 MCU: STM32H750VBT6 STM32CubeIDE: Versi…

Android 屏幕适配各种宽高比的手机

由于android 手机的屏幕宽高比样式太多了&#xff0c;在设计UI时&#xff0c;很多时候&#xff0c;会因为宽高比&#xff0c;分辨率不同会有展示上的差异。 我是这样解决的 在activity的onCreate方法前&#xff0c;调用&#xff1a; fun screenFit(context: Context) {val me…

Gitee 上传项目到仓库(上传文件夹)

一、将仓库下载到本地 1.首先打开仓库&#xff0c;点击下载压缩包 2.将下载的压缩包解压&#xff0c;并打开&#xff0c;在当前目录下打开 二、git操作 1.在文件当前目录打开git bash 2.初始化git git init 该命令会生成一个隐藏的.git文件夹 如果不是第一次使用&#…

自然语言处理14-基于文本向量和欧氏距离相似度的文本匹配,用于找到与查询语句最相似的文本

大家好&#xff0c;我是微学AI&#xff0c;今天给大家介绍一下自然语言处理14-基于文本向量和欧氏距离相似度的文本匹配&#xff0c;用于找到与查询语句最相似的文本。NLP中的文本匹配是指通过计算文本之间的相似度来找到与查询语句最相似的文本。其中一种常用的方法是基于文本…

MybatisPlus使用排序查询时,将null值放到最后

1用户需求 查询结果&#xff0c;按照某些字段进行排序&#xff0c;将为null的值放到最后。按照更新时间排序&#xff0c;但是更新时间可能为null&#xff0c;因此将null的数据放到最后。 2解决方案 最简单的方式&#xff0c;当然是下面这种直接在SQL最后面 NULLS LAST &…

FAPI,2471983-20-5,放射性示踪剂成纤维细胞激活蛋白抑制剂显像剂

资料编辑|陕西新研博美生物科技有限公司小编MISSwu​ 一、产品描述&#xff1a; 成纤维细胞激活蛋白抑制剂显像剂FAPI&#xff08;CAS号&#xff1a;2471983-20-5&#xff09;&#xff0c;FAPI是一种放射性示踪剂&#xff0c;全称为成纤维细胞活化蛋白抑制剂。为小分子酶活性抑…

elasticsearch操作(API方式)

说明&#xff1a;es操作索引库、文档&#xff0c;除了使用它们自带的命令外&#xff08;参考&#xff1a;http://t.csdn.cn/4zpmi&#xff09;&#xff0c;在IDEA中可以添加相关的依赖&#xff0c;使用对应的API来操作。 准备工作 搭建一个SpringBoot项目&#xff0c;DAO使用…

为什么 Linux 内核协议栈会丢弃 SYN 数据包

最近了解到 SYN 数据包丢弃的问题&#xff0c;网上有一些资料&#xff0c;这里记录分享一下。 serverfault上的重要信息 tcp - No SYN-ACK Packet from server - Server Fault 信息如下&#xff1a; My embedded system with LwIP is the client and I have server1 and ser…

微信小程序开发,小程序类目符合,线上版本无权限申请wx.getLocation接口

我开发 的小程序类目符合wx.getLocation接口的申请标准 但是却还是显示无权限申请 后来研究好久才发现&#xff0c;小程序需要在发布线上版本时提交用户隐私保护指引 如未设置也可以在 设置-服务内容声明-用户隐私保护指引-声明处理用户信息项并补充填写后提交用户隐私协议审核…

MURF20100CTR-ASEMI快恢复对管封装、尺寸、参数

编辑&#xff1a;ll MURF20100CTR-ASEMI快恢复对管封装、尺寸、参数 型号&#xff1a;MURF20100CTR 品牌&#xff1a;ASEMI 芯片个数&#xff1a;2 芯片尺寸&#xff1a;102MIL*2 封装&#xff1a;TO-220F 恢复时间&#xff1a;50ns 工作温度&#xff1a;-50C~150C 浪…

k8s集群环境的搭建

1.环境规划 1.1 集群类型 Kubernetes集群大致分为两类&#xff1a;一主多从和多主多从。 一主多从&#xff1a;一个Master节点和多台Node节点&#xff0c;搭建简单&#xff0c;但是有单机故障风险&#xff0c;适合用于测试环境。 多主多从&#xff1a;多台Master和多台Node节点…