定制制作網(wǎng)站哪家好惠州seo網(wǎng)站推廣
一、HAL_UART_Transmit和HAL_UART_Transmit_IT的區(qū)別
1. HAL_UART_Transmit_IT
(非阻塞模式):
HAL_UART_Transmit_IT
是非阻塞的傳輸函數(shù),也就是說(shuō),當(dāng)你調(diào)用 HAL_UART_Transmit_IT
時(shí),它不會(huì)等到數(shù)據(jù)完全發(fā)送完就返回控制權(quán)。它會(huì)啟動(dòng)一個(gè)中斷,通知你數(shù)據(jù)發(fā)送完成,允許你繼續(xù)執(zhí)行其他任務(wù)。這種方式是為了讓你在發(fā)送數(shù)據(jù)的過(guò)程中,能夠繼續(xù)處理其他操作,不會(huì)因?yàn)榈却龜?shù)據(jù)發(fā)送完成而阻塞。
由于數(shù)據(jù)傳輸是異步的,當(dāng)你調(diào)用 HAL_UART_Transmit_IT
時(shí),它會(huì)立即返回,而數(shù)據(jù)的發(fā)送是由硬件自動(dòng)完成的。為了保證數(shù)據(jù)完全發(fā)送完畢,你需要通過(guò)檢查標(biāo)志位(如 UART_FLAG_TC
)或等待 HAL_UART_TxCpltCallback
被調(diào)用來(lái)確認(rèn)數(shù)據(jù)傳輸已經(jīng)完成。
如下圖,需要通過(guò)標(biāo)志位判斷是否發(fā)送完成:
2. HAL_UART_Transmit
(阻塞模式):
HAL_UART_Transmit
是阻塞的傳輸函數(shù)。也就是說(shuō),當(dāng)你調(diào)用 HAL_UART_Transmit
時(shí),函數(shù)會(huì)阻塞,直到所有數(shù)據(jù)都被完全發(fā)送完畢。它會(huì)等待硬件完成數(shù)據(jù)的發(fā)送,并且只有在發(fā)送完成后才會(huì)返回。你不需要手動(dòng)檢查 UART_FLAG_TC
,因?yàn)楹瘮?shù)本身會(huì)等到發(fā)送完成才會(huì)退出。
3. 為什么 HAL_UART_Transmit_IT
需要判斷發(fā)送完成,而 HAL_UART_Transmit
不用?
-
非阻塞 vs 阻塞:
HAL_UART_Transmit_IT
是非阻塞的,它只啟動(dòng)發(fā)送過(guò)程并立即返回,你需要通過(guò)中斷回調(diào)或者標(biāo)志位來(lái)確定發(fā)送是否完成。由于它沒(méi)有等待數(shù)據(jù)發(fā)送完畢,因此你必須在發(fā)送后檢查是否已完成。 -
阻塞模式:
HAL_UART_Transmit
是阻塞的,函數(shù)內(nèi)部會(huì)等待直到數(shù)據(jù)完全發(fā)送完畢,所以你不需要手動(dòng)檢查發(fā)送是否完成。
4、示例
錯(cuò)誤示例:HAL_UART_Transmit_IT使用時(shí)沒(méi)有標(biāo)志位判斷中斷,導(dǎo)致數(shù)據(jù)被截?cái)?#xff0c;不能接收電腦發(fā)送的abc。
數(shù)據(jù)被截?cái)?#xff1a; 由于 HAL_UART_Transmit_IT
是非阻塞的,它啟動(dòng)了發(fā)送后立刻返回。這意味著在你啟動(dòng) str2
的發(fā)送后,可能很快就進(jìn)入了接收部分,而 UART 的發(fā)送緩沖區(qū)可能還沒(méi)有完全發(fā)送 str2
,此時(shí)如果你再次啟動(dòng)發(fā)送操作,就會(huì)中斷之前的發(fā)送,導(dǎo)致數(shù)據(jù)沒(méi)有完全傳輸。
正確操作:
或者
正確結(jié)果:
二、為什么串口發(fā)送不需要斷,而接收需要中斷
-
發(fā)送數(shù)據(jù):
- 串口數(shù)據(jù)發(fā)送是由軟件驅(qū)動(dòng)的過(guò)程。一般來(lái)說(shuō),數(shù)據(jù)發(fā)送到串口的寄存器中后,硬件會(huì)負(fù)責(zé)將其逐個(gè)字節(jié)發(fā)送出去。發(fā)送過(guò)程中,CPU 主要負(fù)責(zé)將數(shù)據(jù)寫(xiě)入寄存器或緩沖區(qū),而并不需要實(shí)時(shí)監(jiān)控每一個(gè)發(fā)送過(guò)程。
- 因?yàn)榘l(fā)送的速度通常比較穩(wěn)定且有足夠的時(shí)間來(lái)處理下一個(gè)字節(jié),CPU 可以通過(guò)簡(jiǎn)單的輪詢(Polling)方式來(lái)確保數(shù)據(jù)的發(fā)送。
- 串口發(fā)送過(guò)程中,硬件會(huì)根據(jù)串口設(shè)置(如波特率)自動(dòng)管理發(fā)送隊(duì)列。當(dāng)發(fā)送緩沖區(qū)空閑時(shí),CPU 只需要繼續(xù)寫(xiě)入數(shù)據(jù),或者使用中斷通知“數(shù)據(jù)發(fā)送完成”。
-
接收數(shù)據(jù):
- 接收數(shù)據(jù)是一個(gè)實(shí)時(shí)性的過(guò)程,硬件通過(guò)中斷來(lái)通知 CPU 什么時(shí)候有新的數(shù)據(jù)可以讀取。如果不使用中斷,CPU 就需要通過(guò)輪詢的方式不斷檢查串口接收緩沖區(qū)的狀態(tài)。這對(duì)于實(shí)時(shí)性要求較高的應(yīng)用來(lái)說(shuō)會(huì)增加負(fù)擔(dān),降低效率。
- 當(dāng)接收到一個(gè)字節(jié)數(shù)據(jù)時(shí),中斷可以直接通知 CPU 進(jìn)行處理。這使得接收數(shù)據(jù)更加及時(shí)和高效,避免了輪詢帶來(lái)的延遲和 CPU 資源浪費(fèi)。
接收中斷:
如下圖:
我們最開(kāi)始會(huì)開(kāi)啟中斷,注意:要使用中斷啟用函數(shù)(HAL_UART_Receive_IT)才能真正啟用中斷,原因我在前幾篇的文章有提到過(guò)。
這里啟用中斷后,UART一當(dāng)檢測(cè)到接受信號(hào)會(huì)進(jìn)入到中斷服務(wù)函數(shù)(HAL_UART_IRQHandler)
接著會(huì)進(jìn)入到回調(diào)函數(shù)(HAL_UART_RxCpltCallback),執(zhí)行我們想要的操作了,比如把數(shù)據(jù)放儲(chǔ)存起來(lái)。
注意:如果你接收后沒(méi)有操作,數(shù)據(jù)雖然接收了,但沒(méi)有儲(chǔ)存,會(huì)丟失。
我這里的回調(diào)函數(shù)是把數(shù)據(jù)放入到g_RecvChar中,如果我們要檢查數(shù)據(jù),就去這里面查找。
接收數(shù)據(jù)的讀取:你也可以不讀取,反正已經(jīng)按照你的要求放入容器中了
如上圖,我這UART1GetChar(&c)就是去讀取被放入容器里面的數(shù)據(jù)。