5. 编写中断接收函数
配置对应的GPIO口对于STM32F4_Discovery开发板而言共有五个,选择UART5作为实验串口,其对应的IO口为PC12、PD2。
UART5_TX: PC12
UART5_RX: PD2
首先需要将对应的GPIO口配置为复用功能,如下所示:
GPIO_InitTypeDef gpioInitStructure; // // 使能对应的GPIO口时钟 RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOC | RCC_AHB1Periph_GPIOD, ENABLE); // // UART5 TX:PC12 RX:PD2 // GPIO_PinAFConfig(GPIOC, GPIO_PinSource12, GPIO_AF_UART5); GPIO_PinAFConfig(GPIOD, GPIO_PinSource2, GPIO_AF_UART5); // // PC12 gpioInitStructure.GPIO_Pin = GPIO_Pin_12; gpioInitStructure.GPIO_Mode = GPIO_Mode_AF; gpioInitStructure.GPIO_OType = GPIO_OType_PP; gpioInitStructure.GPIO_PuPd = GPIO_PuPd_UP; gpioInitStructure.GPIO_Speed = GPIO_Speed_2MHz; GPIO_Init(GPIOC, &gpioInitStructure); // PD2 gpioInitStructure.GPIO_Pin = GPIO_Pin_2; GPIO_Init(GPIOD, &gpioInitStructure);对于GPIO口的配置,实际上是对GPIO各个寄存器的配置。GPIO_PinAFConfig()函数作用是配置GPIOx_AFR寄存器,每个口的复用功能选择由四个位来配置(具体参考STM32F4XX参考手册),因此16个GPIO空需要两个32位寄存器,在STM32F4处理器中,分别是GPIOx_AFRL、GPIOx_AFRH。而在库函数中,将寄存器的地址对应到相应的结构体上,与这两个寄存器放在一个AFR[2]数组中,如下所示。
typedef struct { __IO uint32_t MODER; /*!< GPIO port mode register, Address offset: 0x00 */ __IO uint32_t OTYPER; /*!< GPIO port output type register, Address offset: 0x04 */ __IO uint32_t OSPEEDR; /*!< GPIO port output speed register, Address offset: 0x08 */ __IO uint32_t PUPDR; /*!< GPIO port pull-up/pull-down register, Address offset: 0x0C */ __IO uint32_t IDR; /*!< GPIO port input data register, Address offset: 0x10 */ __IO uint32_t ODR; /*!< GPIO port output data register, Address offset: 0x14 */ __IO uint16_t BSRRL; /*!< GPIO port bit set/reset low register, Address offset: 0x18 */ __IO uint16_t BSRRH; /*!< GPIO port bit set/reset high register, Address offset: 0x1A */ __IO uint32_t LCKR; /*!< GPIO port configuration lock register, Address offset: 0x1C */ __IO uint32_t AFR[2]; /*!< GPIO alternate function registers, Address offset: 0x20-0x24 */ } GPIO_TypeDef;GPIO_Init()函数作用是配置GPIO口的输出输入功能,将GPIO_TypeDef结构体中的寄存器依次配置为相应的模式。
GPIO口配置完成之后,需要配置UART口。
UART口配置配置UART口的同时,需要配置对应的接收中断,对应代码如下:
NVIC_InitTypeDef nvicInitStructure; USART_InitTypeDef uartInitStructure; //使能uart5时钟 RCC_APB1PeriphClockCmd(RCC_APB1Periph_UART5 , ENABLE); // // 配置UART5 uartInitStructure.USART_BaudRate = 9600; uartInitStructure.USART_Mode = USART_Mode_Tx | USART_Mode_Rx; uartInitStructure.USART_WordLength = USART_WordLength_8b; uartInitStructure.USART_StopBits = USART_StopBits_1; uartInitStructure.USART_Parity = USART_Parity_No; uartInitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None; USART_Init(UART5, &uartInitStructure); // // 配置外设接受中断 nvicInitStructure.NVIC_IRQChannel = UART5_IRQn; nvicInitStructure.NVIC_IRQChannelPreemptionPriority = 0; nvicInitStructure.NVIC_IRQChannelSubPriority = 0; nvicInitStructure.NVIC_IRQChannelCmd = ENABLE; NVIC_Init(&nvicInitStructure); // USART_Cmd(UART5, ENABLE);配置UART5的过程主要由USART_Init()函数实现,该函数完成对UART寄存器的配置。在库函数中,UART寄存器如下所示:
typedef struct { __IO uint16_t SR; /*!< USART Status register, Address offset: 0x00 */ uint16_t RESERVED0; /*!< Reserved, 0x02 */ __IO uint16_t DR; /*!< USART Data register, Address offset: 0x04 */ uint16_t RESERVED1; /*!< Reserved, 0x06 */ __IO uint16_t BRR; /*!< USART Baud rate register, Address offset: 0x08 */ uint16_t RESERVED2; /*!< Reserved, 0x0A */ __IO uint16_t CR1; /*!< USART Control register 1, Address offset: 0x0C */ uint16_t RESERVED3; /*!< Reserved, 0x0E */ __IO uint16_t CR2; /*!< USART Control register 2, Address offset: 0x10 */ uint16_t RESERVED4; /*!< Reserved, 0x12 */ __IO uint16_t CR3; /*!< USART Control register 3, Address offset: 0x14 */ uint16_t RESERVED5; /*!< Reserved, 0x16 */ __IO uint16_t GTPR; /*!< USART Guard time and prescaler register, Address offset: 0x18 */ uint16_t RESERVED6; /*!< Reserved, 0x1A */ } USART_TypeDef;UART寄存器详细内容可以参考STM32F4中文手册,这里简单介绍下以下几个寄存器:
SR寄存器:状态寄存器,包含了一些标志位,如TXE(发送数据寄存器为空)、TC(发送完成)、RXNE(读取数据寄存器不为空)