串口通信详解以及基于STM32芯片的底层通信代码

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;
        }            
    }  
}
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值