在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 抽空试试我改的这个,就是按前面我发现的那几项修改的,再测试几次吧。