stm32---RS485半双工通信

典型的串口通信标准有 RS232 和 RS485,RS232 是全双工点对点的通信,而 RS485 是半双工通信(2 线制),可以一点对多点进行组网,而且 RS485 是用缆 线两端的电压差值来表示传递信号,这与 RS232 电气特性大不一样。RS485 仅仅 规定了接受端和发送端的电气特性,并没有规定或推荐任何数据协议,因此 RS485 的协议层可以和 RS232 一样。


stm32---RS485半双工通信_第1张图片
连接方式

发送数据时,串口控制器的 TX 信号经过 收发器转换成差分信号传输到总线上,而接收数据时,收发器把总线上的差分信 号转化成 TTL 信号通过 RX 引脚传输到串口控制器中


stm32---RS485半双工通信_第2张图片
SP3485

SP3485是板子上的收发器。对收发器,RO是接收输出端,DI是发送数据输入端, RE 是接收使能信号(低电平有效), DE 是发送使能信 号(高电平有效)

开发板把RE和DE共同连接到了PG3,用高低电平来表示是输出有效还是接收有效。


本次列程是用USART2

rs485.c

#include "rs485.h"
#include "SysTick.h"

/*******************************************************************************
* 函 数 名         : RS485_Init
* 函数功能         : USART2初始化函数
* 输    入         : bound:波特率
* 输    出         : 无
*******************************************************************************/  
void RS485_Init(u32 bound)
{
    GPIO_InitTypeDef GPIO_InitStructure;
    USART_InitTypeDef USART_InitStructure;
    NVIC_InitTypeDef NVIC_InitStructure;
    
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOG|RCC_APB2Periph_GPIOA,ENABLE); //使能GPIOA\G时钟
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2,ENABLE);//使能USART2时钟
    
    /*  配置GPIO的模式和IO口 */
    GPIO_InitStructure.GPIO_Pin=GPIO_Pin_2; //TX-485    //串口输出PA2
    GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AF_PP;         //复用推挽输出
    GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz; 
    GPIO_Init(GPIOA,&GPIO_InitStructure);       /* 初始化串口输入IO */
    
    GPIO_InitStructure.GPIO_Pin=GPIO_Pin_3; //RX-485       //串口输入PA3
    GPIO_InitStructure.GPIO_Mode=GPIO_Mode_IN_FLOATING;     //模拟输入
    GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
    GPIO_Init(GPIOA,&GPIO_InitStructure);
    
    GPIO_InitStructure.GPIO_Pin=GPIO_Pin_3; //CS-485
    GPIO_InitStructure.GPIO_Mode=GPIO_Mode_Out_PP;     //推挽输出
    GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
    GPIO_Init(GPIOG,&GPIO_InitStructure);
    
    //USART2 初始化设置
    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); //初始化串口2
    
    USART_Cmd(USART2, ENABLE);  //使能串口 2
    
    USART_ClearFlag(USART2, USART_FLAG_TC);
    USART_ITConfig(USART2, USART_IT_RXNE, ENABLE);//开启接受中断

    //Usart2 NVIC 配置
    NVIC_InitStructure.NVIC_IRQChannel = USART2_IRQn;
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=3;//抢占优先级3
    NVIC_InitStructure.NVIC_IRQChannelSubPriority =2;       //子优先级2
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;         //IRQ通道使能
    NVIC_Init(&NVIC_InitStructure); //根据指定的参数初始化VIC寄存器、
    
    RS485_TX_EN=0;              //默认为接收模式   
}

/*******************************************************************************
* 函 数 名         : USART2_IRQHandler
* 函数功能         : USART2中断函数
* 输    入         : 无
* 输    出         : 无
*******************************************************************************/ 
void USART2_IRQHandler(void)
{
    u8 res;     
    if(USART_GetITStatus(USART2, USART_IT_RXNE) != RESET)//接收到数据
    {       
        res =USART_ReceiveData(USART2);//;读取接收到的数据USART2->DR
        RS485_TX_EN=1; //发送模式,RS232是全双工发送读取可同时,不需要这样转换模式分时
        delay_ms(1);
        USART_SendData(USART2,res);
        while(USART_GetFlagStatus(USART2,USART_FLAG_TC)!=1);
        delay_ms(2);
        RS485_TX_EN=0;//接受模式
    }  
    USART_ClearFlag(USART2,USART_FLAG_TC);  
}   


rs485.h

#ifndef _rs485_H
#define _rs485_H

#include "system.h"


//模式控制
#define RS485_TX_EN     PGout(3)    //485模式控制.0,接收;1,发送.
                                                         
void RS485_Init(u32 bound);


#endif

main.c



#include "system.h"
#include "SysTick.h"
#include "led.h"
#include "usart.h"
#include "rs485.h"


/*******************************************************************************
* 函 数 名         : main
* 函数功能         : 主函数
* 输    入         : 无
* 输    出         : 无
*******************************************************************************/
int main()
{
    u8 i=0;

    SysTick_Init(72);
    NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);  //中断优先级分组 分2组
    LED_Init();
    USART1_Init(9600);
    RS485_Init(9600);
    
    while(1)
    {
        i++;
        if(i%20==0)
        {
            led1=!led1;
        }
        
        delay_ms(10);
    }
}

你可能感兴趣的:(stm32---RS485半双工通信)