17.1 485協(xié)議概述
485是屬于OSI模型物理層的電氣標(biāo)準(zhǔn),屬于2線制,半雙工,多點(diǎn)通信標(biāo)準(zhǔn),485總線采用兩根線路的電壓差來(lái)傳遞信號(hào),485兩根線路名稱為A和B,當(dāng)線路A與線路B的電壓差為+2 +6V時(shí)表示邏輯電平1,當(dāng)線路A與線路B的電壓差為-2 -6V時(shí)表示邏輯電平0,485與232協(xié)議都屬于串口通信協(xié)議,都是采用轉(zhuǎn)換芯片將USART接口電平轉(zhuǎn)換為485電平或者232電平,485協(xié)議傳輸速率在10米時(shí)候可達(dá)35Mbps,在1200米是可達(dá)到100Kbps,最大支持總線掛載32個(gè)節(jié)點(diǎn),如果采用特制的芯片可以達(dá)到400個(gè)節(jié)點(diǎn)。
485電氣連接中,為了進(jìn)行阻抗匹配,需要在兩根線路中并聯(lián)一個(gè)120Ω的電阻,一般是一個(gè)設(shè)備并聯(lián)一個(gè),所以485協(xié)議只是之前USART協(xié)議的另一種表現(xiàn)形式,通過(guò)之前掌握的USART配置,借助485轉(zhuǎn)換芯片就可以完成485通信線路的搭建。
17.2 實(shí)驗(yàn)例程
采用STM32F103ZET6芯片的PA2(USART2_TXD)和PA3(USART2_RXD)和一個(gè)485轉(zhuǎn)換芯片SP485來(lái)實(shí)現(xiàn)RS485通信。其中SP485引腳描述如下圖所示。
序號(hào) | 名稱 | 功能描述 |
---|---|---|
1 | RO | 接收器輸出端:當(dāng)RE為低電平時(shí),若A-B≧200mV,RO輸出為高電平若A-B≦-200mV,RO輸出為低電平 |
2 | RE | 接收器輸出使能控制當(dāng)RE接低電平時(shí),接收器輸出使能,RO輸出有效當(dāng)RE接高電平時(shí),接收器輸出禁能,RO為高阻態(tài)RE接高電平且DE接低電平時(shí),器件進(jìn)入低功耗關(guān)斷模式 |
3 | DR | 驅(qū)動(dòng)器輸出使能控制DE接高電平時(shí)驅(qū)動(dòng)器輸出有效,DE為低電平時(shí)輸出為高阻態(tài)RE接高電平且DE接低電平時(shí),器件進(jìn)入低功耗關(guān)斷模式 |
4 | DI | DI驅(qū)動(dòng)器輸入DE為高電平時(shí),DI上的低電平使驅(qū)動(dòng)器同相端輸出為低電平,反相端輸出為高電平DI上的高電平將使同相端輸出為高電平,反相端輸出為低 |
5 | GND | 電源地 |
6 | A | 接收器同相輸入和驅(qū)動(dòng)器同相輸出端 |
7 | B | 接收器反相輸入和驅(qū)動(dòng)器反相輸出端 |
8 | VCC | 電源,推薦3.3V |
根據(jù)上面的芯片描述,我們可以得到連接如下所示。
USART2_TXD(即PA2)接RO端
USART2_RXD(即PA3)接DI端
PD7接DR與RE端
(1)創(chuàng)建rs485.h文件,輸入以下代碼。
/*********************************************************************************************************
RS485 驅(qū) 動(dòng) 文 件
*********************************************************************************************************/
#ifndef _RS485_H_
#define _RS485_H_
#include "sys.h"
/*********************************************************************************************************
硬 件 端 口 定 義
*********************************************************************************************************/
#define RS485_EN PDout( 7 )
/*********************************************************************************************************
數(shù) 據(jù) 結(jié) 構(gòu) 定 義
*********************************************************************************************************/
typedef struct
{
u8 Buffer[ 255 ] ;
u8 Len ;
}Communication_Data;
extern Communication_Data RS485_Data;
/*********************************************************************************************************
函 數(shù) 列 表
*********************************************************************************************************/
void RS485_Init( u32 pclk1,u32 bound ) ; //RS485初始化
void RS485_Send_Data( u8 *buf, u8 len ) ; //發(fā)送n個(gè)字節(jié)
void RS485_Receive_Data( u8 *buf, u8 *len ) ; //接收n個(gè)字節(jié)
#endif
(2)創(chuàng)建rs485.c文件,輸入以下代碼。
#include "rs485.h"
#include "delay.h"
Communication_Data RS485_Data;
/***************************************************
Name :USART2_IRQHandler
Function :串口2中斷服務(wù)函數(shù)
Paramater :None
Return :None
***************************************************/
void USART2_IRQHandler()
{
//接收到數(shù)據(jù)
if( USART2->SR&( 1<<5 ) )
{
RS485_Data.Buffer[ RS485_Data.Len ] = USART2->DR ; //記錄接收到的值
RS485_Data.Len ++ ; //接收數(shù)據(jù)增加1
}
}
/***************************************************
Name :RS485_Send_Data
Function :接收n個(gè)字節(jié)
Paramater :
*buf:接收區(qū)首地址
len:讀取的字節(jié)數(shù)
Return :None
***************************************************/
void RS485_Receive_Data( u8 *buf, u8 *len )
{
u8 i, rxlen=RS485_Data.Len ;
delay_ms( 10 ) ; //連續(xù)超過(guò)10ms沒有接收到一個(gè)數(shù)據(jù),則認(rèn)為接收結(jié)束
//接收到了數(shù)據(jù),且接收完成了
if( ( rxlen==RS485_Data.Len )&&( rxlen!=0 ) )
{
for( i=0; iSR&0x40 )==0 ) ;//等待發(fā)送結(jié)束
USART2->DR = buf[ t ] ;
}
while( ( USART2->SR&0x40 )==0 ) ; //等待發(fā)送結(jié)束
RS485_Data.Len = 0 ;
RS485_EN = 0 ; //設(shè)置為接收模式
}
/***************************************************
Name :RS485_Init
Function :RS485初始化
Paramater :
pclk1:PCLK1時(shí)鐘頻率
bound:波特率
Return :None
***************************************************/
void RS485_Init( u32 pclk1, u32 bound )
{
float temp ;
u16 mantissa, fraction ;
temp = ( float )( pclk1*1000000 )/( bound*16 ) ; //得到USARTDIV
mantissa = temp ; //得到整數(shù)部分
fraction = ( temp-mantissa )*16 ; //得到小數(shù)部分
mantissa <<= 4 ;
mantissa += fraction ;
RCC->APB2ENR |= 1<<5 ; //使能PD口
GPIOD->CRL &= 0x0FFFFFFF ;
GPIOD->CRL |= 0x30000000 ;
RCC->APB2ENR |= 1<<2 ; //使能PA口
GPIOA->CRL &= 0xFFFF00FF ; //IO狀態(tài)設(shè)置
GPIOA->CRL |= 0x00008B00 ; //IO狀態(tài)設(shè)置
RCC->APB1ENR |= 1<<17 ; //使能串口時(shí)鐘
RCC->APB1RSTR |= 1<<17 ; //復(fù)位串口2
RCC->APB1RSTR &= ~( 1<<17 ) ; //停止復(fù)位
//波特率設(shè)置
USART2->BRR = mantissa ; //波特率設(shè)置
USART2->CR1 |= 0x200C ; //1位停止,無(wú)校驗(yàn)位
USART2->CR1 |= 1<<8 ; //PE中斷使能
USART2->CR1 |= 1<<5 ; //接收緩沖區(qū)非空中斷使能
NVIC_Init( 3, 3, USART2_IRQn, 2 ) ; //組2
RS485_EN = 0 ; //默認(rèn)為接收模式
}
(3)創(chuàng)建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時(shí)鐘初始化
SysTick_Init( 72 ) ; //SysTick初始化
USART1_Init( 72, 115200 ) ; //初始化串口1波特率115200
RS485_Init( 36, 9600 ) ; //初始化RS485
RS485_Send_Data( "RS485 Test", 10 ) ; //發(fā)送數(shù)據(jù)
while( 1 )
{
RS485_Receive_Data( datatemp, &len ) ;
delay_ms( 10 ) ;
}
}
-
電壓
+關(guān)注
關(guān)注
45文章
5539瀏覽量
115490 -
物理層
+關(guān)注
關(guān)注
1文章
147瀏覽量
34268 -
OSI
+關(guān)注
關(guān)注
0文章
74瀏覽量
15394
發(fā)布評(píng)論請(qǐng)先 登錄
相關(guān)推薦
評(píng)論