在uart模板中的main函數中修改
HAL_StatusTypeDef status;
while(1)
{
HAL_Delay(1000);
status = HAL_UART_Transmit_IT(&huart1, (uint8_t *)"Hello_1", 7);
printf("status=%d\n", status);
}
結果只打印第一個字符‘H’,監控輸出
status=0
status=2
status=2
status=2
...
是不是使用這個HAL_UART_Transmit_IT的姿勢有問題
使用 HAL_UART_Transmit
it是中斷的意思?
在回調函數中添加了
void HAL_UART_TxCpltCallback(UART_HandleTypeDef *huart)
{
printf("***1***\n");
}
但是在監控中沒有相應的輸出,也就是說沒有進入中斷。
HAL_UART_Transmit_IT()的函數聲明是
HAL_StatusTypeDef HAL_UART_Transmit_IT(UART_HandleTypeDef huart, uint8_t pData, uint16_t Size);
參數有串口handle、待發送的數據指針、有數據長度,我的理解是應該發送數據,然後再發送完成後進入回調函數處理,不知道我的理解對不對。
@baby20060701 不完全對,HAL_UART_Transmit_IT 函數更多的是使能中斷發送,然後把要發送的數據長度,數據指針賦值到 UART_HandleTypeDef 結構體中,然後就會自動發送了,發送過程實在 HAL_UART_IRQHandler 中 調用 UART_Transmit_IT 進行數據指針的++ 和數據長度的-- ,所有數據發送完成後會觸發 UART_EndTransmit_IT 函數 ,最後在 UART_EndTransmit_IT 中調用 你的 HAL_UART_TxCpltCallback 函數,另外需要你沖寫 HAL_UART_TxCpltCallback 函數 去除 __attribute__((weak)) 屬性
跟蹤了以下,中斷進入了HAL_UART_IRQHandler函數,然後沒有調用UART_Transmit_IT,而是調用了UART_EndTransmit_IT,也就是在下面一段中打印了3
if (((isrflags & UART_INTS_TL) != RESET) && ((isrmasks & UART_INTM_RL) == RESET))
{
printf("***2***\n");
UART_Transmit_IT(huart);
}
if (((isrflags & UART_INTS_TEMPT) != RESET) && ((isrmasks & UART_INTM_TEMPT) == RESET))
{
printf("***3***\n");
UART_EndTransmit_IT(huart);
}
然後跟蹤UART_EndTransmit_IT,確實進入了該函數,沒有打印4,然後就返回了
static HAL_StatusTypeDef UART_EndTransmit_IT(UART_HandleTypeDef *huart)
{
printf("UART_EndTransmit_IT\n");
if (huart->TxXferCount == 0)
{
printf("***4***\n");
__HAL_UART_DISABLE_IT(huart, UART_INTM_TL | UART_INTM_TEMPT);
huart->gState = HAL_UART_STATE_READY;
HAL_UART_TxCpltCallback(huart);
}
return HAL_OK;
}
@ZYQ 在HAL_UART_Transmit_IT中有一點看不明白了
do {
if ((huart->Instance->FIFOS & UART_FIFOS_TFC) == UART_FIFO_FULL)
{
break;
}
huart->Instance->TDW = *(huart->pTxBuffPtr);
huart->pTxBuffPtr++;
huart->TxXferCount--;
} while(0);
這個while(0)有什麼用?只執行一次?那不如用if{}else{}
修改了一下,HAL_UART_Transmit_IT能正常工作了
do {
if (((huart->Instance->FIFOS & UART_FIFOS_TFC) == UART_FIFO_FULL)||(huart->TxXferCount == 0))
{
break;
}
huart->Instance->TDW = *(huart->pTxBuffPtr);
huart->pTxBuffPtr++;
huart->TxXferCount--;
} while(1);
這樣修改對嗎?
已經可以工作了,萬分感謝!!!
只是還有一個小問題,每次系統複位後第一次用這個函數輸出時,會把第一個字符輸出兩遍,能解決的話就完美了。
@isme 找到問題的根源了。在HAL_UART_IRQHandler函數中的第二個if語句:
if (((isrflags & UART_INTS_TL) != RESET) && ((isrmasks & UART_INTM_RL) == RESET))
這一行中的UART_INTM_RL有誤,應改為UART_INTM_TL
if (((isrflags & UART_INTS_TL) != RESET) && ((isrmasks & UART_INTM_TL) == RESET))
然後把HAL_UART_Transmit_IT函數中的while(0)修改為
while (huart->RxXferCount > 0U)
就正常了。
另外我覺得那個&& ((isrmasks & UART_INTM_TL) == RESET)是沒有作用的,因為屏蔽位UART_INTM_TL是硬件的屏蔽位,如果前面沒有__HAL_UART_ENABLE_IT(huart, UART_TX_INT_FLAG)清除了屏蔽位,也就是如果UART_INTM_TL != RESET,根本產生不了這個UART_INTS_TL中斷,所以這類的判斷都沒有必要,不知道我的理解對不對。
WM_SDK_W806_v0.6.0_Patch2.zip
@isme 抽空試試我改的這個,就是按前面我發現的那幾項修改的,再測試幾次吧。