RS485通信(Modbus协议)

协议介绍

RS485介绍:http://t.csdn.cn/bOuFX

Modbus协议:http://t.csdn.cn/mgioX

CubeMX配置

RS-485通信使用到了串口3,TX接到SP3485芯片的DI,RX接到RO,芯片使能脚RS485_DE_nRE接到PG10

此外实验还使用到了SHT30数字温湿度传感器获取环境温湿度,继电器和蜂鸣器可通过触摸按键1和触摸按键2控制启动和关闭,数码管实时显示温湿度

GPIO配置

USART3配置

因为Modbus协议多用于工业领域,环境会多干扰,所以波特率常用9600,串口3就配置为9600

开启串口3的发送DMA和接收DMA,都选择普通模式,内存地址增加,因为发送和接收都是放在一个数组中

NVIC配置

发送:采用DMA+TC中断

接收:采用DMA+空闲中断

NVIC配置一定要注意,在代码写完后发现串口通信不了,排查后才发现是NVIC几个中断的优先级有问题,改了优先级就好了

DMA是搬运串口数据的,所以优先级要最高,因为采用DMA+空闲中断接收,代码中采用判断标志位来调用自己的回调函数,所以这里DMA1通道3就不使能中断,没用到。串口3的优先级设为1,定时器6作用较小,优先级设最低

程序

串口数据收发过程(接收采用DMA+空闲中断,写法一)

一、MyInit.c

在初始化函数中,初始化完定时器、数码管和IIC后,用HAL库提供的宏定义使能串口3的空闲中断,然后调用HAL_UART_Receive_DMA开启串口3的DMA接收模式,因为上位机一打开就会通过串口发送modbus协议数据,通过RS-485接口的A、B线,到达实战板的485芯片,被转化为TTL电平到达串口3,DMA就去搬运数据放到pucRec_Buffer接收缓存中

/*
* @name   Peripheral_Set
* @brief  外设设置
* @param  None
* @retval None
*/
static void Peripheral_Set()
{printf("---此程序实现采集SHT30温湿度值并显示功能---\r\n");printf("Initialization completed,system startup!\r\n");printf("Software version is V%.1f\r\n\r\n",SoftWare_Version);Timer6.Timer6_Start_IT();   //启动定时器Display.TM1620_Init();      //数码管初始化IIC_Soft.IIC_Init();        //IIC初始化__HAL_UART_ENABLE_IT(&huart3,UART_IT_IDLE);   //使能串口3空闲中断HAL_UART_Receive_DMA(&huart3,UART3.pucRec_Buffer,PUCREC_BUFFER_LEN);   //开启串口3 DMA接收模式
}

二、stm32f1xx_it.c

待DMA搬运完协议数据后,会触发串口3全局中断USART3_IRQHandler,在该函数里判断空闲中断标志位IDLE是否被置位,是则先清除标志位,再调用自己定义的中断空闲回调函数,要在这个中断源文件前面引入自己的头文件MyApplication.h,才能调用HAL_UART_IDLECallback这个函数

#include "MyApplication.h"
...
/*** @brief This function handles USART3 global interrupt.*/
void USART3_IRQHandler(void)
{/* USER CODE BEGIN USART3_IRQn 0 *///检测到串口空闲中断if(__HAL_UART_GET_FLAG(&huart3,UART_FLAG_IDLE) != 0x00u){//先清除IDLE标志位__HAL_UART_CLEAR_IDLEFLAG(&huart3);//再调用自己的空闲中断回调函数HAL_UART_IDLECallback(&huart3);}/* USER CODE END USART3_IRQn 0 */HAL_UART_IRQHandler(&huart3);/* USER CODE BEGIN USART3_IRQn 1 *//* USER CODE END USART3_IRQn 1 */
}

三、CallBack.c

在自己编写的空闲中断回调函数中调用Modbus协议解析函数Protocol_Analysis,该函数就对串口接收到的Modbus协议进行分析,函数里会先关闭DMA接收,再处理数据,同时会有发送数据的操作,协议解析函数执行完后调用HAL_UART_Receive_DMA重新开启串口DMA接收

注意:HAL_UART_IDLECallback函数HAL库并没有,是自己命名的

/*
* @name   HAL_UART_IDLECallback
* @brief  串口接收完成空闲中断回调函数
* @param  huart:串口指针
* @retval None
*/
void HAL_UART_IDLECallback(UART_HandleTypeDef *huart)
{//接收完成串口数据后,触发空闲中断,在这里处理接收数据if(huart->Instance == huart3.Instance){Modbus.Protocol_Analysis(&UART3);   //Modbus协议解析HAL_UART_Receive_DMA(&huart3,UART3.pucRec_Buffer,PUCREC_BUFFER_LEN);  //重新开启串口DMA接收}
}

四、Modbus.c

先关闭DMA接收,再处理数据,返回的数据通过UART3.SendArray(COM->pucSend_Buffer,13);发送,发送完就清除接收缓存,再退出执行第三步里的重新开启串口DMA接收的函数

五、UART3.c

SendArray函数就是串口3发送函数,要先使能485芯片的,设置为发送模式,然后调用HAL_UART_Transmit_DMA开始DMA发送,这样Modbus协议数据就会通过RS-485接口传输出去

/*
* @name   SendArray
* @brief  发送数组
* @param  p_arr:待发送的数据首地址,len:数组长度
* @retval None
*/
static void SendArray(uint8_t* p_arr,uint16_t len)
{UART3.RS485_Set_SendMode();HAL_UART_Transmit_DMA(&huart3,p_arr,len);
}

六、CallBack.c

待DMA将发送缓存的数据搬运到串口3发送完成后,DMA产生中断请求,几经调用,最终会调用HAL_UART_TxCpltCallback发送完成中断回调函数,在该函数中重新设置485芯片为接收模式,就又能在前面第三步重新开启串口DMA接收时进行数据的接收。

这样就完成了数据接收和发送的一整个流程

/*
* @name   HAL_UART_TxCpltCallback
* @brief  串口发送完成中断回调函数
* @param  huart:串口指针
* @retval None
*/
void HAL_UART_TxCpltCallback(UART_HandleTypeDef *huart)
{/*当DMA将内存数据搬运到串口,待串口发送完后产生中断,经过多次函数调用,最终来到这里的中断回调函数*/if(huart->Instance == huart3.Instance){//RS485设置为接收模式UART3.RS485_Set_RecMode();}
}

串口数据收发过程(接收采用DMA+空闲中断,写法二)

因为最新1.8.4版本的HAL库新增了串口DMA接收产生空闲中断的函数,也提供了现有的空闲中断回调函数,所以换这种写法来实现RS-485通信

使用函数:HAL_UARTEx_ReceiveToIdle_DMA

空闲中断回调函数:HAL_UARTEx_RxEventCallback

使用这种写法,需要开启串口3 DMA接收的中断,从而使用回调函数

一、MyInit.c

这次初始化函数就不用宏定义使能IDLE中断了,直接调用HAL_UARTEx_ReceiveToIdle_DMA函数开启DMA接收,接收完数据后会调用空闲中断回调函数HAL_UARTEx_RxEventCallback

/*
* @name   Peripheral_Set
* @brief  外设设置
* @param  None
* @retval None
*/
static void Peripheral_Set()
{printf("---此程序实现采集SHT30温湿度值并显示功能---\r\n");printf("Initialization completed,system startup!\r\n");printf("Software version is V%.1f\r\n\r\n",SoftWare_Version);Timer6.Timer6_Start_IT();   //启动定时器Display.TM1620_Init();      //数码管初始化IIC_Soft.IIC_Init();        //IIC初始化//使用库函数,使能串口DMA接收,接收完进入串口空闲中断HAL_UARTEx_ReceiveToIdle_DMA(&huart3,UART3.pucRec_Buffer,PUCREC_BUFFER_LEN);
}

二、stm32f1xx_it.c

串口3全局中断中就不用判断IDLE标志位了,后面直接重写回调函数即可

/*** @brief This function handles USART3 global interrupt.*/
void USART3_IRQHandler(void)
{/* USER CODE BEGIN USART3_IRQn 0 *//* USER CODE END USART3_IRQn 0 */HAL_UART_IRQHandler(&huart3);/* USER CODE BEGIN USART3_IRQn 1 *//* USER CODE END USART3_IRQn 1 */
}

三、CallBack.c

写法一的HAL_UART_IDLECallback函数并不是HAL库提供的,是自己仿照其命名来定义的一个用户函数,而这里的HAL_UARTEx_RxEventCallback函数是HAL库提供的串口空闲中断回调函数,直接调用,并在里面添加Modbus协议解析函数即可,这样就能很方便的接收不定长的数据了,后面的功能步骤与写法一相同

* @name   HAL_UARTEx_RxEventCallback
* @brief  串口接收完成空闲中断回调函数
* @param  huart:串口指针,Size:接收数据长度
* @retval None
*/ void HAL_UARTEx_RxEventCallback(UART_HandleTypeDef *huart, uint16_t Size){if(huart->Instance == huart3.Instance){Modbus.Protocol_Analysis(&UART3);   //Modbus协议解析HAL_UARTEx_ReceiveToIdle_DMA(&huart3,UART3.pucRec_Buffer,PUCREC_BUFFER_LEN);   //继续接收数据}}

实验效果

上位机检测到串口号后,发送Modbus协议数据,32单片机接收了并返回了应答数据,上位机能显示SHT30采集的温湿度,同时能通过按钮控制继电器和蜂鸣器,RS-485(Modbus协议)通信成功

STM32物联网项目-RS485通信(Modbus协议)相关推荐

  1. 物联网云平台DTU Modbus协议 上位机 下位机 源码 源代码 程序

    物联网云平台DTU Modbus协议 上位机 下位机 源码 源代码 程序 一.源码的使用基本说明: 1.1 编译语言: 下位机使用C语言:上位机使用C#语言 标准Modbus Slave通信下位机源码 ...

  2. RS485接口modbus协议RTU方式

    文章目录 RS485接口modbus协议RTU方式 一.RS485接口 二.Modbus通信协议 1.1 通信协议 1.2 通信方向 1.3 主从模式和寻址帧格式 1.4 modbus的主机寻址帧格式 ...

  3. STM32物联网项目-GPRS模块通信编程

    GPRS模块通信-编程 实验目的 32单片机通过串口2发送AT指令控制SIM800C检测GPRS网络,连接TCP服务器,连接服务器成功后,通过Doit.am远程信息转发服务将上传至公网服务器的温湿度值 ...

  4. STM32物联网项目-SHT30温湿度采集(IIC通信)

    SHT30温湿度采集(IIC通信) SHT30数字温湿度传感器 SHT3x湿度传感器系列包括低成本版本SHT30.标准版本SHT31,以及高端版本SHT35. SHT3x湿度传感器系列结合了多种功能和 ...

  5. stm32板间串口通信escape协议

    最近有使用串口的需求,用于两块板间的TTL串口通信,目前常见的串口通信协议可以归纳为两种模式 使用串口和一个定时器的通信协议[严格限制时间,常见协议为Modbus RTU] 使用单个串口的通信协议[存 ...

  6. STM32物联网项目-HMI串口屏

    HMI串口屏实验 串口屏 屏幕使用的是淘晶池的串口屏,显示内容可以通过官方上位机来编辑,屏幕学习平台:http://wiki.tjc1688.com/doku.php?id=start 通信原理:屏幕 ...

  7. STM32物联网项目-SPI FLASH编程

    SPI编程--读写Flash芯片(W25Q64JV) FLASH芯片介绍--W25Q64JV W25Q64JV的芯片手册是英文的,用软件翻译了一下,有些地方翻译得不准确,大概了解一下即可,例如芯片的工 ...

  8. STM32物联网项目-通过ESP12S模块连接TCP服务器

    通过ESP12S模块连接TCP服务器 可参考STC15实战的WiFi通信:http://t.csdn.cn/Aw0Uc ESP-12S模块 引脚功能定义 实验目标 STM32通过串口与ESP-12S模 ...

  9. STM32物联网项目-ADC采集实验板板温度(NTC热敏电阻)

    STM32 ADC采集板载温度 STM32 ADC简介 ​ STM32 拥有 1~3 个 ADC(STM32F101/102 系列只有 1 个 ADC),这些 ADC 可以独立使用, 也可以使用双重模 ...

最新文章

  1. mysql数据更新回退_Mysql的几个灵魂拷问(一)
  2. 从源码分析DEARGUI之add_input_text
  3. JavaScript实现表单的分向提交
  4. windows下安装gevent
  5. 思科路由器debug基本操作和简单配置
  6. linux nfs系统客户端,Linux系统中挂载共享目录NFS文件系统客户端安装与配置
  7. Apache2.4 与 PHP 5.5 64位版的安装配置
  8. Centos下安装Gcc和Qt
  9. java list 合并 重复的数据_Java ArrayList合并并删除重复数据3种方法
  10. 2018.12月问题整理杂记
  11. 动物基因组测序基础分析流程总结(GWAS全流程第一部分:WGS基础流程)
  12. 【苹果群发iMessage推送位置推】软件安装将会按照 Developer Program License Agreement
  13. Ultraedit删除空白行
  14. NS-miracle安装
  15. 用上瘾模型来看:艾威学院
  16. python播放url音频_从URL获取音频并播放i
  17. English # 英语学习第一天(audience)
  18. Uniapp 应用消息通知插件 Ba-Notify
  19. FL Studio音频混音教程
  20. 用友U8+助力服装织造企业信息化建设 用友ERP 用友T+ 上海杰然软件

热门文章

  1. ioctl函数详解(Linux内核 )
  2. 燃气灶火小怎么回事?6步帮你判断问题在哪!
  3. TFN 微缆气吹机T500W 吹缆机 配件齐全性价比的首选
  4. 金马赛记 | 畅跑一场马拉松,纪念一段青葱岁月
  5. JAVA(景区门票类)
  6. 太卷了,企业级智慧社区也是能开源的?
  7. JS数字添加千位分隔符
  8. 简单快递查询接口API/插件开发使用
  9. 2020工具钳工(中级)考试题库及工具钳工(中级)复审模拟考试
  10. mysql复合主键的区别_MySQL 的联合主键与复合主键区别