基於STM32f103的RS458通信

簡介

1. 來歷

通常的微處理器都集成有 1 路或多路硬件 UART 通道,可以非常方便地實現串行通訊。在工業控制、電力通訊、智能儀表等領域中,也常常使用簡便易用的串行通訊方式作爲數據交換的手段。但是,在工業控制等環境中,常會有電氣噪聲干擾傳輸線路,使用 RS-232 通訊時經常因外界的電氣干擾而導致信號傳輸錯誤;另外, RS-232 通訊的最大傳輸距離在不增加緩衝器的情況下只可以達到 15 米。爲了解決上述問題, RS-485/422 通訊方式就應運而生了。

2. RS_485標準

RS-485 標準只對接口的電氣特性做出規定,而不涉及接插件、電纜或協議,在此基礎上用戶可以建立自己的高層通信協議。但由於 PC 上的串行數據通訊是通過 UART 芯片(較老版本的 PC 採用 I8250 芯片或 Z8530 芯片)來處理的,其通訊協議也規定了串行數據單元的格式( 8-N-1 格式): 1 位邏輯 0 的起始位, 6/7/8 位數據位, 1 位可選擇的奇(ODD)/偶(EVEN)校驗位, 1/2 位邏輯 1 的停止位。基於 PC 的 RS-232、 RS-422 與 RS-485標準均採用同樣的通訊協議。
在這裏插入圖片描述
RS-485 標準是爲彌補 RS-232 通信距離短、速率低等缺點而產生的。 RS-485 標準只規定了平衡發送器和接收器的電特性,而沒有規定接插件、傳輸電纜和應用層通信協議。RS-485 標準與 RS-232 不一樣,數據信號採用差分傳輸方式(Differential Driver Mode),也稱作平衡傳輸,它使用一對雙絞線,將其中一線定義爲 A,另一線定義爲 B。
通常情況下,發送發送器 A、 B 之間的正電平在+2~+6V,是一個邏輯狀態;負電平在-2~-6V,是另一個邏輯狀態。另有一個信號地 C。在 RS-485 器件中,一般還有一個“使能”控制信號。 “使能”信號用於控制發送發送器與傳輸線的切斷與連接,當“使能”端起作用時,發送發送器處於高阻狀態,稱作“第三態”,它是有別於邏輯“ 1”與“ 0”的第三種狀態。對於接收發送器,也作出與發送發送器相對的規定,收、發端通過平衡雙絞線將 A-A與 B-B 對應相連。當在接收端 A-B 之間有大於+200mV 的電平時,輸出爲正邏輯電平;小於-200mV 時,輸出爲負邏輯電平。在接收發送器的接收平衡線上,電平範圍通常在 200mV至 6V 之間。
在這裏插入圖片描述
定義邏輯 1(正邏輯電平)爲 A>B 的狀態,邏輯 0(負邏輯電平)爲 B>A 的狀態,A、 B 之間的壓差不小於 200mV。
在這裏插入圖片描述

3. 連接方式

在這裏插入圖片描述
它可以由一個主機控制多個從機。由於其採用的是半雙工方式,通信系統每一端的發送器和接收器,通過收/發開關轉換到通信線上,進行方向的切換,因此,會產生時間延遲,而且從機和從機之間要避免同時發送信息,以免數據在總線上互相干擾。

4. 引腳說明

在這裏插入圖片描述
在這裏插入圖片描述

5. 功能分析

(1)發送器

RS485發送器輸出是差分輸出。空載時輸出電壓的大小爲 0V~+3.3V。即使在差分輸出連接了 54Ω負載的條件下,發送器仍可保證輸出電壓大於 1.5V。 SP3481 和 SP3485 有一根使能控制線(高電平有效)。 DE( Pin3)上的邏輯高電平將使能發送器的差分輸出。如果 DE( Pin3)爲低,則發送器輸出呈現三態。

(2)接收器

RS485接收器的輸入是差分輸入,輸入靈敏度可低至± 200mV。接收器的輸入電阻通常爲 15kΩ(最小爲 12kΩ)。- 7V~+12V 的寬共模方式範圍允許系統之間存在大的零電位偏差。 SP3481 和 SP3485 的接收器有一個三態使能控制腳。如果 RE ( Pin2)爲低,接收器使能,反之接收器禁止。

6. RS-485 接口電路

微處理器的標準串行口通過 RXD 直接連接 SP485R 芯片的 RO 引腳, 通過 TXD
直接連接 SP485R 芯片的 DI 引腳。
由微處理器輸出的 R/D 信號直接控制 SP485R 芯片的發送器/接收器使能: R/D 信號爲“ 1”,則 SP485R 芯片的發送器有效,接收器禁止,此時微處理器可以向 RS-485 總線發送數據字節; R/D 信號爲“0”,則 SP485R 芯片的發送器禁止,接收器有效,此時微處理器可以接收來自 RS-485 總線的數據字節。此電路中,任一時刻 SP485R 芯片中的“接收器”和“發送器”只能夠有 1 個處於工作狀態。
在這裏插入圖片描述
在本次實驗中所用的開發板485電路圖是
在這裏插入圖片描述
RO --RS485_TX – PB10 – USART3_TX – 複用
DI --RS485_RX – PB11 – USART3_RX – 複用
RS485_RE – PC9 – 通用 //RS485_RE是發送器和接收器的開關

程序

在這裏我用的是用485與電腦串口連接,實現通信

#include "rs485.h"

void RS485_Config(uint32_t brr)
{
	GPIO_InitTypeDef GPIO_InitStruct;
	USART_InitTypeDef USART_InitStruct;
	//打開時鐘  PB PC USART3
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB|RCC_APB2Periph_GPIOC,ENABLE);
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART3,ENABLE);
	//PB10 配置爲 複用 推輓 無上下
	GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF_PP;  //推輓輸出
	GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz; 
	GPIO_InitStruct.GPIO_Pin = GPIO_Pin_10;
	GPIO_Init(GPIOB,&GPIO_InitStruct);	 //GPIO初始化
	//PB11 配置爲 浮空輸入
	GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IN_FLOATING;  //推輓輸出
	GPIO_InitStruct.GPIO_Pin = GPIO_Pin_11;
	GPIO_Init(GPIOB,&GPIO_InitStruct);	 //GPIO初始化
	//PC9
	GPIO_InitStruct.GPIO_Mode = GPIO_Mode_Out_PP;  //推輓輸出
	GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz; 
	GPIO_InitStruct.GPIO_Pin = GPIO_Pin_9;
	GPIO_Init(GPIOC,&GPIO_InitStruct);	 //GPIO初始化
	//配置串口
	//232協議  1+8+0+1
	USART_InitStruct.USART_BaudRate = brr;
	USART_InitStruct.USART_Parity =  USART_Parity_No;//禁止奇偶檢驗
	USART_InitStruct.USART_WordLength = USART_WordLength_8b;//數據位:8位
	USART_InitStruct.USART_StopBits = USART_StopBits_1;//停止位:1位
	USART_InitStruct.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;//發送,接收使能
	USART_InitStruct.USART_HardwareFlowControl = USART_HardwareFlowControl_None;//無硬件控制流
	USART_Init(USART3,&USART_InitStruct);
	USART_Cmd(USART3,ENABLE);
	Usart3_RxNVICConfig();
	//配置爲接收器
	RS485_RE = RS485_ModeRx;
}

void Usart3_RxNVICConfig(void)
{
	NVIC_InitTypeDef NVIC_InitStruct;
	//接收中斷
	USART_ITConfig(USART3,USART_IT_RXNE,ENABLE);
	NVIC_InitStruct.NVIC_IRQChannel = USART3_IRQn;
	NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE; //中斷通道使能
	NVIC_InitStruct.NVIC_IRQChannelSubPriority = 0;//次級
	NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = 1;//佔先
	NVIC_Init(&NVIC_InitStruct);//初始化 NVIC 寄存器
}

void RS485_Echo(void)
{
	u8 ch;
	//配置爲接收器
	RS485_RE = RS485_ModeRx;
//	USART3->CR1 &=~ (1<<2);
	//接收數據 -- 判斷是否接收到數據
	while(USART_GetFlagStatus(USART3,USART_FLAG_RXNE)!=SET);
	//保存數據
	 ch=USART3->DR;
	//配置發送器
	RS485_RE = RS485_ModeTx;
	//發送數據
	USART3->DR = ch;
	//判斷數據是否發送完成
	while(USART_GetFlagStatus(USART3,USART_FLAG_TC)!=SET);//等待發送結束
	
//	u8 da = 0;
//	if((USART3->SR & (1<<5)) != 0)
//	{
//			da = USART3->DR;
//			USART3->CR1 &= ~(1<<2);
//			GPIOC->ODR |=(0x01<<9);//DE 發送器輸出使能(高電平有效)
//			__NOP();__NOP();__NOP();__NOP();__NOP();
//			 
//			USART3->DR = da;
//			while((USART3->SR & (1<<6)) == 0);
//			GPIOC->ODR &=~(0x01<<9);//RE 接收器輸出使能(低電平有效)
//			__NOP();__NOP();__NOP();__NOP();__NOP();
//			USART3->CR1 |= (1<<2);
//	}
}

void RS485_MoreEcho(void)
{
	u8 ch[5],i=0;
	//配置爲接收器
	RS485_RE = 0;
	for(i=0;i<5;i++)
	{
		//接收數據 -- 判斷是否接收到數據
		while(USART_GetFlagStatus(USART3,USART_FLAG_RXNE)!=SET);
		//保存數據
		 ch[i]=USART3->DR;
	}
	//配置發送器
	RS485_RE = 1;
	for(i=0;i<5;i++)
	{
		//發送數據
		USART3->DR = ch[i];
		//判斷數據是否發送完成
		while(USART_GetFlagStatus(USART3,USART_FLAG_TC)!=SET);//等待發送結束
	}
}

485與232有很多相似之處,我本來打算寫modbus,最後想想還是決定寫寫485,不能因爲簡單就放輕鬆,也算是加深自己的認識,讓我們一起加油。

基於STM32f103的紅外接收發送

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章