HAL库(STM32CubeMX)——USART串口配置学习(中断接收/STM32G431RBT6)

  • UART与USART介绍:

USART(universal synchronous asynchronous receiver and transmitte): 通用同步异步收发器

USART是一个串行通信设备,可以灵活地与外部设备进行全双工数据交换。

UART(universal asynchronous receiver and transmitter): 通用异步收发器

异步串行通信口(UART)就是我们在嵌入式中常说的串口,它还是一种通用的数据通信议。

区别:

USART是指单片机的一个端口模块,可以根据需要配置成同步模式(SPI,I2C),也可以将其配置为异步模式,后者就是UART。所以说UART姑且可以称之为一个与SPI,I2C对等的“协议”,而USART则不是一个协议,而是更应该理解为一个实体。

  •  UART基础配置

 串口发送数据的时序图:

硬件基础:STM32G431RB(蓝桥杯嵌入式)

配置成异步模式即是UART,剩下的就是波特率等一些配置。  

使能中断: 

HAL_UART_Transmit();串口发送数据,使用超时管理机制 
HAL_UART_Receive();串口接收数据,使用超时管理机制
HAL_UART_Transmit_IT();串口中断模式发送  
HAL_UART_Receive_IT();串口中断模式接收
HAL_UART_Transmit_DMA();串口DMA模式发送
HAL_UART_Transmit_DMA();串口DMA模式接收

 一般的情况下,发送数据是主观上的,所以用HAL_UART_Transmit();,接收数据是被动的,一般利用中断完成接收。

串口接收:

在main函数中启动中断接收:

HAL_UART_Receive_IT(&huart1,(uint8_t *)&RX_buf, 1);

 在中断回调函数中要不断开启:(每次接收中断执行HAL_UART_IRQHandler函数之后,接收中断就会被关闭;)

void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
	HAL_UART_Receive_IT(&huart1,(uint8_t *)&RX_buf, 1);//接收一个字节
}

参考:单片机学习笔记-SMT32使用HAL库UART中断方式使用

了解到这个函数里主要是有:对后面要用到的一些参数进行配置。

  huart->pRxBuffPtr  = pData;
  huart->RxXferSize  = Size;
  huart->RxXferCount = Size;
  huart->RxISR       = NULL;

//这里的size就是1,pDate就是接收的数组名

所以调用这个代替终端里重新调用HAL_UART_Receive_IT()函数

串口发送:

 包含这俩个库才能使用sprintf和strlen函数。

char str[40];
sprintf(str, "Hello,world.\r\n");
HAL_UART_Transmit(&huart1,(unsigned char *)str, strlen(str), 50);

//int count=0;
//sprintf(str, "%d:Hello,world.\r\n",count);

  •  UART的DMA配置(太坑了,以后再说吧)

问题:

现在还不清楚选择AFOD和AFPP有什么影响,测试没发现什么问题,网上推荐选择AFOD,不懂为什么? 

  •  利用串口接收中断和空闲中断(直接访问寄存器)

串口接收中断:

使能接受中断RXEN后,串口接收8位数据位后,进入中断

使能:

__HAL_UART_ENABLE_IT(&huart2,UART_IT_RXNE);

实际处理函数:

USART2_IRQHandler(void)

一般在stm32cubemx中打开了串口中断,处理函数通常生成在stm32f1xx_it.c里面

自动生成的,这里面应该不需要使能(没实验过) HAL_UART_IRQHandler(&huart1);在main函数里使能就好

/******************************************************************************/
/* STM32F1xx Peripheral Interrupt Handlers                                    */
/* Add here the Interrupt Handlers for the used peripherals.                  */
/* For the available peripheral interrupt handler names,                      */
/* please refer to the startup file (startup_stm32f1xx.s).                    */
/******************************************************************************/

/**
  * @brief This function handles USART1 global interrupt.
  */
void USART1_IRQHandler(void)
{
  /* USER CODE BEGIN USART1_IRQn 0 */

  /* USER CODE END USART1_IRQn 0 */
  HAL_UART_IRQHandler(&huart1);
  /* USER CODE BEGIN USART1_IRQn 1 */

  /* USER CODE END USART1_IRQn 1 */
}

/* USER CODE BEGIN 1 */

/* USER CODE END 1 */

串口空闲中断:

使能IDLE,在串口接受完一帧数据后,在一个字节的时间内串口保持空闲则触发串口空闲中断  

再次进入上文的处理函数  USART2_IRQHandler()

__HAL_UART_ENABLE_IT(&huart2,UART_IT_IDLE);

实例:参考:STM32基于HAL库的串口接受中断和空闲中断

void USART3_IRQHandler(void){
      uint8_t temp;
    if(huart3.Instance->SR & UART_FLAG_RXNE){
         Rx_uart3_signal=2;
         temp=huart3.Instance->DR;
        Rx_uart3_buf[Rx_uart3_cnt++]=temp; 
    }
    
    else if(huart3.Instance->SR & UART_FLAG_IDLE){
         temp=huart3.Instance->DR;
        Rx_uart3_signal=0;		
    } 
}

串口接受完后空闲必须清除空闲标志位。通过读串口DR寄存器里的值来清除IDLE标志位,否则程序一直触发空闲中断。

这里上下两部分分别是正常数据接收和串口空闲处理,给Rx_uart3_signal赋值,这样就可以在主循环里根据这个标志判断数据接收程度。

这里直接读取的是寄存器:

USART_SR:Status register

TXE: Transmit data register empty

RXNE: Read data register not empty

IDLE: IDLE line detected

USART_DR:包含接收或传输的数据字符

(SR包含了所有的寄存器状态,所以和对应寄存器相与就可以得到该寄存器的状态)

例如:huart3.Instance->SR & 0x40就是判断第7位寄存器TXE状态

更详细的参考:

STM32F1串口寄存器解析及应用

  • 12
    点赞
  • 57
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
以下是使用STM32CubeMXHAL库配置RTC闹钟的步骤: 1. 打开STM32CubeMX软件,创建一个新的工程,并选择您的目标芯片型号。 2. 在Pinout & Configuration选项卡中,配置RTC时钟源。在该选项卡中,您可以选择使用外部晶振或内部RC振荡器。在这个例子中,我们将使用外部晶振。 3. 在Configuration选项卡中,启用RTC模块。在该选项卡中,您可以选择RTC时钟源和时钟分频器。在这个例子中,我们将选择外部晶振作为时钟源,并将时钟分频器设置为32768。 4. 在RTC Configuration选项卡中,启用RTC闹钟功能。在该选项卡中,您可以设置闹钟的时间和日期。在这个例子中,我们将设置闹钟在每天的12点触发。 5. 生成代码,并将生成的代码导入到您的工程中。 6. 在main.c文件中,初始化RTC和闹钟。以下是示例代码: ``` #include "stm32g4xx_hal.h" #include "stm32g4xx_hal_rtc.h" RTC_HandleTypeDef hrtc; void RTC_Init(void) { RCC_OscInitTypeDef RCC_OscInitStruct; RCC_PeriphCLKInitTypeDef PeriphClkInitStruct; /* Enable LSI clock */ RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_LSI; RCC_OscInitStruct.LSIState = RCC_LSI_ON; if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK) { Error_Handler(); } /* Select LSI as RTC clock source */ PeriphClkInitStruct.PeriphClockSelection = RCC_PERIPHCLK_RTC; PeriphClkInitStruct.RTCClockSelection = RCC_RTCCLKSOURCE_LSI; if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInitStruct) != HAL_OK) { Error_Handler(); } /* Initialize RTC */ hrtc.Instance = RTC; hrtc.Init.HourFormat = RTC_HOURFORMAT_24; hrtc.Init.AsynchPrediv = 127; hrtc.Init.SynchPrediv = 255; hrtc.Init.OutPut = RTC_OUTPUT_DISABLE; hrtc.Init.OutPutRemap = RTC_OUTPUT_REMAP_NONE; hrtc.Init.OutPutPolarity = RTC_OUTPUT_POLARITY_HIGH; hrtc.Init.OutPutType = RTC_OUTPUT_TYPE_OPENDRAIN; if (HAL_RTC_Init(&hrtc) != HAL_OK) { Error_Handler(); } /* Enable RTC Alarm */ HAL_RTC_DeactivateAlarm(&hrtc, RTC_ALARM_A); HAL_RTC_SetAlarm_IT(&hrtc, &sAlarm, RTC_FORMAT_BIN); } void HAL_RTC_AlarmAEventCallback(RTC_HandleTypeDef *hrtc) { /* Alarm event occurred */ } int main(void) { /* Initialize RTC */ RTC_Init(); /* Infinite loop */ while (1) { } } ``` 注意,这只是一个示例代码,您需要根据自己的需求进行修改和优化。 7. 在HAL_RTC_AlarmAEventCallback函数中,处理RTC闹钟事件。在该函数中,您可以执行任何所需的操作,例如触发一个中断或打开一个闹钟铃声。 以上就是使用STM32CubeMXHAL库配置RTC闹钟的步骤。希望对您有所帮助。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值