tag 标签: 485通讯

相关博文
  • 2024-10-10 12:01
    57 次阅读|
    0 个评论
    01 概述 RS485通信协议是一种多点通信协议,它允许多个设备在同一总线上进行通信,且每个设备都可以发送和接收数据。RS485通讯协议采用差分信号传输,具有高速、远距离、可靠性强等特点,可实现长距离的数据传输。 RS485信号利用两线之间的电压差来传递逻辑信号,规定当电压差为+2V~+6V时为逻辑“1”,而电压差为-2V~-6V时为逻辑“0”。这种传输方式对于外部干扰有良好的抵抗能力,可实现长距离和高噪声环境下的可靠传输。 RS485通信协议支持半双工通信模式,在同一总线上可以连接多个驱动器和接收器,方便建立设备网络。此外,RS485通信协议的接口电平低,不易损坏芯片,电平与TTL电平兼容,方便与TTL电路连接。RS485通信协议是一种适用于工业控制系统和智能家居等领域的通信协议,具有高速、远距离、可靠性强等优点,能够满足大量数据传输的需求,并提高数据传输的效率和实时性。 02 RS485通信的优缺点 1 RS485通信协议优点: 抗干扰性强:RS485采用平衡驱动器和差分接收器的组合,具有抗共模干扰能力,能够抵抗外部干扰,保证通信的稳定性。 传输距离远:RS485最大的通信距离约为1219米,最大传输速率为10Mbps,传输速率与传输距离成反比,可以在较长的距离上进行稳定的数据传输。 通信速率高:RS485的数据最高传输速率为10Mbps,比传统的串口通信协议快得多,可以满足高速数据传输的需求。 支持多设备连接:RS485采用总线式拓扑结构,允许多个设备共享同一通信线路,方便实现设备之间的互连互通。 2 RS485通信协议缺点: 通信速率限制:虽然RS485支持高速数据传输,但随着传输距离的增加,传输速率会受到限制。当传输距离超过一定距离时,需要使用中继器来扩展传输距离。 连接设备数量限制:由于RS485采用总线式拓扑结构,连接的设备数量越多,线路越复杂,因此连接设备数量受到限制。 信号衰减问题:在长距离传输时,由于信号衰减和噪声干扰等原因,可能会出现数据传输错误或丢失的情况。因此,对于长距离传输,需要采取措施来保证数据的准确性和完整性。 03 物理层接口 RS485通信协议的物理层接口包括差分信号传输、DB9或RJ45接口以及信号定义等。 差分信号传输是RS485通信协议的核心技术,通过两个信号线(A线和B线)来传输数据。A线传输数据的正信号,B线传输数据的负信号。这种差分信号的优点是可以抵消干扰信号,提高通信的稳定性。 在物理层接口中,RS485协议使用DB9或RJ45接口进行连接。DB9接口包括A线、B线、地线和控制线等,而RJ45接口则采用水晶头连接方式。 RS485通信协议的物理层还定义了电压、时序、数据速率等参数。标准规定,逻辑1的电压范围为+2V~+6V,逻辑0的电压范围为-6V~-2V。在较长的电缆长度上,接收器接收到的电压可能会降低到+/- 200 mV,但对于RS485仍然是完全可以接受的。RS485通信协议的物理层接口规定了通信协议的核心技术要求,包括差分信号传输、接口标准和信号定义等,以确保数据传输的稳定性和可靠性。 四 RS485与Modbus的区别 物联网的从业者,刚应用RS485时,经常会接触到另外一个协议:Modbus协议,它与RS485有什么关系和区别呢? RS485与Modbus的区别主要体现在以下三个方面: 协议性质:RS485是一种物理层通信标准,主要定义了电气特性、信号传输方式和连接方式等,而Modbus是一种通信协议,定义了一种常用的通信格式和规则,用于在主设备和从设备之间进行数据交换。 应用范围:RS485通常用作物理层协议,支持Modbus协议,而Modbus更常用于工业控制领域,是一种通用的通信语言,支持RS485、RS232等串口。 功能特性:RS485具有较长的通信距离、较强的抗干扰能力,支持多点、双向通信,而Modbus支持主从模式,可以实现多个设备之间的数据交换。 所以,RS485和Modbus在协议性质、应用范围和功能特性方面存在明显的区别。在工业控制和智能设备通信领域,二者常常被结合使用,以实现高效、稳定的数据传输。 04 综述 RS485通信协议在物联网中具有重要的地位和价值。首先,RS485协议是一种可靠、高效的通信协议,适用于多个设备之间的长距离通信,能够满足物联网中大量设备之间数据传输的需求。其次,RS485协议具有抗干扰能力强、传输距离远、支持多设备连接等优点,可以适应复杂的物联网环境,保证数据传输的稳定性和可靠性。此外,RS485协议的传输层协议规定了数据传输的格式和规则,包括数据帧的定义、传输顺序、校验方式等,可以满足物联网中不同应用场景的数据传输需求。 在物联网中,RS485协议被广泛应用于各种领域,如工业控制、智能家居、城市管理、智能交通等。在这些领域中,RS485协议可以实现设备之间的快速、稳定、可靠的数据传输,提高设备的智能化程度和用户体验。例如,在智能家居中,RS485协议可以用于家庭内部的各种设备之间的通信,包括智能电视、智能音响、智能照明、智能安防等,实现设备的互联互通和集中控制。 AIoT星球君:RS485通信协议在物联网中具有重要的地位和价值,它的优点和特性使其成为工业控制系统和智能家居等领域的重要通信方式。通过使用RS485协议,可以实现设备的远程监控和控制,提高设备的智能化程度和用户体验。 05 组件的使用 1 Gitee链接地址 组件位于amaziot_bloom_os_sdk\libraries\air_4g_sw\air_sw\am_485.c Gitee源码地址:https://gitee.com/ning./hongdou Github源码地址:https://github.com/ayumid/hongdou 2 应用层组件功能介绍 提供485串口Modbus实例。实现轮询,并将Modbus RTU 协议数据,转发到服务器。 该组件需要和文件组件组合使用,文件中记录了485总线中哪些设备目前在线等信息 。 3 代码讲解 dtu_485_task_init 初始化modbus任务 void dtu_485_task_init(void) { OSA_STATUS status = 0; /*creat message*/ status = OSAMsgQCreate(&dtu_485_msgq, "dtu_485_msgq", DTU_485_TASK_MSGQ_MSG_SIZE, DTU_MODBUS_TASK_MSGQ_QUEUE_SIZE, OS_FIFO); ASSERT(status == OS_SUCCESS); status = OSATaskCreate(&dtu_485_msgq_task_ref, dtu_485_task_stack, DTU_485_TASK_STACK_SIZE, 161, "modbus_task", dtu_modbus_task, NULL); ASSERT(status == OS_SUCCESS); } dtu_alive_task 检查设备在线情况任务,轮询检查,检查最后一次收到信息和当前时间的时间差,判断是否离线 static void dtu_alive_task(void *ptr) { OSA_STATUS status = 0; int i = 0; UINT32 timestamp = 0; // int id = 0; DTU_FILE_PARAM_T* dtu_file_ctx = NULL; dtu_file_ctx = dtu_get_file_ctx(); while(1) { // uprintf("%s timer msg\r\n", __FUNCTION__, __LINE__); //for循环查询列表中哪些指令激活,按照激活指令参数配置 指令 for(i = 0; i modbus.cmd .fn); } } sleep(1); } } dtu_485_task 485主任务,接收发送485串口数据 modbus.config.type) { dtu_modbus_interval_timer_start(); } //#define AGILE_MODBUS_FC_READ_COILS 0x01 //#define AGILE_MODBUS_FC_READ_DISCRETE_INPUTS 0x02 //#define AGILE_MODBUS_FC_READ_HOLDING_REGISTERS 0x03 //#define AGILE_MODBUS_FC_READ_INPUT_REGISTERS 0x04 //#define AGILE_MODBUS_FC_WRITE_SINGLE_COIL 0x05 //#define AGILE_MODBUS_FC_WRITE_SINGLE_REGISTER 0x06 //#define AGILE_MODBUS_FC_READ_EXCEPTION_STATUS 0x07 //#define AGILE_MODBUS_FC_WRITE_MULTIPLE_COILS 0x0F //#define AGILE_MODBUS_FC_WRITE_MULTIPLE_REGISTERS 0x10 //#define AGILE_MODBUS_FC_REPORT_SLAVE_ID 0x11 //#define AGILE_MODBUS_FC_MASK_WRITE_REGISTER 0x16 //#define AGILE_MODBUS_FC_WRITE_AND_READ_REGISTERS 0x17 while(1) { //阻塞1s等待从机回复的数据 status = OSAMsgQRecv(dtu_modbus_msgq, (void *)&uart_data, DTU_MODBUS_TASK_MSGQ_MSG_SIZE, OSA_SUSPEND); if(status == OS_SUCCESS) { if(DTU_MODBUS_TIMER_INTERVAL_MSG == uart_data.id) { // uprintf("%s timer msg\r\n", __FUNCTION__, __LINE__); if(DTU_MODBUS_POOLLING_STATE == st_dtu_md.state) { //for循环查询列表中哪些指令激活,按照激活指令参数配置 指令 for(i = st_dtu_md.id; i modbus.config.delay); //开始modbus驱动定时器 // dtu_modbus_interval_timer_start(); } else { // uprintf("%s send md hex\r\n", __FUNCTION__, __LINE__); // int j = 0; // for(j = 0; j send_buf, send_len); } } else if(DTU_MODBUS_POOLLING_WN_STATE == st_dtu_md.state) { //for循环查询列表中哪些指令激活,按照激活指令参数配置 指令 for(i = st_dtu_md.id; i modbus.cmd_wn .reg_data); // int j = 0; // for(j = 0; j modbus.cmd_wn .reg_data); // int j = 0; // for(j = 0; j modbus.config.delay); //开始modbus驱动定时器 dtu_modbus_interval_timer_start(); } else { // uprintf("%s send md hex\r\n", __FUNCTION__, __LINE__); // int j = 0; // for(j = 0; j send_buf, send_len); } } } else if(DTU_MODBUS_DATA_MSG == uart_data.id && NULL != uart_data.UArgs) { // uprintf("%s modbus res", __FUNCTION__, __LINE__); // // UINT8* p = uart_data.UArgs; // for (i = 0; i modbus.config.res_type) // { // //判断是否是modbus一帧数据 // ret = dtu_modbus_protocol_check(uart_data.UArgs, uart_data.len); // if(DTU_MODBUS_PROTOCOL_SUCCESS == ret) // { // uprintf("modbus tcp res"); // } // } else { uprintf("modbus rtu res"); //modbus rtu帧,直接发 #ifdef DTU_BASED_ON_TCP dtu_socket_write(uart_data.UArgs, uart_data.len); #endif /* ifdef DTU_BASED_ON_TCP.2023-10-31 12:01:18 by: zhaoning */ #ifdef DTU_BASED_ON_MQTT dtu_mqtt_send(uart_data.UArgs, uart_data.len); #endif /* ifdef DTU_BASED_ON_MQTT.2023-10-31 12:01:28 by: zhaoning */ } //释放数据内存 free(uart_data.UArgs); //置空 uart_data.UArgs = NULL; } } } } dtu_485_interval_timer_init 初始化指令间隔定时器,Modbus轮询过程中每个指令之间的间隔时间 static void dtu_485_interval_timer_init(void) { OSA_STATUS status = 0; //初始化指令间隔定时器 status = OSATimerCreate(&st_dtu_md.md_timer_ref); ASSERT(status == OS_SUCCESS); } dtu_485_interval_timer_start 开始指令间隔定时器 modbus.config.interval * 200 , dtu_modbus_interval_timer_callback, 0); } 4 Demo实战 4.1 创建一个Demo 复制20.9_di_xtu示例工程,到同一个文件夹下,修改文件名为20.12_485_air_sw,如图: 4.2 修改makefile 增加文件组件所在目录头文件路径,和源文件路径,以及一些宏定义,如图: -D是makefile中定义宏定义必要的前缀,可以搜索相关makefile学习文章学习相关知识。 DTU_BASED_ON_TCP 表示当前是TCP模式,当前组件使用需要am.h中包含一些对应。 DTU_TYPE_5X6 表示使用SOM板贴片5x6卡,可以使用其它卡,修改为对应宏定义就可以。 DTU_UART_115200_BAUD 表示使用115200波特率 DTU_TYPE_JSON_INCLUDE 表示把JSON功能包含进来 4.3 增加头文件 使用代码编辑器,将新建的工程文件加入代码编辑器中,打开main.c,修改main.c,加入am.h头文件,如图: 4.4 修改代码 示例使用的是板载5x6卡,用户的硬件可能是使用外置卡,或者是三合一全网通卡,因为硬件上三种卡使用的模组SIM卡接口不一样(外置卡SIM1,5x6卡和三合一卡SIM2),所以,需要通过一个全局变量来制定SIM卡硬件接口。 extern外部变量SDK_INIT_SIM_SELECT_VALUE,这里判断了是否使用外置卡,这个宏定义在Makefile里面定义。 在Phase1Inits_enter中,宏定义判断是否要包含对SDK_INIT_SIM_SELECT_VALUE变量的修改。 在Phase2Inits_exit 调用文件组件提供的对外API,如图: 4.5 编译 在SDK根目录打开命令行,输入命令.\build.bat -l .\amaziot_bloom_os_sdk\sample\libraries\20.14_modbus_xtu\ 1.301(MB)| |------------------------------------------------------------------------------------| cp_1606L.axf cp_1606L.bin cp_1606L.map gnumake: Leaving directory `F:/3.asr-b/cat.1-asr1606/1.software/BLOOM_OS_1606_OPENCPU_1191_A08/amaziot_bloom_os_sdk/sample/libraries/20.14_modbus_xtu' "copy NEZHAC_CP_CNR_MIFI_TX.bin to ./ " 已复制 1 个文件。 4.6 生成固件 参考入门中开发工具,生成工具。 4.7 查看现象 固件下载到模组后,配置服务器地址,配置Modubs指令,之后用Modbus客户端来模拟查看 OK AT+TRANSIP="TCP","101.200.35.208",8866 OK CONNECT OK AT+MBADD=1,1,1,1,0,10 OK AT+MBADD=2,1,1,2,0,10 OK AT+MBADD=3,1,1,3,0,10 OK AT+MBADD=20,1,1,4,0,10 OK AT+MBADD=49,1,1,5,0,10 OK AT+MBADD=50,1,1,6,0,6666 OK AT+MBADDWN=1,1,1,16,0,5,"16B352A9F615D7D3FE198" OK AT+MBCFG=1,1,3,6 OK 5 总结 根据实验现象,用户需要实现自己的AT指令,只需要参考组件中的例子,按照自己需求修改, 本文章源自奇迹物联开源的物联网应用知识库Cellular IoT Wiki,更多技术干货欢迎关注收藏Wiki: Cellular IoT Wiki 知识库(https://rckrv97mzx.feishu.cn/wiki/wikcnBvAC9WOkEYG5CLqGwm6PHf) 注:本文部分内容来源于网络,如有侵权,请及时联系我们。
相关资源