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