|
如何使用STM32 NUCLEO的串口
正如我们在前面有关ST新的开发板的教程看到的,STM32 NUCLEO板集成了ST-LINK V2.1接口。ST-LINK的设计主要是通过MINI-USB接口对目标MCU进行编程。而且,它至少提供了另一种非常有用的功能:虚拟串口。当你安装完ST-LINK的驱动后,在硬件设备列表中就会出现新的设备:ST-LINK虚拟串口。
如果使用的是Linux的PC或Mac,你会在/ dev目录中发现一个新的终端设备。一般情况下,该设备会以类似于tty.usbmodemXXXX被命名,如下所示:
串口在大多数情况下是有用的,这有两个原因:如果你想要调试你的固件的打印信息(对于ARM架构不是绝对必要的,因为我们也可以使用ARM半主控),或者如果你想要在NUCLEO板和PC之间交换指令和消息(或许,你正在使用创建中的专用的应用程序)。 在这篇文章中我将演示如何正确地配置和使用STM32 NUCLEO板集成的虚拟串口。但是,我们开始编写代码之前,先来看看硬件,这可能是真正有用的。 ST提供STM32 NUCLEO板的全部硬件项目(该板的设计使用Altium Designer的CAD,电子工业中使用的专业的CAD工具,但你不需要有一个如此昂贵的软件来使用您的NUCLEO板)。我采用的是NUCLEO - F401RE型号,但它应该是很容易重新安排指令以便正确使用你的具体的NUCLEO板。
一、引脚 像STM32复杂而灵活的MCU都提供复用功能的的I / O。这意味着,在我们可以用一个外围设备(如我们的例子中的USART)之前,需要配置和相应引脚的相关外设。查看STM32CubeMX工具,我们发现,STM32F401RETx处理器有3个不同的USART:USART1,USART2和USART6。
现在我们来看一看NUCLEO板的原理图。正如我们在下图看到的,USART_TX和USART_RX端口连接到PA2和PA3引脚。也就是说,NUCLEO被配置为使用目标MCU的USART2外设。
到此,我们已经手握需要开始编程所需的硬件相关的所有必要信息。
二、代码 在我们开始配置USART2外设时,我们需要建立一个测试工程。我们将使用GCC ARM Eclipse插件生成一个空项目,正如我在系列关于STM32平台的GCC工具链中的介绍。当您生成测试工程时,可以使用下面的配置参数。
如果你已经按照我以前的GNU Eclipse插件教程,那么你已经知道如何使用插件生成NUCLEO-F4板不正确的时钟配置。我已经展示了如何使用STM32CubeMX工具生成正确的时钟初始化代码。为简单起见,这是你必须把以下代码放入到_initialize_hardware.c文件中。 - void
- configure_system_clock(void)
- {
- RCC_OscInitTypeDef RCC_OscInitStruct;
- RCC_ClkInitTypeDef RCC_ClkInitStruct;
- __PWR_CLK_ENABLE();
- __HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE2);
- RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI;
- RCC_OscInitStruct.HSIState = RCC_HSI_ON;
- RCC_OscInitStruct.HSICalibrationValue = 6;
- RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
- RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSI;
- RCC_OscInitStruct.PLL.PLLM = 16;
- RCC_OscInitStruct.PLL.PLLN = 336;
- RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV4;
- RCC_OscInitStruct.PLL.PLLQ = 7;
- HAL_RCC_OscConfig(&RCC_OscInitStruct);
- RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_SYSCLK|RCC_CLOCKTYPE_PCLK1;
- RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
- RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
- RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV2;
- RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;
- HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_2);
- }
复制代码下一步,我们要添加一个配置USART接口的函数。我们定义为MX_USART2_UART_Init,如下所示。 - UART_HandleTypeDef huart2;
- ...
- void MX_USART2_UART_Init(void)
- {
- huart2.Instance = USART2;
- huart2.Init.BaudRate = 115200;
- huart2.Init.WordLength = UART_WORDLENGTH_8B;
- huart2.Init.StopBits = UART_STOPBITS_1;
- huart2.Init.Parity = UART_PARITY_NONE;
- huart2.Init.Mode = UART_MODE_TX_RX;
- huart2.Init.HwFlowCtl = UART_HWCONTROL_NONE;
- HAL_UART_Init(&huart2);
- }
复制代码该函数非常容易理解,huart2是UART_HandleTypeDef描述符的一个实例。它是用于配置UART外设的结构体。但是,此代码仍不足以使用UART。我们仍需要配置硬件部分,配置正确的引脚和初始化相关UART外设正确的时钟。这项工作由下面的钩子函数完成: - ...
- void HAL_UART_MspInit(UART_HandleTypeDef* huart)
- {
- GPIO_InitTypeDef GPIO_InitStruct;
- if(huart->Instance==USART2)
- {
- __GPIOA_CLK_ENABLE();
- __USART2_CLK_ENABLE();
- /**USART2 GPIO Configuration
- PA2 ------> USART2_TX
- PA3 ------> USART2_RX
- */
- GPIO_InitStruct.Pin = GPIO_PIN_2|GPIO_PIN_3;
- GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
- GPIO_InitStruct.Pull = GPIO_NOPULL;
- GPIO_InitStruct.Speed = GPIO_SPEED_LOW;
- GPIO_InitStruct.Alternate = GPIO_AF7_USART2;
- HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
- }
- }
- ...
复制代码即使在这个例子里,该代码也是很容易理解的。首先,我们需要初始化PORTA GPIO的外设时钟。接下来,我们需要启用与UART2外设相关的时钟。最后,我们必须正确配置PIN2、PIN3作为UART2 TX和RX UART2。 在这值得一提的一个重要方面是,我们并不需要在初始化部分显式调用该功能。这是一个钩子函数,由我们在函数MX_USART2_UART_Init()内调用的HAL_UART_Init()函数自动调用。调用这个初始化函数的正确地方是在_initialize_hardware.c文件的__initialize_hardware()函数中。 那么现在,我们只需要编写一个简单的main()函数来测试UART。 - int main(int argc, char* argv[])
- {
- char *msg = "Hello Nucleo Fun!\n\r";
- HAL_UART_Transmit(&huart2, (uint8_t*)msg, strlen(msg), 0xFFFF);
- while(1);
- }
复制代码main()函数非常简单:它只是在UART打印输出一条消息和一直挂起。 我们编译整个项目之前,我们需要做另一项最后的操作。默认情况下,Eclipse的GNU-ARM插件禁用未使用的STM32 HAL文件,以加快编译操作。因此,我们需要启用stm32f4xx_hal_uart.c文件的编译。 进入到Project Explorer->system->src->stm32f4-hal ,然后在stm32f4xx_hal_uart.c文件上点击鼠标右键,如下图所示:
点击“属性”,然后转到C / C ++编译和取消选中“从生成排除”,如下图所示。
现在,我们可以编译测试工程,并使用GDB和OpenOCD上传到我们的NUCLEO板。
要想看到在UART的消息,根据使用的操作系统你有几个选项。在Eclipse市场,你会发现一些终端仿真器插件。 TCF是其中之一。对于Windows操作系统另一个选择是使用putty。在Mac和Linux ckermit是一个合适的选择。
|