17.1 485协议概述
485是属于OSI模型物理层的电气标准,属于2线制,半双工,多点通信标准,485总线采用两根线路的电压差来传递信号,485两根线路名称为A和B,当线路A与线路B的电压差为+2 +6V时表示逻辑电平1,当线路A与线路B的电压差为-2 -6V时表示逻辑电平0,485与232协议都属于串口通信协议,都是采用转换芯片将USART接口电平转换为485电平或者232电平,485协议传输速率在10米时候可达35Mbps,在1200米是可达到100Kbps,最大支持总线挂载32个节点,如果采用特制的芯片可以达到400个节点。
485电气连接中,为了进行阻抗匹配,需要在两根线路中并联一个120Ω的电阻,一般是一个设备并联一个,所以485协议只是之前USART协议的另一种表现形式,通过之前掌握的USART配置,借助485转换芯片就可以完成485通信线路的搭建。
17.2 实验例程
采用STM32F103ZET6芯片的PA2(USART2_TXD)和PA3(USART2_RXD)和一个485转换芯片SP485来实现RS485通信。其中SP485引脚描述如下图所示。
序号 | 名称 | 功能描述 |
---|---|---|
1 | RO | 接收器输出端:当RE为低电平时,若A-B≧200mV,RO输出为高电平若A-B≦-200mV,RO输出为低电平 |
2 | RE | 接收器输出使能控制当RE接低电平时,接收器输出使能,RO输出有效当RE接高电平时,接收器输出禁能,RO为高阻态RE接高电平且DE接低电平时,器件进入低功耗关断模式 |
3 | DR | 驱动器输出使能控制DE接高电平时驱动器输出有效,DE为低电平时输出为高阻态RE接高电平且DE接低电平时,器件进入低功耗关断模式 |
4 | DI | DI驱动器输入DE为高电平时,DI上的低电平使驱动器同相端输出为低电平,反相端输出为高电平DI上的高电平将使同相端输出为高电平,反相端输出为低 |
5 | GND | 电源地 |
6 | A | 接收器同相输入和驱动器同相输出端 |
7 | B | 接收器反相输入和驱动器反相输出端 |
8 | VCC | 电源,推荐3.3V |
根据上面的芯片描述,我们可以得到连接如下所示。
USART2_TXD(即PA2)接RO端
USART2_RXD(即PA3)接DI端
PD7接DR与RE端
(1)创建rs485.h文件,输入以下代码。
/*********************************************************************************************************
RS485 驱 动 文 件
*********************************************************************************************************/
#ifndef _RS485_H_
#define _RS485_H_
#include "sys.h"
/*********************************************************************************************************
硬 件 端 口 定 义
*********************************************************************************************************/
#define RS485_EN PDout( 7 )
/*********************************************************************************************************
数 据 结 构 定 义
*********************************************************************************************************/
typedef struct
{
u8 Buffer[ 255 ] ;
u8 Len ;
}Communication_Data;
extern Communication_Data RS485_Data;
/*********************************************************************************************************
函 数 列 表
*********************************************************************************************************/
void RS485_Init( u32 pclk1,u32 bound ) ; //RS485初始化
void RS485_Send_Data( u8 *buf, u8 len ) ; //发送n个字节
void RS485_Receive_Data( u8 *buf, u8 *len ) ; //接收n个字节
#endif
(2)创建rs485.c文件,输入以下代码。
#include "rs485.h"
#include "delay.h"
Communication_Data RS485_Data;
/***************************************************
Name :USART2_IRQHandler
Function :串口2中断服务函数
Paramater :None
Return :None
***************************************************/
void USART2_IRQHandler()
{
//接收到数据
if( USART2->SR&( 1<<5 ) )
{
RS485_Data.Buffer[ RS485_Data.Len ] = USART2->DR ; //记录接收到的值
RS485_Data.Len ++ ; //接收数据增加1
}
}
/***************************************************
Name :RS485_Send_Data
Function :接收n个字节
Paramater :
*buf:接收区首地址
len:读取的字节数
Return :None
***************************************************/
void RS485_Receive_Data( u8 *buf, u8 *len )
{
u8 i, rxlen=RS485_Data.Len ;
delay_ms( 10 ) ; //连续超过10ms没有接收到一个数据,则认为接收结束
//接收到了数据,且接收完成了
if( ( rxlen==RS485_Data.Len )&&( rxlen!=0 ) )
{
for( i=0; i SR&0x40 )==0 ) ;//等待发送结束
USART2->DR = buf[ t ] ;
}
while( ( USART2->SR&0x40 )==0 ) ; //等待发送结束
RS485_Data.Len = 0 ;
RS485_EN = 0 ; //设置为接收模式
}
/***************************************************
Name :RS485_Init
Function :RS485初始化
Paramater :
pclk1:PCLK1时钟频率
bound:波特率
Return :None
***************************************************/
void RS485_Init( u32 pclk1, u32 bound )
{
float temp ;
u16 mantissa, fraction ;
temp = ( float )( pclk1*1000000 )/( bound*16 ) ; //得到USARTDIV
mantissa = temp ; //得到整数部分
fraction = ( temp-mantissa )*16 ; //得到小数部分
mantissa <<= 4 ;
mantissa += fraction ;
RCC->APB2ENR |= 1<<5 ; //使能PD口
GPIOD->CRL &= 0x0FFFFFFF ;
GPIOD->CRL |= 0x30000000 ;
RCC->APB2ENR |= 1<<2 ; //使能PA口
GPIOA->CRL &= 0xFFFF00FF ; //IO状态设置
GPIOA->CRL |= 0x00008B00 ; //IO状态设置
RCC->APB1ENR |= 1<<17 ; //使能串口时钟
RCC->APB1RSTR |= 1<<17 ; //复位串口2
RCC->APB1RSTR &= ~( 1<<17 ) ; //停止复位
//波特率设置
USART2->BRR = mantissa ; //波特率设置
USART2->CR1 |= 0x200C ; //1位停止,无校验位
USART2->CR1 |= 1<<8 ; //PE中断使能
USART2->CR1 |= 1<<5 ; //接收缓冲区非空中断使能
NVIC_Init( 3, 3, USART2_IRQn, 2 ) ; //组2
RS485_EN = 0 ; //默认为接收模式
}
(3)创建1.c文件,输入以下代码。
#include "sys.h"
#include "delay.h"
#include "usart1.h"
#include "rs485.h"
int main()
{
u8 len, datatemp[ 10 ] ;
STM32_Clock_Init( 9 ) ; //STM32时钟初始化
SysTick_Init( 72 ) ; //SysTick初始化
USART1_Init( 72, 115200 ) ; //初始化串口1波特率115200
RS485_Init( 36, 9600 ) ; //初始化RS485
RS485_Send_Data( "RS485 Test", 10 ) ; //发送数据
while( 1 )
{
RS485_Receive_Data( datatemp, &len ) ;
delay_ms( 10 ) ;
}
}
-
单片机
+关注
关注
6035文章
44553浏览量
634764 -
OSI
+关注
关注
0文章
81浏览量
15414 -
485总线
+关注
关注
1文章
29浏览量
16780
发布评论请先 登录
相关推荐
评论