[其他ST产品]

STM32-RS485通信软硬件实现

[复制链接]
864|68
手机看帖
扫描二维码
随时随地手机跟帖
原来是wjc|  楼主 | 2024-1-31 20:38 | 显示全部楼层 |阅读模式
1、RS485简介 

  RS-485又名TIA-485-A, ANSI/TIA/EIA-485或TIA/EIA-485。

  RS485是一个定义平衡数字多点系统中的驱动器和接收器的电气特性的标准,该标准由电信行业协会和电子工业联盟定义。使用该标准的数字通信网络能在远距离条件下以及电子噪声大的环境下有效传输信号。RS-485使得廉价本地网络以及多支路通信链路的配置成为可能。RS485接口组成的半双工网络,一般是两线制(以前有四线制接法,只能实现点对点的通信方式,现很少采用),多采用屏蔽双绞线传输。这种接线方式为总线式拓扑结构在同一总线上最多可以挂接32个结点。在RS485通信网络中一般采用的是主从通信方式,即一个主机带多个从机。很多情况下,连接RS-485通信链路时只是简单地用一对双绞线将各个接口的“A”、“B”端连接起来。RS485接口连接器采用DB-9的9芯插头座,与智能终端RS485接口采用DB-9(孔),与键盘连接的键盘接口RS485采用DB-9(针)。

  在低速、短距离、无干扰的场合可以采用普通的双绞线,反之,在高速、长线传输时,则必须采用阻抗匹配(一般为120Ω)的RS485专用电缆(STP-120Ω(用于RS485 & CAN)一对18AWG),而在干扰恶劣的环境下还应采用铠装型双绞屏蔽电缆(ASTP-120Ω(用于RS485 & CAN)一对18AWG)。


使用特权

评论回复
原来是wjc|  楼主 | 2024-1-31 20:39 | 显示全部楼层
2、RS485特性
RS-485的电气特性:逻辑“0”以两线间的电压差为+(2—6)V表示;逻辑“1”以两线间的电压差为-(2—6)V表示。接口信号电平比RS-232降低了,就不易损坏接口电路的芯片,且该电平与TTL电平兼容,可方便与TTL电路连接
RS-485的数据最高传输速率为10Mbps
RS-485接口是采用平衡驱动器和差分接收器的组合,抗共模干扰能力增强,即抗噪声干扰性好
RS-485接口的最大传输距离标准值为4000英尺(约1219米),实际上可达3000英尺,另外RS-232接口在总线上只允许连接1个收发器,即单站能力。而RS-485接口在总线上是允许连接多达128个收发器。即具有多站能力,这样用户可以利用单一的RS-485接口方便地建立起设备网络。

使用特权

评论回复
原来是wjc|  楼主 | 2024-1-31 20:39 | 显示全部楼层
3、RS485通信硬件实现
  博主使用的485芯片为MAX3485,实现半双工通信。应用电路如下图:

5061365ba3f722bd27.png

使用特权

评论回复
原来是wjc|  楼主 | 2024-1-31 20:39 | 显示全部楼层
R6为120欧的阻抗匹配电阻,如果长距离通信的话,一定要在最后一个节点接上这一个电阻;但是短距离通信的话焊上R6反而出错(博主在实验中发现,焊上匹配电阻后,主从节点通信异常,调试发现大量的00字节在自动收发),因此建议大家先不要焊上,但是在电路设计时保留。RXD485、TXD485分别接控制芯片的USART1_RX、USART1_TX(串口号可自行选择,这里使用串口1),此外;485C接芯片的PA4引脚(随意选择)用以切换485的通信状态。J1、J2为两个JST接口,方便485通信线路的连接,由于是从节点因而留出两个。以下为其余连接电路:

使用特权

评论回复
原来是wjc|  楼主 | 2024-1-31 20:39 | 显示全部楼层
7692065ba3f7ec3b40.png

使用特权

评论回复
原来是wjc|  楼主 | 2024-1-31 20:39 | 显示全部楼层
9455165ba3f8497fa6.png

使用特权

评论回复
原来是wjc|  楼主 | 2024-1-31 20:39 | 显示全部楼层
4、RS485通信软件实现

1 #include "sys.h"
2 #include "stdio.h"
3
4 #define        USART1_RX_LEN      50           //接收最大字节
5 #define        USART1_TX_LEN      50           //发送最大字节
6 #define     RS485_TX_EN        PAout(4)
7
8
9 extern  u8 USART1_RX_Buf[USART1_RX_LEN];  //接收缓冲
10 extern  u8 USART1_TX_Buf[USART1_TX_LEN];  //发送缓冲
11 extern  u8 USART1_RX_Data_Len;           //实际接收数据字节长度
12 extern  u8 USART1_TX_Data_Len;           //待发送数据字节长度
13 extern  u8 USART1_RX_Flag;               //是否收到数据
14
15 void RS485_Config(u32 bound);
16 void USART1_IRQHandler(void);
17 void RS485_Send_Data(u8 *buf,u8 len);

使用特权

评论回复
原来是wjc|  楼主 | 2024-1-31 20:40 | 显示全部楼层
1 #include "sys.h"
2 #include "delay.h"
3 #include "rs485.h"
4
5 u8 USART1_RX_Buf[USART1_RX_LEN];  //接收缓冲
6 u8 USART1_TX_Buf[USART1_TX_LEN];  //发送缓冲
7 u8 USART1_RX_Data_Len = 0;        //实际接收数据字节长度
8 u8 USART1_TX_Data_Len = 0;        //待发送数据字节长度
9 u8 USART1_RX_Flag = 0;            //串口1是否接收完数据      
10
11 void USART1_IRQHandler(void)
12 {
13     u8 res;
14     if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET) //接收到数据
15     {
16         res =USART_ReceiveData(USART1); //读取接收到的数据
17         if(USART1_RX_Data_Len<USART1_RX_LEN)
18         {
19             USART1_RX_Buf[USART1_RX_Data_Len]=res; //记录接收到的值
20             USART1_RX_Data_Len++; //接收数据增加 1
21         }                 
22         USART1_RX_Flag=1;   //串口1接收到数据
23     }
24 }
25
26 void RS485_Config(u32 bound)
27 {
28     GPIO_InitTypeDef GPIO_InitStructure;
29     USART_InitTypeDef USART_InitStructure;
30     NVIC_InitTypeDef NVIC_InitStructure;
31     
32     /*********************配置串口1**************************/
33     
34     /* config USART1 clock */
35     RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1 , ENABLE);
36     RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA  , ENABLE);
37     
38     /* USART1 GPIO config */
39     /* Configure USART1 Tx (PA.02) as alternate function push-pull *///TX
40     GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;
41     GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;       //复用推挽输出
42     GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
43     GPIO_Init(GPIOA, &GPIO_InitStructure);   
44     /* Configure USART1 Rx (PA.03) as input floating *///RX
45     GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
46     GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;  //浮空输入
47     GPIO_Init(GPIOA, &GPIO_InitStructure);
48     
49     
50     
51     
52     /* USART1 mode config */
53     
54     USART_InitStructure.USART_BaudRate = bound;
55     USART_InitStructure.USART_WordLength = USART_WordLength_8b;
56     USART_InitStructure.USART_StopBits = USART_StopBits_1;
57     USART_InitStructure.USART_Parity = USART_Parity_No ;
58     USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
59     USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
60     USART_Init(USART1, &USART_InitStructure);
61     
62     /*  USART1 接收中断 */
63     NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn; //使能串口 2 中断
64     NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 3; //先占优先级 3 级
65     NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2; //从优先级 2级
66     NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //使能外部中断通道
67     NVIC_Init(&NVIC_InitStructure);//初始化 NVIC 寄存器
68     
69     USART_ITConfig(USART1, USART_IT_RXNE, ENABLE); //开启中断
70     USART_Cmd(USART1, ENABLE); //使能串口
71     
72     //USART_ClearFlag(USART1, USART_FLAG_TC);//清发送完成标志
73     
74     
75     /**********************配置485控制口*********************/
76
77     GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4;   
78     GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;   //推挽输出 ,PA4,485Ctr
79     GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
80     GPIO_Init(GPIOA, &GPIO_InitStructure);
81     GPIO_ResetBits(GPIOA, GPIO_Pin_4);        //设置为接收模式,默认接收
82     
83 }
84
85 void RS485_Send_Data(u8 *buf,u8 len)       //发送完改为接收
86 {
87     u8 t;
88     RS485_TX_EN=1;//设置为发送模式
89     for(t=0;t<len;t++)
90     {
91         while(USART_GetFlagStatus(USART1, USART_FLAG_TC) == RESET);
92         USART_SendData(USART1,buf[t]);
93     }
94     while(USART_GetFlagStatus(USART1, USART_FLAG_TC) == RESET);
95     
96     USART1_RX_Data_Len=0;
97     RS485_TX_EN=0;//设置为接收模式   
98 }

使用特权

评论回复
原来是wjc|  楼主 | 2024-1-31 20:40 | 显示全部楼层
 通过以上代码我么们就能通过STM32的串口资源实现485的正常通信了。注意事项:

初始化串口:RX设置为浮空输入、TX设置为复用推挽输出
因为是从节点,默认为接收模式,485C初始化为低电平;主节点则相反。可根据需要修改
每次发送或接收时都应切换通信状态

使用特权

评论回复
earlmax| | 2024-2-2 21:15 | 显示全部楼层
RS485支持半双工通信,因此在发送和接收数据时需要进行状态切换。确保在发送数据时关闭接收器,反之亦然。

使用特权

评论回复
houjiakai| | 2024-2-2 22:25 | 显示全部楼层
通常,STM32的USART1_TX(发送)和USART1_RX(接收)引脚分别连接到RS485芯片的A和B引脚,同时,还需将STM32的某个GPIO引脚连接到RS485芯片的DE/RE引脚以控制其工作模式

使用特权

评论回复
uytyu| | 2024-2-3 16:56 | 显示全部楼层
选择适当的RS485芯片和驱动程序库。根据所选芯片的数据手册,正确配置引脚和相关寄存器,以实现RS485通信。

使用特权

评论回复
vivilyly| | 2024-2-3 21:11 | 显示全部楼层
在RS485通信总线上,通常需要在总线的两端各加上一个终端电阻,以减少信号反射。

使用特权

评论回复
kmzuaz| | 2024-2-3 22:10 | 显示全部楼层
在通信过程中可能会遇到各种错误,如帧错误、超时等,应在软件中实现相应的错误处理机制,以便在出现问题时能够采取适当的措施,比如重新发送数据或提示用户。

使用特权

评论回复
macpherson| | 2024-2-4 21:07 | 显示全部楼层
在实际电路中,可能需要加入去抖动处理,以确保接收到的数据脉冲是有效的通信信号,而不是由于接触不良等原因产生的瞬态干扰。

使用特权

评论回复
primojones| | 2024-2-4 22:44 | 显示全部楼层
在实现RS485通信时, 处理可能出现的错误,如通信错误、超时错误等。

使用特权

评论回复
youtome| | 2024-2-5 11:04 | 显示全部楼层
RS485采用差分信号传输,需要通过专门的RS485驱动芯片来实现TxD与RxD线之间的电气转换。

使用特权

评论回复
sdCAD| | 2024-2-5 13:10 | 显示全部楼层
根据RS485网络的实际长度和设备数量,在网络的两端接入匹配的终端电阻,通常为120Ω左右。

使用特权

评论回复
timfordlare| | 2024-2-5 13:51 | 显示全部楼层
由于RS485允许多个设备在同一总线上通信,因此软件应实现适当的冲突检测和解决机制。

使用特权

评论回复
averyleigh| | 2024-2-5 14:35 | 显示全部楼层
通过STM32CubeMX或其他配置工具,正确配置USART或UART外设,包括波特率、数据位、停止位和校验位。

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

68

主题

905

帖子

0

粉丝