在STM32HAL庫(kù)里定義很多狀態(tài)變量,用于對(duì)各自外設(shè)模塊的狀態(tài)管理,比方ready,busy,idle,timeout,error等,以便正確使用各個(gè)外設(shè),避免使用上的混亂。
以usart為例,庫(kù)里為USART的發(fā)送、接收操作分別定義了兩個(gè)狀態(tài)變量,即gState和RxState。其中g(shù)State表示USART的發(fā)送狀態(tài),RxState表述接收時(shí)可能的狀態(tài)。
是ready還是busy或其它出錯(cuò)、超時(shí)狀態(tài)。USART初始化后gState為reddy狀態(tài),當(dāng)要調(diào)用UART發(fā)送函數(shù)時(shí)軟件將其設(shè)置為Busy.當(dāng)usart完成發(fā)送或中止發(fā)送時(shí),軟件將gState設(shè)置回Ready。
如果說(shuō)你調(diào)用的查詢(xún)式發(fā)送函數(shù),即HAL_UART_Transmit(),則在該函數(shù)里查詢(xún)到數(shù)據(jù)發(fā)送完畢或發(fā)生超時(shí)都會(huì)將gState設(shè)置為Ready.
如果說(shuō)你調(diào)用的是中斷式發(fā)送函數(shù),即HAL_UART_Transmit_IT(),同時(shí)你沿用CubeMx創(chuàng)建的中斷服務(wù)程序代碼框架,在相應(yīng)的發(fā)送中斷服務(wù)程序里檢測(cè)到發(fā)送完畢時(shí),也會(huì)將gState修改為ready為下次發(fā)送做準(zhǔn)備。 如果說(shuō)你調(diào)用API函數(shù)是HAL_UART_Transmit_IT(),而中斷服務(wù)程序是另外組織的,要記得在發(fā)送完成時(shí)將gState改為Ready,不然下次調(diào)用HAL_UART_Transmit_IT()函數(shù)會(huì)因?yàn)間state檢查不通過(guò)而不能得以執(zhí)行。
如果說(shuō)你調(diào)用的是DMA方式發(fā)送函數(shù),即HAL_UART_Transmit_DMA(),同樣,也沿用CubeMx創(chuàng)建的中斷服務(wù)程序代碼框架,且開(kāi)啟了DMA完成中斷和UART事件的中斷,
在相應(yīng)的DMA完成中斷代碼里也會(huì)適時(shí)地將gState從busy改為ready。如果說(shuō),你雖然調(diào)用了HAL_UART_Transmit_DMA()函數(shù),但沒(méi)有開(kāi)啟DMA完成中斷,也沒(méi)有在適當(dāng)?shù)奈恢脤State改為ready,這時(shí)就會(huì)發(fā)生即使你多次調(diào)用HAL_UART_Transmit_DMA()函數(shù)而只會(huì)做一次發(fā)送的情形。因?yàn)樵诤罄m(xù)的HAL_UART_Transmit_DMA()函數(shù)里做gState檢查發(fā)現(xiàn)是busy而強(qiáng)行退出。當(dāng)然,這時(shí)手動(dòng)將其改為Ready也是可以的,但要保證合適的時(shí)間點(diǎn)。
比方,我就是不想開(kāi)啟DMA相關(guān)中斷,只是想通過(guò)DMA方式發(fā)送幾次字符串而已,像下面這樣
HAL_UART_Transmit_DMA(&huart2, (uint8_t *)String1,??sizeof(String1));
HAL_Delay(200);
huart2.gState = HAL_UART_STATE_READY;
huart2.hdmatx->State = HAL_DMA_STATE_READY;
__HAL_UNLOCK(huart2.hdmatx);
HAL_UART_Transmit_DMA(&huart2, (uint8_t *)String2,??sizeof(String2));
HAL_Delay(200);
huart2.gState = HAL_UART_STATE_READY;
huart2.hdmatx->State = HAL_DMA_STATE_READY;
__HAL_UNLOCK(huart2.hdmatx);
當(dāng)然,這里還有一種情況,盡管當(dāng)我們基于中斷或DMA方式調(diào)用UART發(fā)送,也開(kāi)啟了相關(guān)中斷并沿用庫(kù)函數(shù)的寫(xiě)法,還是可能出現(xiàn)只有第一次發(fā)送有效的
情況,比方像下面這樣:
HAL_UART_Transmit_DMA(&huart2, (uint8_t *)String1,??sizeof(String1));
HAL_UART_Transmit_DMA(&huart2, (uint8_t *)String2,??sizeof(String2));
HAL_UART_Transmit_DMA(&huart2, (uint8_t *)String3,??sizeof(String3));
這里的三次調(diào)用太近了,第一次調(diào)用時(shí)軟件將gstate改為busy,當(dāng)運(yùn)行第二個(gè)第三個(gè)調(diào)用時(shí),第一次的uart發(fā)送可能根本沒(méi)有完成,自然也就沒(méi)法
基于它的完成中斷將gstate改為ready,這樣導(dǎo)致后續(xù)的兩次調(diào)用都無(wú)效了。所以像這種情況,第二次調(diào)用前要確保上次傳輸完成了。