舉例說明兩者的區別和聯繫「什麼是比特率什麼是波特率」

通常用串口列印亂碼大多是因為串口波特率不對。那麼我們應該如何測量實際的波特率呢?在此之前,讓我們回顧一下波特率的概念。

怎麼測量實際的波特率、比特率?串口通訊協議用代碼怎麼驗證?

什麼是波特率和比特率?

比特率的英文是Bitrate,它表示每秒傳輸的二進位位數,單位為比特/秒(bit/s)。

波特率的英文是Baudrate,它表示每秒傳輸的碼元符號的個數,是衡量數據傳輸速率的指標。

碼元是通信信號調製的概念。具有相同時間間隔的符號通常用於表示通信中的二進位數。這種的信號稱為碼元。

在普通通信傳輸中,0V代表數字0,5V代表數字1,所以一個碼元可以代表0和1兩種狀態,所以一個碼元等於一個二進位位,波特率與比特率一致。

怎麼測量實際的波特率、比特率?串口通訊協議用代碼怎麼驗證?

如果0V、2V、4V和6V在通信傳輸中分別代表二進位數00、01、10和11,那麼每個碼元可以代表四種狀態,即兩個二進位位,因此碼元數是二進位位數的一半,此時波特率是比特率的一半。

因為在許多常見的通信中,例如串口通訊中,一個碼元代表兩種狀態,所以我們通常直接用波特率來表示比特率。

串口通訊協議

在串口通信的協議層,它規定了數據包的內容,由起始位、主數據、校驗位和停止位組成。通訊雙方的數據包格式應一致,才能正常收發數據。數據幀的組成如下:

怎麼測量實際的波特率、比特率?串口通訊協議用代碼怎麼驗證?

讓我們實際驗證數據幀是否真的是這樣,編寫以下代碼:

怎麼測量實際的波特率、比特率?串口通訊協議用代碼怎麼驗證?

代碼非常簡單,即使用串口連續向外發送數據0xAA(當然也可以發送其他數據)。我們的串口配置如下:

怎麼測量實際的波特率、比特率?串口通訊協議用代碼怎麼驗證?

我們可以用示波器或邏輯分析儀抓取實際信號,看數據是否符合上述格式。在這裡,我們用邏輯分析儀來捕捉usart1的傳輸信號線(TX):

怎麼測量實際的波特率、比特率?串口通訊協議用代碼怎麼驗證?

從實際結果中,我們可以看出它確實是按照幀格式發送的。有些人可能對此有所懷疑。在上面的數據幀的圖片中存在空閑狀態。這是什麼?空閑、空閑,當然不是在發送數據的狀態,我們把代碼改為:

怎麼測量實際的波特率、比特率?串口通訊協議用代碼怎麼驗證?

初始化完成後,只發送一個0XAA,邏輯分析儀捕獲的數據是:

怎麼測量實際的波特率、比特率?串口通訊協議用代碼怎麼驗證?

可見,空閑狀態是高電平。在前面的示例中,我們在while循環中發送了數據0XAA,因此沒有空閑狀態。

在這個實驗中,我們需要知道兩點是:

串口發送的數據首先是低位的。我們的單片機發送0XAA(10101010B),邏輯分析儀採集的有效數據為01010101b。

單片機的串口使用TTL電平,這是一個正的邏輯電平信號。邏輯分析儀採集的數據0對應實際電壓0~0.5V,數據1對應實際電壓2.4v~5V。

RS-232電平標準常與TTL電平標準相比較。例如,

怎麼測量實際的波特率、比特率?串口通訊協議用代碼怎麼驗證?

TTL電平標準常用於普通電子電路中。在理想狀態下,5V表示二進位邏輯1,0V表示邏輯0。為了提高串口通信的遠距離傳輸和抗干擾能力,RS-232電平標準用-15V表示邏輯1,+15V表示邏輯0。

在舊的台式計算機中,通常有一個RS-232標準的COM埠(也稱 DB9 介面):

怎麼測量實際的波特率、比特率?串口通訊協議用代碼怎麼驗證?

在這個示常式序中,我們將串口波特率設置為115200bps。在串口通信中,符號只由一個二進位數表示(即只有0 和 1兩種狀態),因此波特率和比特率是相等的。

比特率代表每秒傳輸的二進位位數,所以我們知道傳輸一比特數據的時間,我們能推導出波特率嗎?從邏輯分析儀上我們可以知道,發送一位數據的時間如下:

怎麼測量實際的波特率、比特率?串口通訊協議用代碼怎麼驗證?

發送一位數據的時間約為8.667us,因此可以計算出一秒鐘發送多少位數據:

計算出的波特率為115380bps,非常接近115200bps。最後,肯定是有一定的錯誤。這個錯誤的原因包括邏輯分析儀的質量和我們的測量環境。但這個誤差也在允許範圍內。您可以看到串口助手接收到的數據是否正確:

怎麼測量實際的波特率、比特率?串口通訊協議用代碼怎麼驗證?

可以看到接收到的數據是正確的,即波特率是正確的。

串口波特率對不上怎麼解決?

在實踐中。我們可能會遇到這樣情況,即代碼中配置的波特率與串口助手上設置的波特率相同,但仍然存在一個異常。

例如,如果我們向串口助手發送一個字元串,那麼應該顯示在串口助手上的字元串就被亂碼了。或者我們發送一個數據到串口助手,發現數據被移動了。

在這種情況下,大多數波特率都不對應,因此我們必須檢查底層文件。如果代碼中波特率計算相關值(時鐘)與實際情況不符,就會出現這樣的現象。例如,我的一位同事以前遇到過這種情況,這就是原因。

在使用STM32時,通常使用外部晶體振蕩器,如STM32F103系列。外置晶體振蕩器的輸入範圍為4~16mhz:

怎麼測量實際的波特率、比特率?串口通訊協議用代碼怎麼驗證?

經驗值一般為8MHz,而且一般的demo工程底層代碼里默認的也是設置為8MHz,比如:

怎麼測量實際的波特率、比特率?串口通訊協議用代碼怎麼驗證?

但是如果實際晶體振蕩器沒有粘貼8m,就會出現問題(例如串口波特率不正確)。追溯到源代碼,串口波特率被分配到USART_Init函數中的,打開這個函數:

怎麼測量實際的波特率、比特率?串口通訊協議用代碼怎麼驗證?

計算串口波特率需要一個apbclock變數,而這個值得來源從RCC_GetClocksFreq函數來,再打開這個函數:

怎麼測量實際的波特率、比特率?串口通訊協議用代碼怎麼驗證?

所以要注意的是,HSE_VALUE這個值要與實際做對應。

遇到這種問題找誰說理去。經驗就是不斷采坑不斷積累的一個過程,早點遇到坑可能也是一件好事。像類似底層的問題很少遇到,但是一旦遇到那就得比較棘手的問題了,需要很有耐心地去查找。

能用穩定的晶元是一件很幸福的事情,用不穩定、不成熟的晶元的時候,那個才是真的難啊,遇到問題真是讓人懷疑人生啊,軟體、硬體、晶元都可能有問題。

原創文章,作者:投稿專員,如若轉載,請註明出處:https://www.506064.com/zh-tw/n/287909.html

(0)
打賞 微信掃一掃 微信掃一掃 支付寶掃一掃 支付寶掃一掃
投稿專員的頭像投稿專員
上一篇 2024-12-23 13:41
下一篇 2024-12-23 13:41

相關推薦

發表回復

登錄後才能評論