學習於:野火stm32視頻教程

CAN是用在汽車匯流排中,RS485是用在工業現場環境中。特定是傳輸距離遠,抗干擾能力強

485由232協議改進而來,協議層不變,只是改進了物理層,因此保留了串口通訊協議應用簡單的特點。

節點之間的連接示意圖如下所示:

即A接A,B接B。

A,B出來的是差分信號,這樣差距比較大,所以才會有前面說的特點:抗干擾能力強、傳輸距離遠。

一般來說,封裝好的485是這樣的:

也就是把電阻也加入進去,然後流出兩根線 A和B。

這裡注意:使用485收發器後,全雙工變成了半雙工。這樣的話編程方式就會有所改變

下面是一個簡單的比較:

注意:差分、距離、多設備互相通訊

RS-485 網路只有一對差分信號線,它使用差分信號來表達邏輯,當 AB 兩線間的電壓差 為-6V~-2V 時表示邏輯 1,當電壓差為+2V~+6V 表示邏輯 0,在同一時刻只能表達一個信 號,所以它的通訊是半雙工形式的

火哥這裡是A與A相連,B與B相連就OK了。沒有接相互的GND

然後來看晶元的使用方法:

先看晶元的輸入,即單片機這邊只需要控制三個引腳,兩個是txd,rxd, 還有一個引腳CS控制半雙工的收發。編寫程序的思路就是要發送數據的時候,把CS置為高電平,然後通過串口發送數據。發送完數據之後,馬上把引腳置為低電平,這樣就時刻處於接收數據的狀態了。(這裡記得配置這個cs引腳為推挽輸出模式啊,還有開啟時鐘之類的,就像配置led這樣,還有就是控制CS引腳的電平變化的時候,需要加上一定的延時,不然數據可能還未發送出去,然後你就改變引腳狀態,那麼數據就可能會發送失敗之類的

這是火哥的設計。

下面這個是max485的輸入:

輸入高電平發送數據,低電平接收數據。

而我們實驗板中使用的是ADM2687E 。其實都差不多,也就是一個485收發器。

然後是晶元的輸出,由前面的示意圖也可以知道只有A,B兩根線。

下面是max485的示意圖:

5V <--->C/4-5V 這是單片機這邊的接線,5v是給晶元供電的。

RX <--->485_R

TX <--->485_D

DE/RE <--->PD11 這個就是前面提到的控制接收的CS端

輸出的右邊的 1,2對應的就是A,B兩線了。

實物如下:

然後我先是進行開發板和電腦的通信,這裡由於電腦沒有485晶元,所以買了個USB轉RS485的模塊。接線就是單獨引出485的A,B兩根線即可,如下:(下面只接了兩根線)

然後是程序: 值得注意的就是下面這個了

和串口發送差不多,不過就是發送前和發送後加上一些小操作。

完整代碼可以去論壇找火哥的F429的固件庫常式里的RS485通訊實驗代碼,這裡就不重複上傳了。

常式里的是單片機與單片機之間的485通信,而我這裡是單片機的電腦的485通信,都是一樣的。常式的主要功能就是發送0到256到電腦中,然後把電腦發送過來的數據通過另一個串口列印到電腦上。

下面是實驗現象:

下面是485的串口

觀察可以得知,這個軟體是使用了一種中文編碼方式,但是不可以選。估計可能是系統的GBK編碼吧,反正我們得知了 數據是正常發送到電腦中(0-9 a-z A-Z....) 這裡注意,有時候會不斷地出現亂碼,這個可以考慮 zhidao.baidu.com/questi 這裡說最好是共地,可是我共地後還是有這種亂碼出現,然後懷疑可能是杜邦線連接的問題,但是由於器件問題,這裡就暫時不考慮這個亂碼先了。

然後是電腦發送數據到單片機,這裡由於一開始的程序里是要達到250個位元組才列印出來,所以比較尷尬,後面進行了修改,收到5個位元組就列印出來。

下面是單片機的串口:

下面是16進位顯示:

控制返回:

最後的正常輸出:

下面是另一次485通信的記錄:

先是開發板:

接線如下:

接電腦的是usb轉485模塊。

這裡經過實驗,接A,B兩根線即可,接gnd也沒啥影響,按理說是最好接三根線。可是我用了兩根線沒出現啥問題。

然後是程序:

然後是現象:

下面是32的調試串口的輸出:

下面是usb轉485的模塊的串口:

發送的是0-ff的16進位數據。 這裡接收了兩次數據,一次用16進位顯示,一次用串口的默認編碼進行顯示,按理說是平台默認的gbk編碼。、

然後又試了另一根usb轉485的介麵線,

接線如下:

結果如下:

一切ok。

然後是到實驗板和電腦的485通訊了:(前面是野火的開發板,現在是自製的實驗板)

在這裡極力吐槽一下:這個swd下載方式的時候,感覺需要一個規範啊,不然那幾根線的連接順序都是按自己的意願設置,這樣就都是自己杜邦線連接,總是容易鬆動,就很難受,每次下載到按著線。。。

首先來看我們的實驗板:

PC6對應的是標號為TXD2,PC7對應的是RXD2 ,PC8對應的就是控制485收發的信號了 。注意,這裡並不是32的串口2,這只是altium designer里的一個網路標號而已。

RXD2接的是ADM2687E的RXD,TXD2同理。

ADM2687E的輸出的A接的是9孔的7腳,B接的是8腳。

(注意,這裡的9孔串口集成了232和485轉換晶元,所以可同時進行兩種方式的傳輸)

參考: STM32官方手冊 中的 STM32F4xx中文數據手冊.PDF

PC6對應的是串口6的TX端,PC7對應的是串口6的RX端。這裡才是單片機的串口號。

上圖在第18頁

這裡要注意他們的時鐘信號。串口1和串口6都是掛載在APB2上的,其它的串口都是掛載在APB1上的。 這裡容易寫錯!在stm32f4xx.rcc.h文件中又定義,如下:

然後開始修改代碼:

首先,修改按鍵的GPIO。這裡使用實驗板的K1按鍵,對應PH10. 按下按鍵即為低電平。

由於火哥封裝地很好了,所以很多時候我們只需要修改頭文件即可,但是不知道為啥這裡設置了另一個按鍵,估計火哥也是複製過來地,所以這裡直接刪除,避免和實驗板電路衝突。

感覺開著分屏模式來修改比較好,推薦一下。(把文件拉過去選擇verical即可)

然後是led,這裡就不需要led了,所以直接刪除led部分。

接著是修改串口文件,由於調試的串口都是實驗的串口1,所以這裡就不進行修改了,而且前面也調試過了,success。 所以現在是修改前面提到的485的串口以及控制線

這裡先簡單介紹一下使用的485收發器: ADM2687E

引腳說明:

介紹這個的原因是要知道半雙工的它什麼時候收,什麼時候發:

極力吐槽這個9孔中同時集合232和485兩種方式的通訊,根本不方便調試,拿杜邦線接是最難受的,很不穩定。也不方便拔出來。

這裡犯了一個很大的錯誤:

在 stm32f4xx_usart.c 文件中調用printf函數,這樣就導致了printf函數的反覆調用,然後就程序死了,相當於系統崩潰這樣。。非常尷尬。。。現象就是串口功能無效。

然後修改之後進行調試:

一直停留在reset當中,說明485串口的數據並未發送出去。。

說明:此時發送數據寄存器不為空。

基礎:使用 USART_GetFlagStatus函數來獲取USART 事件標誌來實現發送完成功能等待,它接收兩個參數,一個是 USART,一個是事件標誌。 這裡我們循環檢測發送數據寄存器為空這個標誌,當跳出 while 循環時說明發送數據寄存 器為空這個事實。

然後拔掉接線485,發現情況一致,說明此時可能是485的A,B兩線接觸不良或者接錯了。或者是之前就有問題了。可以參考: zhuanlan.zhihu.com/p/65 進行解決。即是時鐘線得配置問題。

然後又遇到一個問題:如下圖

即發送數據不正確,接收數據也不正確。 或者說根本就沒接收或發送,而這只是電平得晃動導致得單碼輸出。

類似如下:

串口轉485得指示燈:

右邊綠燈為發,左邊黃燈為收。

左邊為沒接usb轉485的正確情況,右邊是實驗板情況。由此可見,還是串口6的配置有問題,還極有可能是中斷方面的問題。

即每按一次按鍵,就會產生一次接收中斷。然後調試按鍵裡面運行的程序。

去掉這兩個之後,有:

也就是說,是rx_en和txen引起的串口6中斷。按理說應該是串口6接收到數據的時候產生接收中斷的。

很明顯,沒有_485_RX_EN()就不會觸發串口6中斷的。

然後,這說明 沒有 _485_TX_EN(); 就不會觸發。

兩個都在就觸發了串口6的接收中斷。

啊啊

開機後總會自動觸發接收中斷。

換了一個re引腳就不會觸發串口6的中斷了。

所以,現在結果就是: 串口6 pc6,pc7引腳接485收發器的收發引腳,pc8接控制引腳.但是現在pc8可以的置位複位可以引起串口6的接收中斷,並且返回的數據為0.

然後我就換了一個引腳:既然pc8可以引起接收數據的中斷,那麼,我就把它改為串口的接收引腳。

實物連接圖如下:(232用於調試,485用於通信,dap還用杜邦線接,難以想像這有多坑比,每次下載都按著線頭,還不一定找得到設備)

程序如下:(這裡已經不是大家所認識的串口6了)

#define _485_USART USART6
#define _485_USART_CLK RCC_APB2Periph_USART6
#define _485_USART_BAUDRATE 115200

#define _485_USART_RX_GPIO_PORT GPIOC
#define _485_USART_RX_GPIO_CLK RCC_AHB1Periph_GPIOC
#define _485_USART_RX_PIN GPIO_Pin_8
#define _485_USART_RX_AF GPIO_AF_USART6
#define _485_USART_RX_SOURCE GPIO_PinSource8

#define _485_USART_TX_GPIO_PORT GPIOC
#define _485_USART_TX_GPIO_CLK RCC_AHB1Periph_GPIOC
#define _485_USART_TX_PIN GPIO_Pin_6
#define _485_USART_TX_AF GPIO_AF_USART6
#define _485_USART_TX_SOURCE GPIO_PinSource6

#define _485_RE_GPIO_PORT GPIOC
#define _485_RE_GPIO_CLK RCC_AHB1Periph_GPIOC
#define _485_RE_PIN GPIO_Pin_7

#define _485_INT_IRQ USART6_IRQn
#define _485_IRQHandler USART6_IRQHandler

下面是主程序:

下面是485串口:

下面是232串口:

不過有一個問題就是開機後總是會自動按下按鍵,然後觸發數據發送。連續三次。然後是這裡不能通過485接收數據。只能發送數據。

猜測:莫非這裡是由於tx引腳配置正確,也就是pc6是正確的,然後pc7也是正確的收發控制端。就pc8不是接收引腳,所以才導致了這個問題?

然後試了另一種配置pc5為rx,pc6為tx,pc7為控制端。

不能發送數據也不能接收數據,說明我們脫離pc8的猜想是錯的。

然後另一種嘗試:rx-pc6,tx-pc8, ec-pc7 現象如下:

情況和第一種一樣,也就是說第一和第三種情況一樣,能向485發送數據,但是不能接收485發送過來的數據,也就是不能引起串口6中斷。

然後是第四種配置:pc7為rx,pc8為tx,pc6為en

結果就是485這邊收到的數據都是0 。和前面一樣的情況。

值得注意的是這裡一開始會進入接收中斷。。

然後再嘗試另一種配置:pc6-rx pc 7-tx pc8-en

每按一次都可以進入接收中斷。

8--7--6

往485發送或者接收都是返回一個0

7-6-8

現在是只要8和6在txd和rxd的引腳上,那麼就能向485模塊發送數據。但是不能接收數據。那個使能引腳是什麼都無所謂。簡直心態爆炸。。。

然後發現:

把這兩個引腳都不需要,還是可以向485發送數據,心態更加爆炸了。

啊啊

寫著升級固件的板子是需要升級4g模塊的固件的。所以4g模塊不能使用,但是其它模塊都能正常使用。 沒有寫的則是可以使用全部功能。


推薦閱讀:
相关文章