#include "main.h" #include "usart.h" #include "gpio.h" /* Private includes ----------------------------------------------------------*/ /* USER CODE BEGIN Includes */ /* USER CODE END Includes */ /* Private typedef -----------------------------------------------------------*/ /* USER CODE BEGIN PTD */ /* USER CODE END PTD */ /* Private define ------------------------------------------------------------*/ /* USER CODE BEGIN PD */ /* USER CODE END PD */ /* Private macro -------------------------------------------------------------*/ /* USER CODE BEGIN PM */ /* USER CODE END PM */ /* Private variables ---------------------------------------------------------*/ /* USER CODE BEGIN PV */ /* USER CODE END PV */ /* Private function prototypes -----------------------------------------------*/ void SystemClock_Config(void); /* USER CODE BEGIN PFP */ /* USER CODE END PFP */ /* Private user code ---------------------------------------------------------*/ /* USER CODE BEGIN 0 */ void USART1_IRQHandler(void) { volatile uint8_t receive; //receive interrupt 接收中断 if(huart1.Instance->SR & UART_FLAG_RXNE) { receive = huart1.Instance->DR; HAL_GPIO_TogglePin(LED_R_GPIO_Port, LED_R_Pin); } //idle interrupt 空闲中断 else if(huart1.Instance->SR & UART_FLAG_IDLE) { receive = huart1.Instance->DR; HAL_GPIO_WritePin(LED_R_GPIO_Port, LED_R_Pin, GPIO_PIN_RESET); } } void USART6_IRQHandler(void) { volatile uint8_t receive; //receive interrupt 接收中断 if(huart6.Instance->SR & UART_FLAG_RXNE) { receive = huart6.Instance->DR; HAL_GPIO_TogglePin(LED_G_GPIO_Port, LED_G_Pin); } //idle interrupt 空闲中断 else if(huart6.Instance->SR & UART_FLAG_IDLE) { receive = huart6.Instance->DR; HAL_GPIO_WritePin(LED_G_GPIO_Port, LED_G_Pin, GPIO_PIN_RESET); } } /* USER CODE END 0 */ /** * @brief The application entry point. * @retval int */ int main(void) { /* USER CODE BEGIN 1 */ /* USER CODE END 1 */ /* MCU Configuration--------------------------------------------------------*/ /* Reset of all peripherals, Initializes the Flash interface and the Systick. */ HAL_Init(); /* USER CODE BEGIN Init */ /* USER CODE END Init */ /* Configure the system clock */ SystemClock_Config(); /* USER CODE BEGIN SysInit */ /* USER CODE END SysInit */ /* Initialize all configured peripherals */ MX_GPIO_Init(); MX_USART1_UART_Init(); MX_USART6_UART_Init(); /* USER CODE BEGIN 2 */ HAL_GPIO_WritePin(LED_R_GPIO_Port, LED_R_Pin, GPIO_PIN_RESET); HAL_GPIO_WritePin(LED_G_GPIO_Port, LED_G_Pin, GPIO_PIN_RESET); HAL_GPIO_WritePin(LED_B_GPIO_Port, LED_B_Pin, GPIO_PIN_RESET); //enable receive interrupt and idle interrupt //使能接收中断和空闲中断 __HAL_UART_ENABLE_IT(&huart1, UART_IT_RXNE); //receive interrupt __HAL_UART_ENABLE_IT(&huart1, UART_IT_IDLE); //idle interrupt __HAL_UART_ENABLE_IT(&huart6, UART_IT_RXNE); //receive interrupt __HAL_UART_ENABLE_IT(&huart6, UART_IT_IDLE); //idle interrupt /* USER CODE END 2 */ /* Infinite loop */ /* USER CODE BEGIN WHILE */ while (1) { /* USER CODE END WHILE */ /* USER CODE BEGIN 3 */ //send data by usart //串口发送数据 HAL_UART_Transmit(&huart1, "RoboMaster\r\n", 12, 100); HAL_Delay(100); HAL_UART_Transmit(&huart6, "RoboMaster\r\n", 12, 100); HAL_Delay(100); } /* USER CODE END 3 */ } /** * @brief System Clock Configuration * @retval None */ void SystemClock_Config(void) { RCC_OscInitTypeDef RCC_OscInitStruct = {0}; RCC_ClkInitTypeDef RCC_ClkInitStruct = {0}; /** Configure the main internal regulator output voltage */ __HAL_RCC_PWR_CLK_ENABLE(); __HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1); /** Initializes the CPU, AHB and APB busses clocks */ RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE; RCC_OscInitStruct.HSEState = RCC_HSE_ON; RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON; RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE; RCC_OscInitStruct.PLL.PLLM = 6; RCC_OscInitStruct.PLL.PLLN = 168; RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2; RCC_OscInitStruct.PLL.PLLQ = 4; if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK) { Error_Handler(); } /** Initializes the CPU, AHB and APB busses clocks */ RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2; RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK; RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1; RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV4; RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV2; if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_5) != HAL_OK) { Error_Handler(); } } /* USER CODE BEGIN 4 */ /* USER CODE END 4 */ /** * @brief This function is executed in case of error occurrence. * @retval None */ void Error_Handler(void) { /* USER CODE BEGIN Error_Handler_Debug */ /* User can add his own implementation to report the HAL error return state */ /* USER CODE END Error_Handler_Debug */ } #ifdef USE_FULL_ASSERT /** * @brief Reports the name of the source file and the source line number * where the assert_param error has occurred. * @param file: pointer to the source file name * @param line: assert_param error line source number * @retval None */ void assert_failed(uint8_t *file, uint32_t line) { /* USER CODE BEGIN 6 */ /* User can add his own implementation to report the file name and line number, tex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */ /* USER CODE END 6 */ }用中文详细解读以上程序
这段代码是一个使用USART(通用异步收发器)进行串口通信的示例。以下是对代码的详细解读:
- 引用头文件:
cCopy code#include "main.h"
#include "usart.h"
#include "gpio.h"
这些头文件包含了需要使用的库函数和宏定义。
- 定义USART1和USART6的中断处理函数:
cCopy codevoid USART1_IRQHandler(void)
{
// 中断处理代码
}
void USART6_IRQHandler(void)
{
// 中断处理代码
}
这些函数是USART1和USART6的中断处理函数,当接收到数据或发生空闲中断时,将执行相应的处理代码。
- 主函数:
cCopy codeint main(void)
{
HAL_Init();
SystemClock_Config();
MX_GPIO_Init();
MX_USART1_UART_Init();
MX_USART6_UART_Init();
// 初始化GPIO和USART模块
while (1)
{
// 发送数据到USART1和USART6
HAL_UART_Transmit(&huart1, "RoboMaster\r\n", 12, 100);
HAL_Delay(100);
HAL_UART_Transmit(&huart6, "RoboMaster\r\n", 12, 100);
HAL_Delay(100);
}
}
在主函数中,首先进行一些初始化操作,包括HAL库的初始化、系统时钟配置、GPIO初始化和USART初始化。然后进入一个无限循环,循环中通过USART1和USART6发送数据。
- SystemClock_Config函数:
cCopy codevoid SystemClock_Config(void)
{
RCC_OscInitTypeDef RCC_OscInitStruct = {0};
RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
// 系统时钟配置代码
}
这个函数用于配置系统时钟。它通过设置RCC_OscInitStruct和RCC_ClkInitStruct结构体中的参数来配置主内部振荡器(HSE)和锁相环(PLL)。这里使用了168MHz的系统时钟频率。
- Error_Handler函数:
cCopy codevoid Error_Handler(void)
{
// 错误处理代码
}
这个函数是一个错误处理函数,当发生错误时会进入该函数。在这个示例中,没有定义错误处理的具体内容。
- assert_failed函数:
cCopy codevoid assert_failed(uint8_t *file, uint32_t line)
{
// 错误处理代码
}
这个函数是断言失败时的处理函数,用于报告发生断言失败的源文件和行号。在这个示例中,没有定义断言失败的具体处理内容。
以上是对给定代码的详细解读。请注意,这段代码中还引用了其他头文件(main.h、usart.h、gpio.h)和函数(MX_GPIO_Init、MX_USART1_UART_Init、MX_USART6_UART_Init),这些代码可能包含在其他文件中。因此,要完全理解代码的功能和结构,可能需要查看更多的源代码文件。
详细解读以下代码: HAL_GPIO_WritePin(LED_R_GPIO_Port, LED_R_Pin, GPIO_PIN_RESET); HAL_GPIO_WritePin(LED_G_GPIO_Port, LED_G_Pin, GPIO_PIN_RESET); HAL_GPIO_WritePin(LED_B_GPIO_Port, LED_B_Pin, GPIO_PIN_RESET); //enable receive interrupt and idle interrupt //使能接收中断和空闲中断 __HAL_UART_ENABLE_IT(&huart1, UART_IT_RXNE); //receive interrupt __HAL_UART_ENABLE_IT(&huart1, UART_IT_IDLE); //idle interrupt __HAL_UART_ENABLE_IT(&huart6, UART_IT_RXNE); //receive interrupt __HAL_UART_ENABLE_IT(&huart6, UART_IT_IDLE); //idle interrupt
这段代码主要包含两个部分,第一个部分是控制GPIO引脚输出低电平,第二个部分是使能USART的接收中断和空闲中断。
- 控制GPIO引脚输出低电平:
cCopy codeHAL_GPIO_WritePin(LED_R_GPIO_Port, LED_R_Pin, GPIO_PIN_RESET); HAL_GPIO_WritePin(LED_G_GPIO_Port, LED_G_Pin, GPIO_PIN_RESET); HAL_GPIO_WritePin(LED_B_GPIO_Port, LED_B_Pin, GPIO_PIN_RESET);
这三行代码使用HAL库函数控制GPIO引脚输出低电平。HAL_GPIO_WritePin
函数的第一个参数是GPIO端口,第二个参数是引脚号,第三个参数是输出的电平状态。在这里,LED_R_GPIO_Port、LED_G_GPIO_Port和LED_B_GPIO_Port是GPIO端口的宏定义,LED_R_Pin、LED_G_Pin和LED_B_Pin是引脚号的宏定义,GPIO_PIN_RESET表示低电平。
通过这段代码,将LED_R、LED_G和LED_B引脚的电平都设置为低电平。
- 使能USART的接收中断和空闲中断:
cCopy code__HAL_UART_ENABLE_IT(&huart1, UART_IT_RXNE); //receive interrupt
__HAL_UART_ENABLE_IT(&huart1, UART_IT_IDLE); //idle interrupt
__HAL_UART_ENABLE_IT(&huart6, UART_IT_RXNE); //receive interrupt
__HAL_UART_ENABLE_IT(&huart6, UART_IT_IDLE); //idle interrupt
这四行代码使用宏定义__HAL_UART_ENABLE_IT
来使能USART的中断功能。第一个参数是对应的USART实例(这里是huart1和huart6),第二个参数是中断类型。UART_IT_RXNE表示接收中断,UART_IT_IDLE表示空闲中断。
通过这段代码,使能了USART1和USART6的接收中断和空闲中断,以便在接收到数据或发生空闲状态时触发相应的中断处理函数。
UART_IT_RXNE什么意思
UART_IT_RXNE是USART的接收缓冲区非空中断的中断类型标志位。
在串口通信中,当接收到数据时,数据将被存储在USART的接收缓冲区中。当接收缓冲区非空时,可以触发接收缓冲区非空中断,即UART_IT_RXNE中断。这个中断类型表示可以从接收缓冲区读取数据。
在代码中,通过使能UART_IT_RXNE中断,可以在接收到数据时触发相应的中断处理函数,并执行相应的数据处理操作。
UART_IT_IDLE
UART_IT_IDLE是USART的空闲中断的中断类型标志位。
在串口通信中,空闲状态是指接收线上连续接收到空闲帧(即停止位为高电平)一段时间后的状态。当串口接收线上一段时间没有接收到新的数据时,可以触发空闲中断,即UART_IT_IDLE中断。这个中断类型表示检测到了串口的空闲状态。
在代码中,通过使能UART_IT_IDLE中断,可以在串口进入空闲状态时触发相应的中断处理函数,并执行相应的数据处理操作。空闲中断通常用于判断一帧数据的接收是否完成。
#include "usart.h" /* USER CODE BEGIN 0 */ /* USER CODE END 0 */ UART_HandleTypeDef huart1; UART_HandleTypeDef huart6; /* USART1 init function */ void MX_USART1_UART_Init(void) { huart1.Instance = USART1; huart1.Init.BaudRate = 115200; huart1.Init.WordLength = UART_WORDLENGTH_8B; huart1.Init.StopBits = UART_STOPBITS_1; huart1.Init.Parity = UART_PARITY_NONE; huart1.Init.Mode = UART_MODE_TX_RX; huart1.Init.HwFlowCtl = UART_HWCONTROL_NONE; huart1.Init.OverSampling = UART_OVERSAMPLING_16; if (HAL_UART_Init(&huart1) != HAL_OK) { Error_Handler(); } } /* USART6 init function */ void MX_USART6_UART_Init(void) { huart6.Instance = USART6; huart6.Init.BaudRate = 115200; huart6.Init.WordLength = UART_WORDLENGTH_8B; huart6.Init.StopBits = UART_STOPBITS_1; huart6.Init.Parity = UART_PARITY_NONE; huart6.Init.Mode = UART_MODE_TX_RX; huart6.Init.HwFlowCtl = UART_HWCONTROL_NONE; huart6.Init.OverSampling = UART_OVERSAMPLING_16; if (HAL_UART_Init(&huart6) != HAL_OK) { Error_Handler(); } } void HAL_UART_MspInit(UART_HandleTypeDef* uartHandle) { GPIO_InitTypeDef GPIO_InitStruct = {0}; if(uartHandle->Instance==USART1) { /* USER CODE BEGIN USART1_MspInit 0 */ /* USER CODE END USART1_MspInit 0 */ /* USART1 clock enable */ __HAL_RCC_USART1_CLK_ENABLE(); __HAL_RCC_GPIOB_CLK_ENABLE(); __HAL_RCC_GPIOA_CLK_ENABLE(); /**USART1 GPIO Configuration PB7 ------> USART1_RX PA9 ------> USART1_TX */ GPIO_InitStruct.Pin = GPIO_PIN_7; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; GPIO_InitStruct.Pull = GPIO_PULLUP; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH; GPIO_InitStruct.Alternate = GPIO_AF7_USART1; HAL_GPIO_Init(GPIOB, &GPIO_InitStruct); GPIO_InitStruct.Pin = GPIO_PIN_9; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; GPIO_InitStruct.Pull = GPIO_PULLUP; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH; GPIO_InitStruct.Alternate = GPIO_AF7_USART1; HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); /* USART1 interrupt Init */ HAL_NVIC_SetPriority(USART1_IRQn, 0, 0); HAL_NVIC_EnableIRQ(USART1_IRQn); /* USER CODE BEGIN USART1_MspInit 1 */ /* USER CODE END USART1_MspInit 1 */ } else if(uartHandle->Instance==USART6) { /* USER CODE BEGIN USART6_MspInit 0 */ /* USER CODE END USART6_MspInit 0 */ /* USART6 clock enable */ __HAL_RCC_USART6_CLK_ENABLE(); __HAL_RCC_GPIOG_CLK_ENABLE(); /**USART6 GPIO Configuration PG14 ------> USART6_TX PG9 ------> USART6_RX */ GPIO_InitStruct.Pin = GPIO_PIN_14|GPIO_PIN_9; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; GPIO_InitStruct.Pull = GPIO_PULLUP; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH; GPIO_InitStruct.Alternate = GPIO_AF8_USART6; HAL_GPIO_Init(GPIOG, &GPIO_InitStruct); /* USART6 interrupt Init */ HAL_NVIC_SetPriority(USART6_IRQn, 0, 0); HAL_NVIC_EnableIRQ(USART6_IRQn); /* USER CODE BEGIN USART6_MspInit 1 */ /* USER CODE END USART6_MspInit 1 */ } } void HAL_UART_MspDeInit(UART_HandleTypeDef* uartHandle) { if(uartHandle->Instance==USART1) { /* USER CODE BEGIN USART1_MspDeInit 0 */ /* USER CODE END USART1_MspDeInit 0 */ /* Peripheral clock disable */ __HAL_RCC_USART1_CLK_DISABLE(); /**USART1 GPIO Configuration PB7 ------> USART1_RX PA9 ------> USART1_TX */ HAL_GPIO_DeInit(GPIOB, GPIO_PIN_7); HAL_GPIO_DeInit(GPIOA, GPIO_PIN_9); /* USART1 interrupt Deinit */ HAL_NVIC_DisableIRQ(USART1_IRQn); /* USER CODE BEGIN USART1_MspDeInit 1 */ /* USER CODE END USART1_MspDeInit 1 */ } else if(uartHandle->Instance==USART6) { /* USER CODE BEGIN USART6_MspDeInit 0 */ /* USER CODE END USART6_MspDeInit 0 */ /* Peripheral clock disable */ __HAL_RCC_USART6_CLK_DISABLE(); /**USART6 GPIO Configuration PG14 ------> USART6_TX PG9 ------> USART6_RX */ HAL_GPIO_DeInit(GPIOG, GPIO_PIN_14|GPIO_PIN_9); /* USART6 interrupt Deinit */ HAL_NVIC_DisableIRQ(USART6_IRQn); /* USER CODE BEGIN USART6_MspDeInit 1 */ /* USER CODE END USART6_MspDeInit 1 */ } } /* USER CODE BEGIN 1 */ /* USER CODE END 1 */ /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ 详细解读以上代码
以上代码是使用STM32的HAL库初始化USART1和USART6串口的配置。
首先,通过包含"usart.h"头文件,引入USART相关的定义和函数。
然后,定义了两个全局变量huart1
和huart6
,它们分别表示USART1和USART6的句柄(handle),用于存储相关的配置和状态信息。
接下来,分别定义了MX_USART1_UART_Init()
和MX_USART6_UART_Init()
函数,用于初始化USART1和USART6的配置。
在MX_USART1_UART_Init()
函数中,首先对huart1
句柄进行配置,包括波特率、数据位长度、停止位、校验位、工作模式等参数。然后调用HAL库提供的函数HAL_UART_Init()
进行USART1的初始化。
在MX_USART6_UART_Init()
函数中,同样对huart6
句柄进行配置,并调用HAL_UART_Init()
函数进行USART6的初始化。
接下来,定义了HAL_UART_MspInit()
函数和HAL_UART_MspDeInit()
函数,用于初始化和去初始化USART的外设时钟、GPIO配置和中断优先级。
在HAL_UART_MspInit()
函数中,根据uartHandle
参数的值,判断是USART1还是USART6的初始化。然后对相应的GPIO进行配置,设置为复用功能,同时使能对应的GPIO时钟。最后,配置USART的中断优先级,并使能对应的中断。
在HAL_UART_MspDeInit()
函数中,根据uartHandle
参数的值,判断是USART1还是USART6的去初始化。然后禁用USART外设的时钟,去初始化对应的GPIO配置,同时禁用对应的中断。
以上是对USART1和USART6的初始化和去初始化过程的详细解读。这些函数的具体实现可以在ST的HAL库中找到相应的代码。
void MX_USART1_UART_Init(void) { huart1.Instance = USART1; huart1.Init.BaudRate = 115200; huart1.Init.WordLength = UART_WORDLENGTH_8B; huart1.Init.StopBits = UART_STOPBITS_1; huart1.Init.Parity = UART_PARITY_NONE; huart1.Init.Mode = UART_MODE_TX_RX; huart1.Init.HwFlowCtl = UART_HWCONTROL_NONE; huart1.Init.OverSampling = UART_OVERSAMPLING_16; if (HAL_UART_Init(&huart1) != HAL_OK) { Error_Handler(); } }详细解读