RS485和RS232的区别
RS485简介
RS-485采用平衡发送和差分接收,因此具有抑制共模干扰的能力。加上总线收发器具有高灵敏度,能检测低至200mV的电压,故传输信号能在千米以外得到恢复,所以远距离传输一般使用RS485通信。
RS485在通信时采用差分传输方式,它使用一对双绞线,将其中一线定义为A,另一线定义为B,通常情况下,发送驱动器A、B之间的正电平在+2~+6V,是一个逻辑状态,负电平在-2~6V,是另一个逻辑状态。
RS-485是半双工的工作方式,因此,发送电路须由使能信号加以控制。
RS232简介
RS-232的工作方式时全双工通信方式,采取不平衡传输方式,即所谓单端通讯,收、发端的数据信号是相对于信号地。RS-232-C总线标准设有25条信号线,包括一个主通道和一个辅助通道,在多数情况下主要使用主通道,需要几条信号线就可实现,如一条发送线、一条接收线及一条地线。
典型的RS-232信号在正负电平之间摆动,在发送数据时,发送端驱动器输出正电平在+5~+15V,负电平在-5~-15V电平。当无数据传输时,线上为TTL,从开始传送数据到结束,线上电平从TTL电平到RS-232电平再返回TTL电平。
接收器典型的工作电平在+3~+12V与-3~-12V。由于发送电平与接收电平的差仅为2V至3V左右,所以其共模抑制能力差,再加上双绞线上的分布电容,其传送距离最大为约15米,最高速率为20kb/s。
区别
简单地说,RS-232与RS-485的区别在于:
1、传输方式不同。 RS-232是全双工通信,采取不平衡传输方式,即所谓单端通讯。而RS485是半双工通信,采用平衡传输,即差分传输方式。
2、传输距离不同。RS-232适合本地设备之间的通信,传输距离一般不超过20m。而RS-485的传输距离为几十米到上千米。
3、RS-232 只允许一对一通信,而RS-485 接口在总线上是允许连接多达128个收发器。
代码实现
初始化
void USART3_Init(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
USART_InitTypeDef USART_InitStructure;
/* config USART3 clock */
RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOB , ENABLE);
RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOE , ENABLE);
RCC_APB1PeriphClockCmd( RCC_APB1Periph_USART3 , ENABLE);
//对于复用的输入功能,端口必须配置成输入模式(浮空、上拉或下拉)且输入引脚必须由外部驱动
//对于复用输出功能,端口必须配置成复用功能输出模式(推挽或开漏)。
//对于双向复用功能,端口位必须配置复用功能输出模式(推挽或开漏)。这时,输入驱动器被配置成浮空输入模式。
//如果把端口配置成复用输出功能,则引脚和输出寄存器断开,并和片上外设的输出信号连接。
//如果软件把一个GPIO脚配置成复用输出功能,但是外设没有被激活,它的输出将不确定
/* USART3 GPIO config */
/* Configure USART3 Tx as alternate function push-pull */
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOB, &GPIO_InitStructure);
// Configure USART3 Rx as input floating
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;//
GPIO_Init( GPIOB, &GPIO_InitStructure);
/*通用推挽输出*/
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_15 ;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOE, &GPIO_InitStructure);
/* USART3 mode config */
//The baud rate is computed using the following formula:
//- IntegerDivider = ((PCLKx) / (16 * (USART_InitStruct->USART_BaudRate)))
//- FractionalDivider = ((IntegerDivider - ((u32) IntegerDivider)) * 16) + 0.5 */
USART_InitStructure.USART_BaudRate = 19200;
USART_InitStructure.USART_WordLength = USART_WordLength_8b;
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( USART3, &USART_InitStructure);
GPIO_WriteBit( EN_1000_PORT, EN_1000_PORTBIT, Bit_RESET ); //发送使能关闭,只有在接受完数据,解析好了以后准备发送数据包的时候使能。
/*中断使能*/
USART_ITConfig(USART3, USART_IT_RXNE , ENABLE );
USART_ITConfig(USART3, USART_IT_TC , ENABLE );
USART_Cmd( USART3, ENABLE);
//中断配置
NVIC_InitTypeDef NVIC_InitStructure;
NVIC_PriorityGroupConfig( NVIC_PriorityGroup_1 );
/*中断设置*/
NVIC_InitStructure.NVIC_IRQChannel = USART3_IRQn; //CAN1 RX0中断
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1; //抢占优先级1
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; //子优先级为2
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
}
中断函数管理
//预定义
#define UARTFLAG_REVIDLE 0X03
#define UARTFLAG_REVING 0X01
#define UARTFLAG_REVEND 0X02
#define UART_STA_WAITREV 0x04
#define UARTFLAG_SENDING 0X10
#define UARTFLAG_SENDEND 0X20
#define UART_BUFFER_SIZE 300
//结构体定义
typedef struct tagTYPE_UART_DATA
{
//UART
uint8_t ucRunFlag; // b0 正在接收 B1 接收完毕 B4正在发送 B5发送完毕
uint8_t ucRevDataLen;
uint8_t ucsRevData[ UART_BUFFER_SIZE ];
uint8_t ucSendIndex;
uint8_t ucSendLen;
uint8_t ucsSendData[ UART_BUFFER_SIZE ];
uint32_t ulTimeCount; //10ms,用于判断接收数据包停止时间
uint32_t ulWaitTimeCount;//10MS,用于判断接收等待最长时间和下次发送间隔
}TYPE_UART_DATA;
extern TYPE_UART_DATA USART3Info;
void USART3_IRQHandler(void)
{
uint8_t i;
if( USART_GetFlagStatus( USART3, USART_FLAG_RXNE ) == SET)
{
USART_ClearFlag(USART3, USART_FLAG_RXNE);
i = USART3->DR;
if( ( !(USART3Info.ucRunFlag &UARTFLAG_REVING) ) &&
( !(USART3Info.ucRunFlag & UARTFLAG_REVEND)) )
{ //串口由别的状态转为接受状态,更改相关标志位
USART3Info.ucsRevData[0] = i;
USART3Info.ucRunFlag = UARTFLAG_REVING;
USART3Info.ucRevDataLen = 1;
USART3Info.ulTimeCount = 1; //开始超时计算,在TIMER里面计时,超时认为接收完成,令USART3Info.ucRunFlag = UARTFLAG_REVEND
USART3Info.ulWaitTimeCount = 1 ;
}
else if( USART3Info.ucRunFlag & UARTFLAG_REVING)
{//串口处于接受状态就将数据依次保存到接受缓存区
USART3Info.ucsRevData[ USART3Info.ucRevDataLen++ ] = i;
USART3Info.ulTimeCount = 1;
USART3Info.ulWaitTimeCount = 1 ;
}
}
if( USART_GetFlagStatus( USART3, USART_FLAG_TC ) == SET)
{
USART_ClearFlag(USART3, USART_FLAG_TC);
if( USART3Info.ucSendIndex < USART3Info.ucSendLen )
{
USART_SendData(USART3, USART3Info.ucsSendData[ USART3Info.ucSendIndex++ ] );
}
else
{
GPIO_WriteBit( EN_1000_PORT, EN_1000_PORTBIT, Bit_RESET );
USART3Info.ucRunFlag = 0;
USART3Info.ulWaitTimeCount = 0;
}
}
}