细说STM32F407单片机RS485收发通信实例及调试方法

目录

一、硬件配置

1、RCC、DEBUG、CodeGenerator

2、USART3

[3、 RS485_DIR](#3、 RS485_DIR)

4、NVIC

二、软件设计

1、RS485的收发控制

2、main.c

三、运行调试

1、修改RS485_DIR为SET后需要延迟

2、向串口助手发送的数据不能太长


MCU上的串口UART(USART)是逻辑电平(TTL或CMOS电平),在开发板上实现与串口助手之间的RS485通信,就是把单片机上的逻辑电平通过RS485物理层芯片转换为RS485电平。

本文继续使用旺宝红龙开发板STM32F407ZGT6 KIT V1.0。本文的目的是通过MAX485物理层芯片把开发板上的USART3(PB10、PB11)逻辑电平转换为RS485电平,然后通过一条USB转RS485的转换线连接到串口助手上。原理图如下:

P18的管脚A+连接USB转RS485的线的T/R+,P18的管脚A-连接USB转RS485的线的T/R-。

在串口助手上识别出识别出该线的驱动,选择并设置波特率,通过几次调试可以选择到不失真时的最大波特率,其它参数可以默认。串口助手的波特率与MCU里配置USART3时选择的波特率要一致。

一、硬件配置

1、RCC、DEBUG、CodeGenerator

  • RCC:外部晶振25MHz,HCLK=168MHz,PCLK1=42MHz,PCLK2=84MHz;
  • DEBUG:Serial Wire;
  • CodeGenerator:勾选☑Generate peripheral initialization as a pair of '.c/.h' files per peripheral

2、USART3

配置PB10、PB11为USART3,波特率9600,其它参数默认;

本文作者测试到波特率14400,不失真,15200失真。

3、 RS485_DIR

RS485是半双工通信的,因此有方向控制,设置PF7为RS485_DIR,默认为高电平。

4、NVIC

把Times base的中断优先级修改为0。USART3的全局中断可以设置为优先级1。如果不需要也可以不选择。

二、软件设计

实例程序很短,只是为了演示RS485的收发控制。

1、RS485的收发控制

每次向串口助手发送前,要先把RS485_DIR置位。

cpp 复制代码
  //修改RS485为发送
  HAL_GPIO_WritePin(RS485_DIR_GPIO_Port, RS485_DIR_Pin, GPIO_PIN_SET);

每次接收数据前要先把RS485_DIR复位。

cpp 复制代码
//默认RS485为接收状态
HAL_GPIO_WritePin(RS485_DIR_GPIO_Port, RS485_DIR_Pin, GPIO_PIN_RESET);

2、main.c

cpp 复制代码
/* USER CODE BEGIN Includes */
#include <stdio.h>
uint8_t rxbuf[8];
uint8_t ackbuf[]="123\r\n";
/* USER CODE END Includes */
cpp 复制代码
/* USER CODE BEGIN 2 */
  //默认RS485为发送状态
  uint8_t txbuf1[]="Hello,world!\r\n";
  HAL_UART_Transmit(&huart3,txbuf1,sizeof(txbuf1),1000);
  HAL_Delay(500);
  HAL_UART_Transmit(&huart3,txbuf1,sizeof(txbuf1),1000);
  HAL_Delay(500);
  uint8_t txbuf2[]="TEST RS485!\r\n";
  HAL_UART_Transmit(&huart3,txbuf2,sizeof(txbuf2),1000);
  HAL_Delay(500);
  HAL_UART_Transmit(&huart3,ackbuf,sizeof(ackbuf),1000);
  HAL_Delay(500);
  //修改RS485为接收
  HAL_GPIO_WritePin(RS485_DIR_GPIO_Port, RS485_DIR_Pin, GPIO_PIN_RESET);
  //485改为接收后,不能发送
  HAL_UART_Transmit(&huart3,ackbuf,sizeof(ackbuf),1000);
  HAL_Delay(500);
  //修改RS485为发送
  HAL_GPIO_WritePin(RS485_DIR_GPIO_Port, RS485_DIR_Pin, GPIO_PIN_SET);
  //没有适当的延迟,则乱码
  HAL_Delay(200);	//切换测试,注释掉,以观察乱码
  uint8_t txbuf3[]="can transmit again.\r\n";
  HAL_UART_Transmit(&huart3,txbuf3,sizeof(txbuf3),1000);
  HAL_Delay(500);
  HAL_UART_Transmit(&huart3,ackbuf,sizeof(ackbuf),1000);
  HAL_Delay(500);
  HAL_UART_Transmit(&huart3,txbuf1,sizeof(txbuf1),1000);
  HAL_Delay(500);
  //修改为小于16字节后,乱码消失.
  uint8_t txbuf4[]="transmit again.\r\n";
  HAL_UART_Transmit(&huart3,txbuf4,sizeof(txbuf4),1000);
  HAL_Delay(500);
  /* USER CODE END 2 */
cpp 复制代码
/* USER CODE BEGIN WHILE */
while (1)
{
    /* USER CODE END WHILE */
    /* USER CODE BEGIN 3 */
    /* 如果MCU接收到数据,则执行发送任务,发送前修改485为发送*/
    if(HAL_UART_Receive(&huart3,rxbuf,sizeof(rxbuf),1000) == HAL_OK)
    {
	    /*设置485为发送*/
	    HAL_GPIO_WritePin(RS485_DIR_GPIO_Port, RS485_DIR_Pin, GPIO_PIN_SET);
	    //修改RS485收发控制后要有延迟,否则,立刻发送的数据会有乱码
	    HAL_UART_Transmit(&huart3,ackbuf,sizeof(ackbuf),1000);
	    printf("\r\n");
	    HAL_Delay(200);
	    printf("修改RS485_DIR后要有延迟,");
	    printf("否则,立刻发送的数据会有乱码.\r\n");

	    HAL_Delay(500);	//这是必需,否则会乱码
	    HAL_UART_Transmit(&huart3,ackbuf,sizeof(ackbuf),1000);
	    HAL_Delay(500);

	    char str[8];
	    sprintf(str,"%s",ackbuf);
	    printf("test:%s\r\n",str);
	    HAL_Delay(500);

	    uint8_t txbuf6[]="RS485发送的数据:";
	    HAL_UART_Transmit(&huart3,txbuf6,sizeof(txbuf6),1000);
	    //printf("RS485发送的数据:");
	    HAL_Delay(500);
	    HAL_UART_Transmit(&huart3,rxbuf,sizeof(rxbuf),1000);
	    HAL_Delay(500);
	    printf("\r\n");
	    HAL_Delay(200);
	    uint8_t txbuf7[]="\r\n";
	    HAL_UART_Transmit(&huart3,txbuf7,sizeof(txbuf7),1000);
	    HAL_Delay(200);
    }

    /默认RS485为接收状态
    HAL_GPIO_WritePin(RS485_DIR_GPIO_Port, RS485_DIR_Pin, GPIO_PIN_RESET);
}
/* USER CODE END 3 */
cpp 复制代码
/* USER CODE BEGIN 4 */
//串口打印
int __io_putchar(int ch)
{
	HAL_UART_Transmit(&huart3,(uint8_t*)&ch,1,0xFFFF);
	return ch;
}
/* USER CODE END 4 */

三、运行调试

重要的调试发现,在调试RS485通讯时,发现串口助手上显示乱码,最终找到2个原因:

1、修改RS485_DIR为SET后需要延迟

每次HAL_GPIO_WritePin(RS485_DIR_GPIO_Port, RS485_DIR_Pin, GPIO_PIN_SET)后应该适当地延迟,不然,显示到串口助手上的数据乱码。

2、向串口助手发送的数据不能太长

向串口助手上发送的数据不能太长,不然,也会乱码。具体达到多长的数据才开始乱码,要测试后确定。过长的数据可以分批次传送,printf()函数更适合发送长的数据,也适合发送和显示有换行要求的数据;

相关推荐
CODECOLLECT1 小时前
京元 I62D Windows PDA 技术拆解:Windows 10 IoT 兼容 + 硬解码模块,如何降低工业软件迁移成本?
stm32·单片机·嵌入式硬件
BackCatK Chen1 小时前
STM32+FreeRTOS:嵌入式开发的黄金搭档,未来十年就靠它了!
stm32·单片机·嵌入式硬件·freertos·低功耗·rtdbs·工业控制
全栈游侠4 小时前
STM32F103XX 02-电源与备份寄存器
stm32·单片机·嵌入式硬件
Lsir10110_4 小时前
【Linux】中断 —— 操作系统的运行基石
linux·运维·嵌入式硬件
深圳市九鼎创展科技6 小时前
瑞芯微 RK3399 开发板 X3399 评测:高性能 ARM 平台的多面手
linux·arm开发·人工智能·单片机·嵌入式硬件·边缘计算
辰哥单片机设计6 小时前
STM32项目分享:车辆防盗报警系统
stm32·单片机·嵌入式硬件
風清掦8 小时前
【江科大STM32学习笔记-05】EXTI外部中断11
笔记·stm32·学习
小龙报8 小时前
【51单片机】从 0 到 1 玩转 51 蜂鸣器:分清有源无源,轻松驱动它奏响新年旋律
c语言·数据结构·c++·stm32·单片机·嵌入式硬件·51单片机
范纹杉想快点毕业8 小时前
嵌入式与单片机开发核心学习指南——从思维转变到第一性原理的深度实践
单片机·嵌入式硬件
Industio_触觉智能8 小时前
瑞芯微RK3566开发板规格书,详细参数配置,型号EVB3566-V1,基于RK3566核心板SOM3566邮票孔封装
嵌入式硬件·开发板·rk3568·rk3566·核心板·瑞芯微