STM32-RS485通信軟硬件實現


OS:Windows 64

Development kit:MDK5.14

IDE:UV4

MCU:STM32F103C8T6/VET6

AD:Altium Designer 18.0.12

1、RS485簡介 

  RS-485又名TIA-485-A, ANSI/TIA/EIA-485或TIA/EIA-485。
  RS485是一個定義平衡數字多點系統中的驅動器和接收器的電氣特性的標准,該標准由電信行業協會和電子工業聯盟定義。使用該標准的數字通信網絡能在遠距離條件下以及電子噪聲大的環境下有效傳輸信號。RS-485使得廉價本地網絡以及多支路通信鏈路的配置成為可能。RS485接口組成的半雙工網絡,一般是兩線制(以前有四線制接法,只能實現點對點的通信方式,現很少采用),多采用屏蔽雙絞線傳輸。這種接線方式為總線式拓撲結構在同一總線上最多可以掛接32個結點。在RS485通信網絡中一般采用的是主從通信方式,即一個主機帶多個從機。很多情況下,連接RS-485通信鏈路時只是簡單地用一對雙絞線將各個接口的“A”、“B”端連接起來。RS485接口連接器采用DB-9的9芯插頭座,與智能終端RS485接口采用DB-9(孔),與鍵盤連接的鍵盤接口RS485采用DB-9(針)。
  在低速、短距離、無干擾的場合可以采用普通的雙絞線,反之,在高速、長線傳輸時,則必須采用阻抗匹配(一般為120Ω)的RS485專用電纜(STP-120Ω(用於RS485 & CAN)一對18AWG),而在干擾惡劣的環境下還應采用鎧裝型雙絞屏蔽電纜(ASTP-120Ω(用於RS485 & CAN)一對18AWG)。

2、RS485特性

  • RS-485的電氣特性:邏輯“0”以兩線間的電壓差為+(2—6)V表示;邏輯“1”以兩線間的電壓差為-(2—6)V表示。接口信號電平比RS-232降低了,就不易損壞接口電路的芯片,且該電平與TTL電平兼容,可方便與TTL電路連接
  • RS-485的數據最高傳輸速率為10Mbps
  • RS-485接口是采用平衡驅動器和差分接收器的組合,抗共模干擾能力增強,即抗噪聲干擾性好
  • RS-485接口的最大傳輸距離標准值為4000英尺(約1219米),實際上可達3000英尺,另外RS-232接口在總線上只允許連接1個收發器,即單站能力。而RS-485接口在總線上是允許連接多達128個收發器。即具有多站能力,這樣用戶可以利用單一的RS-485接口方便地建立起設備網絡。

3、RS485通信硬件實現

  博主使用的485芯片為MAX3485,實現半雙工通信。應用電路如下圖:

 

 

  R6為120歐的阻抗匹配電阻,如果長距離通信的話,一定要在最后一個節點接上這一個電阻;但是短距離通信的話焊上R6反而出錯(博主在實驗中發現,焊上匹配電阻后,主從節點通信異常,調試發現大量的00字節在自動收發),因此建議大家先不要焊上,但是在電路設計時保留。RXD485、TXD485分別接控制芯片的USART1_RX、USART1_TX(串口號可自行選擇,這里使用串口1),此外;485C接芯片的PA4引腳(隨意選擇)用以切換485的通信狀態。J1、J2為兩個JST接口,方便485通信線路的連接,由於是從節點因而留出兩個。以下為其余連接電路:

 

MAX3485通信指示        

4、RS485通信軟件實現

 1 #include "sys.h"
 2 #include "stdio.h"
 3 
 4 #define        USART1_RX_LEN      50           //接收最大字節
 5 #define        USART1_TX_LEN      50           //發送最大字節
 6 #define     RS485_TX_EN        PAout(4)
 7 
 8 
 9 extern  u8 USART1_RX_Buf[USART1_RX_LEN];  //接收緩沖
10 extern  u8 USART1_TX_Buf[USART1_TX_LEN];  //發送緩沖
11 extern  u8 USART1_RX_Data_Len;           //實際接收數據字節長度
12 extern  u8 USART1_TX_Data_Len;           //待發送數據字節長度
13 extern  u8 USART1_RX_Flag;               //是否收到數據
14 
15 void RS485_Config(u32 bound); 16 void USART1_IRQHandler(void); 17 void RS485_Send_Data(u8 *buf,u8 len);
485.h
 1 #include "sys.h"
 2 #include "delay.h"
 3 #include "rs485.h"
 4 
 5 u8 USART1_RX_Buf[USART1_RX_LEN];  //接收緩沖
 6 u8 USART1_TX_Buf[USART1_TX_LEN];  //發送緩沖
 7 u8 USART1_RX_Data_Len = 0;        //實際接收數據字節長度
 8 u8 USART1_TX_Data_Len = 0;        //待發送數據字節長度
 9 u8 USART1_RX_Flag = 0;            //串口1是否接收完數據 
10 
11 void USART1_IRQHandler(void) 12 { 13  u8 res; 14     if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET) //接收到數據
15  { 16         res =USART_ReceiveData(USART1); //讀取接收到的數據
17         if(USART1_RX_Data_Len<USART1_RX_LEN) 18  { 19             USART1_RX_Buf[USART1_RX_Data_Len]=res; //記錄接收到的值
20             USART1_RX_Data_Len++; //接收數據增加 1
21  } 22         USART1_RX_Flag=1;   //串口1接收到數據
23  } 24 } 25 
26 void RS485_Config(u32 bound) 27 { 28  GPIO_InitTypeDef GPIO_InitStructure; 29  USART_InitTypeDef USART_InitStructure; 30  NVIC_InitTypeDef NVIC_InitStructure; 31     
32     /*********************配置串口1**************************/
33     
34     /* config USART1 clock */
35  RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1 , ENABLE); 36  RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA , ENABLE); 37     
38     /* USART1 GPIO config */
39     /* Configure USART1 Tx (PA.02) as alternate function push-pull *///TX
40     GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9; 41     GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;       //復用推挽輸出
42     GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; 43     GPIO_Init(GPIOA, &GPIO_InitStructure); 44     /* Configure USART1 Rx (PA.03) as input floating *///RX
45     GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10; 46     GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;  //浮空輸入
47     GPIO_Init(GPIOA, &GPIO_InitStructure); 48     
49     
50     
51     
52     /* USART1 mode config */
53     
54     USART_InitStructure.USART_BaudRate = bound; 55     USART_InitStructure.USART_WordLength = USART_WordLength_8b; 56     USART_InitStructure.USART_StopBits = USART_StopBits_1; 57     USART_InitStructure.USART_Parity = USART_Parity_No ; 58     USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None; 59     USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx; 60     USART_Init(USART1, &USART_InitStructure); 61     
62     /* USART1 接收中斷 */
63     NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn; //使能串口 2 中斷
64     NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 3; //先占優先級 3 級
65     NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2; //從優先級 2級
66     NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //使能外部中斷通道
67     NVIC_Init(&NVIC_InitStructure);//初始化 NVIC 寄存器
68     
69     USART_ITConfig(USART1, USART_IT_RXNE, ENABLE); //開啟中斷
70     USART_Cmd(USART1, ENABLE); //使能串口 71     
72     //USART_ClearFlag(USART1, USART_FLAG_TC);//清發送完成標志
73     
74     
75     /**********************配置485控制口*********************/
76 
77     GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4; 78     GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;   //推挽輸出 ,PA4,485Ctr
79     GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; 80     GPIO_Init(GPIOA, &GPIO_InitStructure); 81     GPIO_ResetBits(GPIOA, GPIO_Pin_4);        //設置為接收模式,默認接收
82     
83 } 84 
85 void RS485_Send_Data(u8 *buf,u8 len)       //發送完改為接收
86 { 87  u8 t; 88     RS485_TX_EN=1;//設置為發送模式
89     for(t=0;t<len;t++) 90  { 91         while(USART_GetFlagStatus(USART1, USART_FLAG_TC) == RESET); 92  USART_SendData(USART1,buf[t]); 93  } 94     while(USART_GetFlagStatus(USART1, USART_FLAG_TC) == RESET); 95     
96     USART1_RX_Data_Len=0; 97     RS485_TX_EN=0;//設置為接收模式 
98 }
485.c

  通過以上代碼我么們就能通過STM32的串口資源實現485的正常通信了。注意事項:

  • 初始化串口:RX設置為浮空輸入、TX設置為復用推挽輸出
  • 因為是從節點,默認為接收模式,485C初始化為低電平;主節點則相反。可根據需要修改
  • 每次發送或接收時都應切換通信狀態

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM