国民技术
直播中

HonestQiao

8年用户 520经验值
擅长:嵌入式技术
私信 关注
[经验]

【国民技术N32项目移植】明明白白弄懂N32G45x的USART/UART端口复用

N32G45x系统上,提供了多组USART/UART,通过用户手册中的总线架构图,可以了解详细的情况:

image.png

从上图中可以看到,可以使用的USART/UART有USART1、USART2、USART3、UART4、UART5、UART6、UART7,多达7个。
其中USART1、UART6、UART7挂在APB2上,而USART、USART3、UART4、UART5挂在APB1上,最后APB1、APB2才连接到AHB。

从上面的命名可以看出,N32串口的命名顺序和友商的有一点点不同,部分友商的为0开头,而N32的为1开头。

在这里,有几点基础知识需要先了解一下:

  • UART:Universal Asynchronous Receiver/Transmitter,通用非同步收發傳輸器
  • USART:Universal Synchronous/Asynchronous Receiver/Transmitter,通用同步非同步收發傳輸器
  • AHB:Advanced High-performance Bus, 高速总线,用来接高速外设的
  • APB:APB (Advanced Peripheral Bus) 低速总线,用来接低速外设的

相对于SRAM、SDIO这些来说,即使是SPI也属于慢速,更别提USART/UART了,所以USART/UART挂在APB上,再由APB桥接到AHB上。
再上述总线架构图中,可以看到由APB1、APB2。N32G45x系统包含 2 个 AHB2APB 桥,即 AHB2APB1 和 AHB2APB2。其中 APB1 包含 26 个低速 APB 外设, PCLK1 的最高速度为 36MHz;APB2 包含 18 个高速 APB 外设,PCLK2 最高速度等于 72MHz。

正是因为不同的USART/UART,挂在不同的APB上,所以在进行对应功能的复位和时钟初始化的时候,需要使用对应的APB参数,否则功能不正常。后续代码部分,将会具体说明。

同一个USART/UART,往往不止对应到一组IO端口上,而是由多组可供复用使用。
从用户手册中,可以了解到具体情况:
image.png

image.png

从上面的图可以看出,每一个USART/UART,都有多组IO端口可供复用使用。
但同一时刻,一个USART/UART只能映射到1组IO端口,不能多组同时使用。

在部分友商的系统中,复用不同的IO端口,直接在初始化的时候指定即可。但N32中,不仅要指定,还要在代码中,配置相应的寄存器(AFIO_RMP_CFG, AFIO_RMP_CFGx),所复用功能就和其原来的IO端口断开,重新映射到新的IO端口上了。

从复用对照表中,可以查看具体的USART/UART可复用的IO端口组:
image.png

如上图,USART1默认组为PA9、PA10,复用组有一组为PB6、PB7
下面,以实力进行说明,分别使用默认的IO组,以及使用复用的IO组。

当使用默认的IO组时,使用如下的代码:

// 定义UART1默认对应的配置
#define USARTx_NAME     "USART1"
#define USARTx          USART1
#define USARTx_CLK      RCC_APB2_PERIPH_USART1
#define USARTx_GPIO_CLK RCC_APB2_PERIPH_GPIOA
#define USARTx_GPIO     GPIOA
#define USARTx_RxPin    GPIO_PIN_10
#define USARTx_TxPin    GPIO_PIN_9

#define USART_APBxClkCmd RCC_EnableAPB2PeriphClk
#define GPIO_APBxClkCmd  RCC_EnableAPB2PeriphClk

//  CLK初始化
GPIO_APBxClkCmd(USARTx_GPIO_CLK | RCC_APB2_PERIPH_AFIO, ENABLE);
USART_APBxClkCmd(USARTx_CLK, ENABLE);

// GPIO初始化
GPIO_InitType GPIO_InitStructure;
// TX引脚
GPIO_InitStructure.Pin        = USARTx_TxPin;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode  = GPIO_Mode_AF_PP;
GPIO_InitPeripheral(USARTx_GPIO, &GPIO_InitStructure);

// RX引脚
GPIO_InitStructure.Pin       = USARTx_RxPin;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
GPIO_InitPeripheral(USARTx_GPIO, &GPIO_InitStructure);

// 定义USART通讯参数
USART_InitStructure.BaudRate            = 115200;
USART_InitStructure.WordLength          = USART_WL_8B;
USART_InitStructure.StopBits            = USART_STPB_1;
USART_InitStructure.Parity              = USART_PE_NO;
USART_InitStructure.HardwareFlowControl = USART_HFCTRL_NONE;
USART_InitStructure.Mode                = USART_MODE_RX | USART_MODE_TX;

// 初始化USART
USART_Init(USARTx, &USART_InitStructure);

// 使用USART
USART_Enable(USARTx, ENABLE);

为了方便更换端口,使用龙宏定义来进行一些配置,方便修改更换。
因为GPIOx都挂在APB2上,所以GPIO的CLK定义 USARTx_GPIO_CLK对应APB2上的RCC_APB2_PERIPH_GPIOA。
而USART1也挂在APB2上,所以USART2的CLK定义USARTx_CLK为APB2上的RCC_APB2_PERIPH_USART1。
同理,其各自对应的外设时钟使能调用都为RCC_EnableAPB2PeriphClk()。
如果使用了USART2/3、UART4/5,则其挂在APB1上,则对应的应使用APB1所关联的。

做好基础定义后,后面的步骤就是:

  1. 使能GPIO时钟
  2. 使能USART1时钟
  3. 初始化TX引脚
  4. 初始化RX引脚
  5. 定义通讯参数
  6. 启用USART1

在上述代码中,因为对应的引脚TX:PA9、RX:PA10,都在GPIOA,上,所以GPIO时钟初始化只有一个;TX和RX引脚,也都使用了同一个USARTx_GPIO。如果是不同的GPIO分组,则需要分别设置。

而如果要使用复用的IO组,则只需要在GPIO引脚初始化的部分,添加上复用的调用即可,具体如下:

// 定义UART1默认对应的配置
#define USARTx_NAME     "USART1_1"
#define USARTx          USART1
#define USARTx_CLK      RCC_APB2_PERIPH_USART1
#define USARTx_GPIO_CLK RCC_APB2_PERIPH_GPIOB
#define USARTx_GPIO     GPIOB
#define USARTx_RxPin    GPIO_PIN_7
#define USARTx_TxPin    GPIO_PIN_6

#define USART_APBxClkCmd RCC_EnableAPB2PeriphClk
#define GPIO_APBxClkCmd  RCC_EnableAPB2PeriphClk

#define USARTx_RMP  GPIO_RMP_USART1

//  CLK初始化
GPIO_APBxClkCmd(USARTx_GPIO_CLK | RCC_APB2_PERIPH_AFIO, ENABLE);
USART_APBxClkCmd(USARTx_CLK, ENABLE);

// GPIO初始化
GPIO_InitType GPIO_InitStructure;
// TX引脚
GPIO_InitStructure.Pin        = USARTx_TxPin;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode  = GPIO_Mode_AF_PP;
GPIO_InitPeripheral(USARTx_GPIO, &GPIO_InitStructure);

// RX引脚
GPIO_InitStructure.Pin       = USARTx_RxPin;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
GPIO_InitPeripheral(USARTx_GPIO, &GPIO_InitStructure);

// 复用
GPIO_ConfigPinRemap(USARTx_RMP, ENABLE);

// 定义USART通讯参数
USART_InitStructure.BaudRate            = 115200;
USART_InitStructure.WordLength          = USART_WL_8B;
USART_InitStructure.StopBits            = USART_STPB_1;
USART_InitStructure.Parity              = USART_PE_NO;
USART_InitStructure.HardwareFlowControl = USART_HFCTRL_NONE;
USART_InitStructure.Mode                = USART_MODE_RX | USART_MODE_TX;

// 初始化USART
USART_Init(USARTx, &USART_InitStructure);

// 使用USART
USART_Enable(USARTx, ENABLE);

主要逻辑和默认的类似,只是添加了GPIO_ConfigPinRemap()调用。

GPIO_ConfigPinRemap的第一个参数,定义在 n32g45x_gpio.h 中,其取值情况,对应着复用的分组情况,例如:
USART1只有一个复用分组:
image.png

那么就提供了一个复用映射调用:GPIO_RMP_USART1

而USART2有三组,则提供了三组复用映射调用:
image.png

GPIO_RMP1_USART2
GPIO_RMP2_USART2
GPIO_RMP3_USART2
上述表中,00 、01、10、11为二进制,对应0、1、2、3。使用默认组0时,不需要设置复用映射。

USART2、UART4-UART7的复用映射定义如下:

#define GPIO_RMP1_USART2 ((uint32_t)0x44200000) /*!< USART2 Alternate Function mapping */
#define GPIO_RMP2_USART2 ((uint32_t)0x44200008) /*!< USART2 Alternate Function mapping */
#define GPIO_RMP3_USART2 ((uint32_t)0x46200008) /*!< USART2 Alternate Function mapping */
#define GPIO_RMP1_UART4 ((uint32_t)0x40340010) /*!< UART4 Alternate Function mapping */
#define GPIO_RMP2_UART4 ((uint32_t)0x40340020) /*!< UART4 Alternate Function mapping */
#define GPIO_RMP3_UART4 ((uint32_t)0x40340030) /*!< UART4 Alternate Function mapping */
#define GPIO_RMP1_UART5 ((uint32_t)0x40360040) /*!< UART5 Alternate Function mapping */
#define GPIO_RMP2_UART5 ((uint32_t)0x40360080) /*!< UART5 Alternate Function mapping */
#define GPIO_RMP3_UART5 ((uint32_t)0x403600C0) /*!< UART5 Alternate Function mapping */
#define GPIO_RMP2_UART6 ((uint32_t)0x40380200) /*!< UART6 Alternate Function mapping */
#define GPIO_RMP3_UART6 ((uint32_t)0x40380300) /*!< UART6 Alternate Function mapping */
#define GPIO_RMP1_UART7 ((uint32_t)0x403A0400) /*!< UART7 Alternate Function mapping */
#define GPIO_RMP3_UART7 ((uint32_t)0x403A0C00) /*!< UART7 Alternate Function mapping */

取那个,就根据查表所看到的对应组的二进制码确定了。

但USART3的命名,又有一点点差异了。
image.png
USART3能使用的为0、1、3,0不用设置,而1、3对应的复用映射为:

#define GPIO_PART_RMP_USART3       ((uint32_t)0x00140010) /*!< USART3 Partial Alternate Function mapping */
#define GPIO_ALL_RMP_USART3        ((uint32_t)0x00140030) /*!< USART3 Full Alternate Function mapping */

在使用具体的IO引脚的时候,要注意查看数据手册,检测是否会与其他的功能冲突,例如:
image.png

image.png

如果你使用了UART4复用引脚PA13、PA14,如果你又用了对应的SWDIO、SWCLK,那么就会冲突了。

经过一番研究测试,尝试了部分复用端口:
image.png

以下为具体测试的代码:
main.h:包含多组复用配置

/**
 * [url=home.php?mod=space&uid=1455510]@file[/url] main.h
 */
#ifndef __MAIN_H__
#define __MAIN_H__

#ifdef __cplusplus
extern "C" {
#endif

#include "n32g45x.h"

// #define _USART1_COM_         // OK
// #define _USART1_COM_1_       // OK
// #define _USART2_COM_         // OK
// #define _USART2_COM_01_      // OK
// #define _USART3_COM_         // OK
// #define _USART3_COM_01_      // OK
// #define _USART3_COM_11_      // OK

// #define _UART4_COM_          // OK
#define _UART5_COM_             // OK
// #define _UART5_COM_11_       // OK
// #define _UART6_COM_          // OK
// #define _UART6_COM_10_       // OK
// #define _UART7_COM_          // OK
// #define _UART7_COM_01_       // OK
// #define _UART7_COM_11_       // 没引脚

#ifdef _USART1_COM_
#define USARTx_NAME     "USART1"
#define USARTx          USART1
#define USARTx_CLK      RCC_APB2_PERIPH_USART1
#define USARTx_GPIO_CLK RCC_APB2_PERIPH_GPIOA
#define USARTx_GPIO     GPIOA
#define USARTx_RxPin    GPIO_PIN_10
#define USARTx_TxPin    GPIO_PIN_9

#define USART_APBxClkCmd RCC_EnableAPB2PeriphClk
#define GPIO_APBxClkCmd  RCC_EnableAPB2PeriphClk

// #define USARTx_RMP  GPIO_RMP_USART1
#endif

#ifdef _USART1_COM_1_
#define USARTx_NAME     "USART1_1"
#define USARTx          USART1
#define USARTx_CLK      RCC_APB2_PERIPH_USART1
#define USARTx_GPIO_CLK RCC_APB2_PERIPH_GPIOB
#define USARTx_GPIO     GPIOB
#define USARTx_RxPin    GPIO_PIN_7
#define USARTx_TxPin    GPIO_PIN_6

#define USART_APBxClkCmd RCC_EnableAPB2PeriphClk
#define GPIO_APBxClkCmd  RCC_EnableAPB2PeriphClk

#define USARTx_RMP  GPIO_RMP_USART1
#endif

#ifdef _USART2_COM_
#define USARTx_NAME     "USART2"
#define USARTx          USART2
#define USARTx_CLK      RCC_APB1_PERIPH_USART2
#define USARTx_GPIO_CLK RCC_APB2_PERIPH_GPIOA
#define USARTx_GPIO     GPIOA
#define USARTx_RxPin    GPIO_PIN_3
#define USARTx_TxPin    GPIO_PIN_2

#define USART_APBxClkCmd RCC_EnableAPB1PeriphClk
#define GPIO_APBxClkCmd  RCC_EnableAPB2PeriphClk

// #define USARTx_RMP  GPIO_RMP_USART2
#endif

#ifdef _USART2_COM_01_
#define USARTx_NAME     "USART2_01"
#define USARTx          USART2
#define USARTx_CLK      RCC_APB1_PERIPH_USART2
#define USARTx_GPIO_CLK RCC_APB2_PERIPH_GPIOD
#define USARTx_GPIO     GPIOD
#define USARTx_RxPin    GPIO_PIN_6
#define USARTx_TxPin    GPIO_PIN_5

#define USART_APBxClkCmd RCC_EnableAPB1PeriphClk
#define GPIO_APBxClkCmd  RCC_EnableAPB2PeriphClk

#define USARTx_RMP  GPIO_RMP1_USART2
#endif


#ifdef _USART3_COM_
#define USARTx_NAME     "USART3"
#define USARTx          USART3
#define USARTx_CLK      RCC_APB1_PERIPH_USART3
#define USARTx_GPIO_CLK RCC_APB2_PERIPH_GPIOB
#define USARTx_GPIO     GPIOB
#define USARTx_RxPin    GPIO_PIN_11
#define USARTx_TxPin    GPIO_PIN_10

#define USART_APBxClkCmd RCC_EnableAPB1PeriphClk
#define GPIO_APBxClkCmd  RCC_EnableAPB2PeriphClk

// #define USARTx_RMP  GPIO_RMP1_USART3
#endif

#ifdef _USART3_COM_01_
#define USARTx_NAME     "USART3_01"
#define USARTx          USART3
#define USARTx_CLK      RCC_APB1_PERIPH_USART3
#define USARTx_GPIO_CLK RCC_APB2_PERIPH_GPIOC
#define USARTx_GPIO     GPIOC
#define USARTx_RxPin    GPIO_PIN_11
#define USARTx_TxPin    GPIO_PIN_10

#define USART_APBxClkCmd RCC_EnableAPB1PeriphClk
#define GPIO_APBxClkCmd  RCC_EnableAPB2PeriphClk

#define USARTx_RMP  GPIO_PART_RMP_USART3
#endif

#ifdef _USART3_COM_11_
#define USARTx_NAME     "USART3_11"
#define USARTx          USART3
#define USARTx_CLK      RCC_APB1_PERIPH_USART3
#define USARTx_GPIO_CLK RCC_APB2_PERIPH_GPIOD
#define USARTx_GPIO     GPIOD
#define USARTx_RxPin    GPIO_PIN_9
#define USARTx_TxPin    GPIO_PIN_8

#define USART_APBxClkCmd RCC_EnableAPB1PeriphClk
#define GPIO_APBxClkCmd  RCC_EnableAPB2PeriphClk

#define USARTx_RMP  GPIO_ALL_RMP_USART3
#endif

#ifdef _UART4_COM_
#define USARTx_NAME     "UART4"
#define USARTx          UART4
#define USARTx_CLK      RCC_APB1_PERIPH_UART4
#define USARTx_GPIO_CLK RCC_APB2_PERIPH_GPIOC
#define USARTx_GPIO     GPIOC
#define USARTx_RxPin    GPIO_PIN_11
#define USARTx_TxPin    GPIO_PIN_10

#define USART_APBxClkCmd RCC_EnableAPB1PeriphClk
#define GPIO_APBxClkCmd  RCC_EnableAPB2PeriphClk

// #define USARTx_RMP  GPIO_RMP1_UART4
#endif

#ifdef _UART5_COM_
#define USARTx_NAME     "UART5"
#define USARTx          UART5
#define USARTx_CLK      RCC_APB1_PERIPH_UART5
#define USARTx_GPIO_CLK RCC_APB2_PERIPH_GPIOC
#define USARTx_GPIO_CLK_Rx RCC_APB2_PERIPH_GPIOD
#define USARTx_GPIO     GPIOC
#define USARTx_GPIO_Rx  GPIOD
#define USARTx_RxPin    GPIO_PIN_2
#define USARTx_TxPin    GPIO_PIN_12

#define USART_APBxClkCmd RCC_EnableAPB1PeriphClk
#define GPIO_APBxClkCmd  RCC_EnableAPB2PeriphClk

// #define USARTx_RMP  GPIO_RMP1_UART5
#endif

#ifdef _UART5_COM_11_
#define USARTx_NAME     "UART5_11"
#define USARTx          UART5
#define USARTx_CLK      RCC_APB1_PERIPH_UART5
#define USARTx_GPIO_CLK RCC_APB2_PERIPH_GPIOB
#define USARTx_GPIO     GPIOB
#define USARTx_RxPin    GPIO_PIN_9
#define USARTx_TxPin    GPIO_PIN_8

#define USART_APBxClkCmd RCC_EnableAPB1PeriphClk
#define GPIO_APBxClkCmd  RCC_EnableAPB2PeriphClk

#define USARTx_RMP  GPIO_RMP3_UART5
#endif

#ifdef _UART6_COM_
#define USARTx_NAME     "UART6"
#define USARTx          UART6
#define USARTx_CLK      RCC_APB2_PERIPH_UART6
#define USARTx_GPIO_CLK RCC_APB2_PERIPH_GPIOE
#define USARTx_GPIO     GPIOE
#define USARTx_RxPin    GPIO_PIN_3
#define USARTx_TxPin    GPIO_PIN_2

#define USART_APBxClkCmd RCC_EnableAPB2PeriphClk
#define GPIO_APBxClkCmd  RCC_EnableAPB2PeriphClk

// #define USARTx_RMP  GPIO_RMP1_UART6
#endif

#ifdef _UART6_COM_10_
#define USARTx_NAME     "UART6_10"
#define USARTx          UART6
#define USARTx_CLK      RCC_APB2_PERIPH_UART6
#define USARTx_GPIO_CLK RCC_APB2_PERIPH_GPIOC
#define USARTx_GPIO     GPIOC
#define USARTx_RxPin    GPIO_PIN_1
#define USARTx_TxPin    GPIO_PIN_0

#define USART_APBxClkCmd RCC_EnableAPB2PeriphClk
#define GPIO_APBxClkCmd  RCC_EnableAPB2PeriphClk

#define USARTx_RMP  GPIO_RMP2_UART6
#endif

#ifdef _UART7_COM_
#define USARTx_NAME     "UART7"
#define USARTx          UART7
#define USARTx_CLK      RCC_APB2_PERIPH_UART7
#define USARTx_GPIO_CLK RCC_APB2_PERIPH_GPIOC
#define USARTx_GPIO     GPIOC
#define USARTx_RxPin    GPIO_PIN_5
#define USARTx_TxPin    GPIO_PIN_4

#define USART_APBxClkCmd RCC_EnableAPB2PeriphClk
#define GPIO_APBxClkCmd  RCC_EnableAPB2PeriphClk

// #define USARTx_RMP  GPIO_RMP1_UART7
#endif

#ifdef _UART7_COM_01_
#define USARTx_NAME     "UART7_01"
#define USARTx          UART7
#define USARTx_CLK      RCC_APB2_PERIPH_UART7
#define USARTx_GPIO_CLK RCC_APB2_PERIPH_GPIOC
#define USARTx_GPIO     GPIOC
#define USARTx_RxPin    GPIO_PIN_3
#define USARTx_TxPin    GPIO_PIN_2

#define USART_APBxClkCmd RCC_EnableAPB2PeriphClk
#define GPIO_APBxClkCmd  RCC_EnableAPB2PeriphClk

#define USARTx_RMP  GPIO_RMP1_UART7
#endif

#ifdef _UART7_COM_11_
#define USARTx_NAME     "UART7_11"
#define USARTx          UART7
#define USARTx_CLK      RCC_APB2_PERIPH_UART7
#define USARTx_GPIO_CLK RCC_APB2_PERIPH_GPIOC
#define USARTx_GPIO     GPIOG
#define USARTx_RxPin    GPIO_PIN_1
#define USARTx_TxPin    GPIO_PIN_0

#define USART_APBxClkCmd RCC_EnableAPB2PeriphClk
#define GPIO_APBxClkCmd  RCC_EnableAPB2PeriphClk

#define USARTx_RMP  GPIO_RMP3_UART7
#endif

#ifdef __cplusplus
}
#endif

#endif /* __MAIN_H__ */

main.c

/**
 * @file main.c
 */
#include <stdio.h>
#include "main.h"

/** @addtogroup USART_Printf
 * @{
 */

typedef enum
{
    FAILED = 0,
    PASSED = !FAILED
} TestStatus;

#define countof(a) (sizeof(a) / sizeof(*(a)))

USART_InitType USART_InitStructure;

void RCC_Configuration(void);
void GPIO_Configuration(void);
TestStatus Buffercmp(uint8_t* pBuffer1, uint8_t* pBuffer2, uint16_t BufferLength);

/**
 * [url=home.php?mod=space&uid=2666770]@Brief[/url]  Main program
 */
int main(void)
{
    /* System Clocks Configuration */
    RCC_Configuration();

    /* Configure the GPIO ports */
    GPIO_Configuration();

    /* USARTy and USARTz configuration ------------------------------------------------------*/
    USART_InitStructure.BaudRate            = 115200;
    USART_InitStructure.WordLength          = USART_WL_8B;
    USART_InitStructure.StopBits            = USART_STPB_1;
    USART_InitStructure.Parity              = USART_PE_NO;
    USART_InitStructure.HardwareFlowControl = USART_HFCTRL_NONE;
    USART_InitStructure.Mode                = USART_MODE_RX | USART_MODE_TX;

    /* Configure USARTx */
    USART_Init(USARTx, &USART_InitStructure);
    /* Enable the USARTx */
    USART_Enable(USARTx, ENABLE);

    /* Output a message on Hyperterminal using printf function */
    printf("\n\rUSART Printf Example: retarget the C library printf function to the %s\n\r", USARTx_NAME);

    while (1)
    {
    }
}

/**
 * @brief  Configures the different system clocks.
 */
void RCC_Configuration(void)
{
    /* Enable GPIO clock */
    GPIO_APBxClkCmd(USARTx_GPIO_CLK | RCC_APB2_PERIPH_AFIO, ENABLE);
#ifdef USARTx_GPIO_CLK_Rx
    GPIO_APBxClkCmd(USARTx_GPIO_CLK_Rx | RCC_APB2_PERIPH_AFIO, ENABLE);
#endif    
    /* Enable USARTy and USARTz Clock */
    USART_APBxClkCmd(USARTx_CLK, ENABLE);
}

/**
 * @brief  Configures the different GPIO ports.
 */
void GPIO_Configuration(void)
{
    GPIO_InitType GPIO_InitStructure;

    /* Configure USARTx Tx as alternate function push-pull */
    GPIO_InitStructure.Pin        = USARTx_TxPin;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_InitStructure.GPIO_Mode  = GPIO_Mode_AF_PP;
    GPIO_InitPeripheral(USARTx_GPIO, &GPIO_InitStructure);

    /* Configure USARTx Rx as input floating */
    GPIO_InitStructure.Pin       = USARTx_RxPin;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
#ifdef USARTx_GPIO_Rx
    GPIO_InitPeripheral(USARTx_GPIO_Rx, &GPIO_InitStructure);
#else    
    GPIO_InitPeripheral(USARTx_GPIO, &GPIO_InitStructure);
#endif

#ifdef USARTx_RMP
    GPIO_ConfigPinRemap(USARTx_RMP, ENABLE);    
#endif
}

/**
 * @brief  Compares two buffers.
 * [url=home.php?mod=space&uid=3142012]@param[/url]  pBuffer1, pBuffer2: buffers to be compared.
 * @param BufferLength buffer's length
 * [url=home.php?mod=space&uid=1141835]@Return[/url] PASSED: pBuffer1 identical to pBuffer2
 *         FAILED: pBuffer1 differs from pBuffer2
 */
TestStatus Buffercmp(uint8_t* pBuffer1, uint8_t* pBuffer2, uint16_t BufferLength)
{
    while (BufferLength--)
    {
        if (*pBuffer1 != *pBuffer2)
        {
            return FAILED;
        }

        pBuffer1++;
        pBuffer2++;
    }

    return PASSED;
}

/* retarget the C library printf function to the USART */
int fputc(int ch, FILE* f)
{
    USART_SendData(USARTx, (uint8_t)ch);
    while (USART_GetFlagStatus(USARTx, USART_FLAG_TXDE) == RESET)
        ;

    return (ch);
}

#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
 */
void assert_failed(const uint8_t* expr, const uint8_t* file, uint32_t line)
{
    /* User can add his own implementation to report the file name and line number,
       ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */

    /* Infinite loop */
    while (1)
    {
    }
}

#endif

/**
 * @}
 */

/**
 * @}
 */

上述代码,是参考官方资料中的Printf的演示来的,可以将printf重定向到USART/UART输出,然后在此基础上,添加了复用设置。
其中UART5的配置,就包含了不同的时钟、不同的GPIO分组设定,可供参考。

image.png

编译烧录后,用串口工具连接对应的引脚,将会收到对应的串口输出的信息:
image.png

尝试启用main.h中不同的USART/UART分组,然后对照接线,再编译烧录,就能看到更新了。

有多达7组USART/UART使用,如果配合SPI接口的网卡,就能做一个多串口服务器了,想想都挺激动的。

更多回帖

发帖
×
20
完善资料,
赚取积分