485通讯( 详解 )

485通讯( 详解 )485 一般称作 RS485 EIA 485 是隶属于 OSI 模型物理层的电气特性规定为 2 线 半双工 多点通信的标准

大家好,欢迎来到IT知识分享网。


一、485 简介

485(一般称作 RS485/EIA-485)是隶属于 OSI 模型物理层的电气特性规定为 2 线,半双工,多点通信的标准。它的电气特性和 RS-232 大不一样。用缆线两端的电压差值来表示传递信号。

(2) 传输速率高。10 米时,RS485 的数据最高传输速率可达 35Mbps,在 1200m 时,传输速度可达 100Kbps。

(3) 抗干扰能力强。RS485 接口是采用平衡驱动器和差分接收器的组合,抗共模干扰能力增强,即抗噪声干扰性好。

(4) 传输距离远,支持节点多。RS485 总线最长可以传输 1200m 以上(速率≤100Kbps)一般最大支持 32 个节点,如果使用特制的 485 芯片,可以达到 128 个或者 256 个节点,最大的可以支持到 400 个节点。

本节我以原子哥的战舰STM32开发板为例进行485通讯

本节我们通过该芯片连接 STM32 的串口 2,实现两个开发板之间的 485 通信。本节将实现这样的功能:通过连接两个战舰 STM32 开发板的 RS485 接口,然后由 KEY0 控制发送,当按下一个开发板的 KEY0 的时候,就发送 5 个数据给另外一个开发板,并在两个开发板上分别显示发送的值和接收到的值。

本节,我们只需要配置好串口 2,就可以实现正常的 485 通信了,串口 2 的配置和串口 1基本类似,只是串口的时钟来自 APB1,最大频率为 36Mhz。

二、 硬件设计

三、软件设计

rs485.c

#include "sys.h"  #include "rs485.h"  #include "delay.h" #ifdef EN_USART2_RX //如果使能了接收 //接收缓存区  u8 RS485_RX_BUF[64]; //接收缓冲,最大64个字节. //接收到的数据长度 u8 RS485_RX_CNT=0; void USART2_IRQHandler(void) { 
     u8 res; if(USART_GetITStatus(USART2, USART_IT_RXNE) != RESET) //接收到数据 { 
     res =USART_ReceiveData(USART2); //读取接收到的数据 if(RS485_RX_CNT<64) { 
     RS485_RX_BUF[RS485_RX_CNT]=res; //记录接收到的值 RS485_RX_CNT++; //接收数据增加1  } } } #endif  //初始化IO 串口2 //pclk1:PCLK1时钟频率(Mhz) //bound:波特率  void RS485_Init(u32 bound) { 
     GPIO_InitTypeDef GPIO_InitStructure; USART_InitTypeDef USART_InitStructure; NVIC_InitTypeDef NVIC_InitStructure; RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_GPIOD, ENABLE);//使能GPIOA,D时钟 RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2,ENABLE);//使能USART2时钟 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_7; //PD7端口配置 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; //推挽输出 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOD, &GPIO_InitStructure); GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2; //PA2 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //复用推挽 GPIO_Init(GPIOA, &GPIO_InitStructure); GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3;//PA3 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; //浮空输入 GPIO_Init(GPIOA, &GPIO_InitStructure); RCC_APB1PeriphResetCmd(RCC_APB1Periph_USART2,ENABLE);//复位串口2 RCC_APB1PeriphResetCmd(RCC_APB1Periph_USART2,DISABLE);//停止复位 #ifdef EN_USART2_RX //如果使能了接收 USART_InitStructure.USART_BaudRate = bound;//波特率设置 USART_InitStructure.USART_WordLength = USART_WordLength_8b;//8位数据长度 USART_InitStructure.USART_StopBits = USART_StopBits_1;//一个停止位 USART_InitStructure.USART_Parity = USART_Parity_No;///奇偶校验位 USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;//无硬件数据流控制 USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;//收发模式 USART_Init(USART2, &USART_InitStructure); ; //初始化串口 NVIC_InitStructure.NVIC_IRQChannel = USART2_IRQn; //使能串口2中断 NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 3; //先占优先级2级 NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3; //从优先级2级 NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //使能外部中断通道 NVIC_Init(&NVIC_InitStructure); //根据NVIC_InitStruct中指定的参数初始化外设NVIC寄存器 USART_ITConfig(USART2, USART_IT_RXNE, ENABLE);//开启中断 USART_Cmd(USART2, ENABLE); //使能串口  #endif RS485_TX_EN=0; //默认为接收模式 } //RS485发送len个字节. //buf:发送区首地址 //len:发送的字节数(为了和本代码的接收匹配,这里建议不要超过64个字节) void RS485_Send_Data(u8 *buf,u8 len) { 
     u8 t; RS485_TX_EN=1; //设置为发送模式 for(t=0;t<len;t++) //循环发送数据 { 
     while(USART_GetFlagStatus(USART2, USART_FLAG_TC) == RESET); USART_SendData(USART2,buf[t]); } while(USART_GetFlagStatus(USART2, USART_FLAG_TC) == RESET); RS485_RX_CNT=0; RS485_TX_EN=0; //设置为接收模式  } //RS485查询接收到的数据 //buf:接收缓存首地址 //len:读到的数据长度 void RS485_Receive_Data(u8 *buf,u8 *len) { 
     u8 rxlen=RS485_RX_CNT; u8 i=0; *len=0; //默认为0 delay_ms(10); //等待10ms,连续超过10ms没有接收到一个数据,则认为接收结束 if(rxlen==RS485_RX_CNT&&rxlen)//接收到了数据,且接收完成了 { 
     for(i=0;i<rxlen;i++) { 
     buf[i]=RS485_RX_BUF[i]; } *len=RS485_RX_CNT; //记录本次数据长度 RS485_RX_CNT=0; //清零 } } 

在头文件 rs485.h 中开启串口 2 的中断接收。

main.c

#include "led.h" #include "delay.h" #include "key.h" #include "sys.h" #include "lcd.h" #include "usart.h"  #include "rs485.h" int main(void) { 
     u8 key; u8 i=0,t=0; u8 cnt=0; u8 rs485buf[5]; delay_init(); //延时函数初始化  NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//设置中断优先级分组为组2:2位抢占优先级,2位响应优先级 uart_init(); //串口初始化为 LED_Init(); //初始化与LED连接的硬件接口 LCD_Init(); //初始化LCD  KEY_Init(); //按键初始化  RS485_Init(9600); //初始化RS485 POINT_COLOR=RED;//设置字体为红色  LCD_ShowString(30,50,200,16,16,"WarShip STM32"); LCD_ShowString(30,70,200,16,16,"RS485 TEST"); LCD_ShowString(30,90,200,16,16,"ATOM@ALIENTEK"); LCD_ShowString(30,110,200,16,16,"2015/1/15"); LCD_ShowString(30,130,200,16,16,"KEY0:Send"); //显示提示信息  POINT_COLOR=BLUE;//设置字体为蓝色  LCD_ShowString(30,150,200,16,16,"Count:"); //显示当前计数值  LCD_ShowString(30,170,200,16,16,"Send Data:"); //提示发送的数据  LCD_ShowString(30,210,200,16,16,"Receive Data:"); //提示接收到的数据  while(1) { 
     key=KEY_Scan(0); if(key==KEY0_PRES)//KEY0按下,发送一次数据 { 
     for(i=0;i<5;i++) { 
     rs485buf[i]=cnt+i;//填充发送缓冲区 LCD_ShowxNum(30+i*32,190,rs485buf[i],3,16,0X80); //显示数据 } RS485_Send_Data(rs485buf,5);//发送5个字节  } RS485_Receive_Data(rs485buf,&key); if(key)//接收到有数据 { 
     if(key>5)key=5;//最大是5个数据. for(i=0;i<key;i++)LCD_ShowxNum(30+i*32,230,rs485buf[i],3,16,0X80); //显示数据 } t++; delay_ms(10); if(t==20) { 
     LED0=!LED0;//提示系统正在运行  t=0; cnt++; LCD_ShowxNum(30+48,150,cnt,3,16,0X80); //显示数据 } } } 

此部分代码, cnt 是一个累加数,一旦 KEY0 按下按下,就以这个数位基准连续发送 5 个数据。当 485 总线收到数据的时候,就将收到的数据直接显示在 LCD 屏幕上。

免责声明:本站所有文章内容,图片,视频等均是来源于用户投稿和互联网及文摘转载整编而成,不代表本站观点,不承担相关法律责任。其著作权各归其原作者或其出版社所有。如发现本站有涉嫌抄袭侵权/违法违规的内容,侵犯到您的权益,请在线联系站长,一经查实,本站将立刻删除。 本文来自网络,若有侵权,请联系删除,如若转载,请注明出处:https://haidsoft.com/135840.html

(0)
上一篇 2025-07-01 19:33
下一篇 2025-07-01 20:00

相关推荐

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注微信