STM32CUBEIDE 使用串口中断的接受与发送笔记

使用的是STM32f750

1:printf的使用

	//在usart.h文件中包含头文件:记得勾选Use Microlib
	#include "stdio.h"
	#ifdef __GNUC__
	  /* With GCC/RAISONANCE, small printf (option LD Linker->Libraries->Small printf
	     set to 'Yes') calls __io_putchar() */
	  #define PUTCHAR_PROTOTYPE int __io_putchar(int ch)
	#else
	  #define PUTCHAR_PROTOTYPE int fputc(int ch, FILE *f)
	#endif /* __GNUC__ */
	/**
	  * @brief  Retargets the C library printf function to the USART.
	  * @param  None
	  * @retval None
	  */
	PUTCHAR_PROTOTYPE
	{
	  /* Place your implementation of fputc here */
	  /* e.g. write a character to the EVAL_COM1 and Loop until the end of transmission */
		HAL_UART_Transmit( &huart6 , (uint8_t *)&ch, 1, 0xFFFF);
	  return ch;
	}

2:相关常用函数的介绍:

 2.1 HAL_UART_Transmit(UART_HandleTypeDef *huart, const uint8_t *pData, uint16_t Size, uint32_t Timeout)

功能:串口发送指定长度的数据。如果超时没发送完成,则不再发送,返回超时标志(HAL_TIMEOUT)。

参数:

UART_HandleTypeDef *huart      UATR的别名    如 :   UART_HandleTypeDef huart1;   别名就是huart1  
*pData      需要发送的数据 
Size    发送的字节数
Timeout   最大发送时间,发送数据超过该时间退出发送 ,堵塞发送

HAL_StatusTypeDef HAL_UART_Transmit(UART_HandleTypeDef *huart, const uint8_t *pData, uint16_t Size, uint32_t Timeout)
{
  const uint8_t  *pdata8bits;
  const uint16_t *pdata16bits;
  uint32_t tickstart;

  /* Check that a Tx process is not already ongoing */
  if (huart->gState == HAL_UART_STATE_READY)
  {
    if ((pData == NULL) || (Size == 0U))
    {
      return  HAL_ERROR;
    }

    __HAL_LOCK(huart);

    huart->ErrorCode = HAL_UART_ERROR_NONE;
    huart->gState = HAL_UART_STATE_BUSY_TX;

    /* Init tickstart for timeout management */
    tickstart = HAL_GetTick();

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

    /* In case of 9bits/No Parity transfer, pData needs to be handled as a uint16_t pointer */
    if ((huart->Init.WordLength == UART_WORDLENGTH_9B) && (huart->Init.Parity == UART_PARITY_NONE))
    {
      pdata8bits  = NULL;
      pdata16bits = (const uint16_t *) pData;
    }
    else
    {
      pdata8bits  = pData;
      pdata16bits = NULL;
    }

    __HAL_UNLOCK(huart);

    while (huart->TxXferCount > 0U)
    {
      if (UART_WaitOnFlagUntilTimeout(huart, UART_FLAG_TXE, RESET, tickstart, Timeout) != HAL_OK)
      {
        return HAL_TIMEOUT;
      }
      if (pdata8bits == NULL)
      {
        huart->Instance->TDR = (uint16_t)(*pdata16bits & 0x01FFU);
        pdata16bits++;
      }
      else
      {
        huart->Instance->TDR = (uint8_t)(*pdata8bits & 0xFFU);
        pdata8bits++;
      }
      huart->TxXferCount--;
    }

    if (UART_WaitOnFlagUntilTimeout(huart, UART_FLAG_TC, RESET, tickstart, Timeout) != HAL_OK)
    {
      return HAL_TIMEOUT;
    }

    /* At end of Tx process, restore huart->gState to Ready */
    huart->gState = HAL_UART_STATE_READY;

    return HAL_OK;
  }
  else
  {
    return HAL_BUSY;
  }
}

2.2 HAL_UART_Transmit_IT(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size)

执行中:发送pData指针指向空间的信息+使能“发送寄存器空”中断;
执行结束后:立即进入中断;
在中断里,先自动调用 UART_EndTransmit_IT(UART_HandleTypeDef *huart) 函数(该函数会失能“发送完成”中断。不过无所谓,可以不用在意);
中断里,之后再自动调用 HAL_UART_TxCpltCallback(UART_HandleTypeDef *huart) 回调函数(用户自定义其功能),退出中断,等待下一次信息的发送。;

//HAL_UART_Transmit_IT()执行函数(非阻塞)后进去回调函数
//比如我发送完一次数据后进入回调函数执行一次LED的反转
while(1)
{
     HAL_UART_Transmit_IT( &huart1, &"zjy", sizeof("zjy"));
}
void HAL_UART_TxCpltCallback(UART_HandleTypeDef *huart)
{
	if( huart == &huart1 )
	{
		//HAL_UART_Transmit_IT( &huart1, &"2222", 1);
		HAL_GPIO_TogglePin(GPIOB,LED0_Pin);
	}
}

2.3 HAL_UART_Receive(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size, uint32_t Timeout)

HAL_StatusTypeDef HAL_UART_Receive(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size, uint32_t Timeout)
{
  uint8_t  *pdata8bits;
  uint16_t *pdata16bits;
  uint16_t uhMask;
  uint32_t tickstart;

  /* Check that a Rx process is not already ongoing */
  if (huart->RxState == HAL_UART_STATE_READY)
  {
    if ((pData == NULL) || (Size == 0U))
    {
      return  HAL_ERROR;
    }

    __HAL_LOCK(huart);

    huart->ErrorCode = HAL_UART_ERROR_NONE;
    huart->RxState = HAL_UART_STATE_BUSY_RX;
    huart->ReceptionType = HAL_UART_RECEPTION_STANDARD;

    /* Init tickstart for timeout management */
    tickstart = HAL_GetTick();

    huart->RxXferSize  = Size;
    huart->RxXferCount = Size;

    /* Computation of UART mask to apply to RDR register */
    UART_MASK_COMPUTATION(huart);
    uhMask = huart->Mask;

    /* In case of 9bits/No Parity transfer, pRxData needs to be handled as a uint16_t pointer */
    if ((huart->Init.WordLength == UART_WORDLENGTH_9B) && (huart->Init.Parity == UART_PARITY_NONE))
    {
      pdata8bits  = NULL;
      pdata16bits = (uint16_t *) pData;
    }
    else
    {
      pdata8bits  = pData;
      pdata16bits = NULL;
    }

    __HAL_UNLOCK(huart);

    /* as long as data have to be received */
    while (huart->RxXferCount > 0U)
    {
      if (UART_WaitOnFlagUntilTimeout(huart, UART_FLAG_RXNE, RESET, tickstart, Timeout) != HAL_OK)
      {
        return HAL_TIMEOUT;
      }
      if (pdata8bits == NULL)
      {
        *pdata16bits = (uint16_t)(huart->Instance->RDR & uhMask);
        pdata16bits++;
      }
      else
      {
        *pdata8bits = (uint8_t)(huart->Instance->RDR & (uint8_t)uhMask);
        pdata8bits++;
      }
      huart->RxXferCount--;
    }

    /* At end of Rx process, restore huart->RxState to Ready */
    huart->RxState = HAL_UART_STATE_READY;

    return HAL_OK;
  }
  else
  {
    return HAL_BUSY;
  }
}

判断是否忙-->锁住-->标记接收忙-->获取tick计数

-->赋值RxXferCount有多少数据要接收-->每次从DR内获取一个Byte存在pData指向的空间

2.4 HAL_UART_Receive_IT(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size)

用户在 main() 和回调函数 HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart) 中都调用一次该函数;

  HAL_Init();
  SystemClock_Config();
  MX_GPIO_Init();
  MX_USART1_UART_Init();
  MX_DMA_Init();
  HAL_UART_Receive_IT(&huart1, Rxbuf, 1);
/*没有在main()里调用 HAL_UART_Receive_IT(),usart是不会进入中断
 *去接收信息的。——阅读了stm32f1xx_hal_uart.c文件中对uart外设的说明,
 *发现了该问题并解决。*/


执行中:指定未来接收到的信息要存入的空间,即pData指针指向的空间就是之后接收到的信息要存入的空间+使能“奇偶校验错误”中断+使能“其它uart错误”中断+使能“接收寄存器非空”中断;(特别注意:该函数是不会接收信息的,只是指定信息要存入的空间
执行结束后:等待接收寄存器非空,然后进入中断;
在中断里,先自动调用 UART_Receive_IT(UART_HandleTypeDef *huart) 函数(该函数会接收信息并存入上一步已经预备好的空间中+失能“奇偶校验错误”中断+失能“其它uart错误”中断+失能“接收寄存器非空”中断);

//确保中断线与uart以对应
void USART1_IRQHandler(void)
{
	HAL_UART_IRQHandler(&huart1);
}
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
	if(huart->Instance==USART1)//如果是串口1
	{


		printf("11\r\n");
		HAL_UART_Transmit(&huart1,Txbuf ,sizeof(Txbuf),0xFFFF);

	}
	HAL_UART_Receive_IT(&huart1,Rxbuf ,1);
}
/*没有在 HAL_UART_RxCpltCallback() 中再次调用 HAL_UART_Receive_IT(),
*usart只会响应一次中断去接*收信息,之后再来新的信息就不会进入中断去接收了,
*更不会进入 HAL_UART_RxCpltCallback() 函数里了。**——通过软件的单步调试
*功能和网上海量教程,发现了该问题并解决*/


中断里,之后再自动调用 HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart) 回调函数(用户自定义其功能,但是用户在该函数中必须自行添加 HAL_UART_Receive_IT() 函数,以指定下一次信息待存入的空间并再次使能对应的中断功能);
退出中断,等待下一次接收寄存器非空

2.5总结

1、HAL_UART_Receive_IT和HAL_UART_Receive的区别就是:中断接收是有数据到了才去读;直接接收是直接读取,如果超时就返回

2、HAL_UART_Receive_IT配置后,有数据来,计数会在调用中断函数之后自动减1。只有到计数为0时,才会关闭中断并调用回调函数。至此有数据来不再调用中断函数,因为中断已经失效。

3、HAL_UART_Receive_IT在计数未至0之前,应该可以读取之前接收到的数据,但这样做应该比较危险。

4、在开源电子的例程中,使用 HAL_UART_Receive_IT(&huart1,(uint8_t *)aRxBuffer, 1);  即Size设置为1,只接收1Byte数据,在每次中断结束后重新配置来使能中断。
 

正点原子学习笔记

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值