我试图理解STM32F091VB是如何使用函数HAL_UART_Transmit_IT()通过串行协议管理数据发送的

目前,我在main()中调用了一个函数,该函数创建数据包并通过串口发送;是这样的:

tx1[0] = STX;    
tx1[1] = 0xFF;
tx1[2] = 0x80;
tx1[3] = 0x80;

DE_TAST_HIGH;
HAL_UART_Transmit_IT(&huart3, tx1, 8);

现在,我发送的数据非常小,所以代码运行得非常快,我试图理解如果我试图通过串行协议发送一个巨大的数据包会发生什么.

对于istance,如果我的tx1[]字节是HAL_UART_Transmit_IT()功能块,那么当完整的数据包被发送到串行端口时,CPU会等待,或者它更像是一个单独的过程,在我告诉micro发送数据包的同时,它还会处理代码/主功能的剩余部分?

我试着在微数据表上搜索,看看这个过程是否有什么问题,但我没有运气.我已经阅读了stm32f0xx_hal_uart.c,它确认它是在非阻塞模式下通过中断发送的,但我想有一些关于它的更深入的文档

推荐答案

首先,你需要了解HAL_UART_Transmit_IT的用途.我们可以从STM FAQ人那里得到一些帮助.

interrupt mode.

这个函数是"非阻塞"的,因为当你调用它时,它会对中断进行一些配置,然后返回.在调用函数的过程中,缓冲区不会被传输,相反,繁重的工作将被推迟到稍后的阶段.

我们可以进一步查看源代码,从我说的话中得到证据(注意,我只保留了有趣的部分).

stage调度

HAL_StatusTypeDef HAL_UART_Transmit(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size, uint32_t Timeout)
{
  uint16_t* tmp;
  uint32_t tickstart = 0U;
  
    // [ ... ]

    huart->TxXferSize = Size;
    huart->TxXferCount = Size;
    while(huart->TxXferCount > 0U)
    {

        // [ ... ]
        // This is were the actual HW regs are accessed, starting the transfer
        huart->Instance->DR = (*pData++ & (uint8_t)0xFF);
      } 
    }
    
    // [ ... ]

  return HAL_OK
}

Non stage调度

HAL_StatusTypeDef HAL_UART_Transmit_IT(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size)
{

    
    huart->pTxBuffPtr = pData;
    huart->TxXferSize = Size;
    huart->TxXferCount = Size;

    /* Enable the UART Transmit data register empty Interrupt */
    // This is the only part were HW regs are accessed. What is happening here??
    SET_BIT(huart->Instance->CR1, USART_CR1_TXEIE);
    
    return HAL_OK;

}

IT功能仅激活一个中断,也基于数据表:

enter image description here

enter image description here

这意味着只要TX缓冲区空闲,我们就会收到一个中断.Who is actually sending the data then?

在常见问题解答和阅读源代码的帮助下,我们发现void HAL_UART_IRQHandler(UART_HandleTypeDef *huart)的功能如下:

/* UART in mode Transmitter ------------------------------------------------*/
   if(((isrflags & USART_SR_TXE) != RESET) && ((cr1its & USART_CR1_TXEIE) != RESET))
   {
     UART_Transmit_IT(huart);
     return;
   }

这又称为UART_Transmit_IT

 static HAL_StatusTypeDef UART_Transmit_IT(UART_HandleTypeDef *huart)
 {
   uint16_t* tmp;
   
   /* Check that a Tx process is ongoing */
   if(huart->gState == HAL_UART_STATE_BUSY_TX)
   {

       huart->Instance->DR = (uint8_t)(*huart->pTxBuffPtr++ & (uint8_t)0x00FF);
 
     if(--huart->TxXferCount == 0U)
     {
       /* Disable the UART Transmit Complete Interrupt */
       CLEAR_BIT(huart->Instance->CR1, USART_CR1_TXEIE);
 
       /* Enable the UART Transmit Complete Interrupt */    
       SET_BIT(huart->Instance->CR1, USART_CR1_TCIE);
     }
     return HAL_OK;
   }
   else
   {
     return HAL_BUSY;
   }
 }

这个函数只传输一个字节!然后它递减传输的计数器(记住,所有信息都被设置到uart处理程序中),如果达到0,最后调用complete中断.

打断

请注意,StmCube为您执行外围设备初始化和中断链接,但如果您从头开始编程,则需要记住写入和注册UART_IRQ_Handler

您可以在"代码导航器"中找到here条代码,以查看我的代码片段并进行进一步研究.

C++相关问答推荐

以前版本的tty_ldisc_ops.ioctl()是否也需要文件参数?

难以理解Makefile隐含规则

LibpCap禁用监视器模式(C、MacOS)

Char变量如何在不使用方括号或花括号的情况下存储字符串,以及它如何迭代到下一个字符?

如何使用指向 struct 数组的指针并访问数组中特定索引处的 struct

为什么我可以在GCC的标签后声明变量,但不能声明Clang?

将返回的char*设置为S在函数中定义的字符串文字可能会产生什么问题?

编译器如何处理具有更复杂值的枚举?

将字符串数组传递给C中的函数:`str[dim1][str_size]`vs`*str[dim1]`

如何使用FSeek和文件流指针在C中查找文件的前一个元素和前一个减go 一个元素

静态初始化顺序失败是否适用于C语言?

可以';t从A9G模块拨打电话

可以对两种 struct 类型中的任何一种进行操作的C函数

C: NULL>;NULL总是false?

将char*铸造为空**

是什么阻止编译器优化手写的 memcmp()?

C11 嵌套泛型

快速准确计算double的小数指数

为什么这里的符号没有解析?

c 中符号表缺少项目