某日,一工程師咨詢在使用STM32F407 MCU開發(fā)產(chǎn)品時(shí)用到UART5和USART6做串行異步通信,將二者波特率配置為1200bps時(shí),發(fā)現(xiàn)UART5正常,而USART6工作不正常。
咋聽起來的確有點(diǎn)奇怪。懷疑其相關(guān)配置有問題,查看代碼并無異常,而且當(dāng)波特率調(diào)高時(shí),二者都表現(xiàn)正常。這基本斷定代碼配置沒有邏輯或流程上的錯(cuò)誤。
結(jié)合技術(shù)手冊來看,UART5與USART6的差別主要體現(xiàn)在掛在不同的外設(shè)總線上,UART5掛在APB1上,USART6掛在APB2總線上。對于32f407而言,APB1最高時(shí)鐘42M, APB2最高時(shí)鐘可達(dá)84M。

經(jīng)進(jìn)一步了解,客戶系統(tǒng)的APB1總線時(shí)鐘工作在42M,APB2總線時(shí)鐘工作在84M?蛻艄こ處熓褂ST官方參考固件庫進(jìn)行開發(fā)。如果利用庫來開發(fā)的話,對于UART波特率的設(shè)定,只需要在相應(yīng)變量位置填入你期望的波特率數(shù)值即可,至于具體的寄存器配置是通過庫函數(shù)調(diào)用實(shí)現(xiàn)的。用固件庫操作的話,工程師往往并沒怎么在意這個(gè)實(shí)現(xiàn)過程。
USART_InitStructure.USART_BaudRate = 115200;
USART_InitStructure.USART_WordLength = USART_WordLength_8b;
USART_InitStructure.USART_StopBits = USART_StopBits_1;
USART_InitStructure.USART_Parity = USART_Parity_No;
USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
USART_Init(USARTx, &USART_InitStructure);
這里有必要看看關(guān)于STM32F407 UART的波特率的設(shè)置及實(shí)現(xiàn)。UART的波特率具體是 通過USART_BRR寄存器來配置實(shí)現(xiàn)的,具體是用USARTDIV來設(shè)置。
關(guān)于波特率、外設(shè)時(shí)鐘、USART_BRR的配置參數(shù)有如下關(guān)系式:
上圖算式中OVER8取0或1,8 x( 2-OVER8) 分別代表過采樣的外設(shè)時(shí)鐘個(gè)數(shù)16或8。Fck表示UART所對應(yīng)的外設(shè)時(shí)鐘【APB1或APB2】,USARTDIV就是對應(yīng) 某波特率和外設(shè)時(shí)鐘及過采樣情況下要填入USART_BRR寄存器中的數(shù)字。
結(jié)合上面的計(jì)算,這個(gè)USARTDIV很可能就不是整數(shù),可能是帶小數(shù)的數(shù)字,這正好滿足USART_BRR內(nèi)部寄存器內(nèi)部的2部分設(shè)計(jì),DIV_MANTISSA【11:0】和DIV_Fraction【3:0】。DIV_MANTISSA放USARTDIV的整數(shù)部分,DIV_Fraction放USARTDIV的小數(shù)部分。當(dāng)然,放入DIV_Fraction的數(shù)字是將小數(shù)部分折算成多少個(gè)采樣時(shí)鐘個(gè)數(shù)后來存放的。具體細(xì)節(jié)請查看stm32f4系列參考手冊相關(guān)部分,這里不細(xì)化了。
細(xì)心的人可能會發(fā)現(xiàn),因?yàn)?font face="Times New Roman">USART_BRR寄存器的整數(shù)部分DIV_MANTISSA【11:0】是12位,加上小數(shù)部分,USARTDIV最大只能為4096。顯然,根據(jù)上面算式不難理解在外設(shè)頻率一定、采樣頻率一定的情況下,那個(gè)波特率的設(shè)計(jì)值是有一定范圍的,并不能隨意地天馬行空。不然,你所需要的USARTDIV根本沒法在USART_BRR寄存器中實(shí)現(xiàn)。
講到這里,大家或許明白了為什么會出現(xiàn)文章開頭提出的疑問。我們可以核實(shí)下,此時(shí)UART5的APB1總線時(shí)鐘42M,假如過采樣為16、波特率為1200的話,可以算得此時(shí)的USARTDIV 為2187.5;而UART6此時(shí)的APB2總線時(shí)鐘為84M,同樣假如過采樣為16,波特率1200的話,不難算得此時(shí)的USARTDIV為 4375,顯然4375遠(yuǎn)超出USART_BRR寄存器中USARTDIV所能實(shí)現(xiàn)的數(shù)據(jù)范圍了。如果通過調(diào)用庫函數(shù)做黑匣子式地修改USART_BRR的話,就會導(dǎo)致實(shí)際配置的波特率跟期望值大相徑庭而不不自知。
既然知道原因就好辦了,可結(jié)合產(chǎn)品應(yīng)用需求具體調(diào)整來解決該問題,比方調(diào)整UART口或者調(diào)整APB2的工作時(shí)鐘等。