USART功能在调试的时候经常会用到,配置也很方便。首先你得知道USART的一些基本知识,这里我没有选择使用硬件流控,所以算是UART,关于USART和UART的区别可以看这篇文章 http://blog.sina.com.cn/s/blog_5eaeb24d01011q57.html


USART的相关配置和GPIO类似,步骤如下

引脚配置

首先是配置所使用到的引脚,这里我们只需要USART_TX和USART_RX两个引脚,这里我们选择USART1,从芯片手册的截图中我们可以看到,USART1_TX和USART1_RX分别对应PA9和PA10。

stm32CUbemx的USART2禁用 stm32f4 usart_复用

引脚的配置和F103由些许区别,USART是F407的引脚复用功能,所以配置引脚需要配置成复用模式,配置代码如下:

/*这里只是部分配置代码,前面还有结构体声明和时钟初始化,最后会全部列出*/
	//串口1对应引脚复用映射
	GPIO_PinAFConfig(GPIOA,GPIO_PinSource9,GPIO_AF_USART1); //GPIOA9复用为USART1
	GPIO_PinAFConfig(GPIOA,GPIO_PinSource10,GPIO_AF_USART1); //GPIOA10复用为USART1

	//USART1端口配置
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9 | GPIO_Pin_10; //GPIOA9与GPIOA10
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;//复用功能
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;	//速度50MHz
	GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; //推挽复用输出
	GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP; //上拉
	GPIO_Init(GPIOA,&GPIO_InitStructure); //初始化PA9,PA10

使能USART时钟

配置好GPIO后我们来看看USART1的时钟配置,同样翻看F407的数据手册,从中我们可以看到,USART1的时钟由APB2总线提供,调用APB2时钟初始化函数即可。

stm32CUbemx的USART2禁用 stm32f4 usart_复用_02

RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1,ENABLE);//使能USART1时钟

USART初始化结构体

USART的配置信息都在“stm32f4xx_usart.h”头文件中,定义如下。

/** 
  * @brief  USART Init Structure definition  
  */ 
  
typedef struct
{
  uint32_t USART_BaudRate;            /*!< This member configures the USART communication baud rate.
                                           The baud rate is computed using the following formula:
                                            - IntegerDivider = ((PCLKx) / (8 * (OVR8+1) * (USART_InitStruct->USART_BaudRate)))
                                            - FractionalDivider = ((IntegerDivider - ((u32) IntegerDivider)) * 8 * (OVR8+1)) + 0.5 
                                           Where OVR8 is the "oversampling by 8 mode" configuration bit in the CR1 register. */

  uint16_t USART_WordLength;          /*!< Specifies the number of data bits transmitted or received in a frame.
                                           This parameter can be a value of @ref USART_Word_Length */

  uint16_t USART_StopBits;            /*!< Specifies the number of stop bits transmitted.
                                           This parameter can be a value of @ref USART_Stop_Bits */

  uint16_t USART_Parity;              /*!< Specifies the parity mode.
                                           This parameter can be a value of @ref USART_Parity
                                           @note When parity is enabled, the computed parity is inserted
                                                 at the MSB position of the transmitted data (9th bit when
                                                 the word length is set to 9 data bits; 8th bit when the
                                                 word length is set to 8 data bits). */
 
  uint16_t USART_Mode;                /*!< Specifies wether the Receive or Transmit mode is enabled or disabled.
                                           This parameter can be a value of @ref USART_Mode */

  uint16_t USART_HardwareFlowControl; /*!< Specifies wether the hardware flow control mode is enabled
                                           or disabled.
                                           This parameter can be a value of @ref USART_Hardware_Flow_Control */
} USART_InitTypeDef;
  • 1、USART_BaudRate
    第一个配置的是波特率,常用的有9600、19200、38400、57600、115200,越低的越稳定,所以我们只需选择满足我们需求的最低波特率即可。
  • 2、USART_WordLength
    第二个是USART的数据位宽,关于数据位宽,在STM32中WordLength需要包含数据位数和奇偶校验的位数。
    如果需要8位数据,无奇偶校验,则WordLength=8。
    如果需要8位数据,有奇偶校验,则WordLength=9。
/*数据位宽宏定义*/
#define USART_WordLength_8b                  ((uint16_t)0x0000)
#define USART_WordLength_9b                  ((uint16_t)0x1000)
  • 3、USART_StopBits
    第三个是停止位,它是一个字符数据的结束标志。可以是1位、1.5位、2位的高电平。 由于数据是在传输线上定时的,并且每一个设备有其自己的时钟,很可能在通信中两台设备间出现了小小的不同步。因此停止位不仅仅是表示传输的结束,并且提供计算机校正时钟同步的机会。适用于停止位的位数越多,不同时钟同步的容忍程度越大,但是数据传输率同时也越慢。
    STM32F407为我们提供了四种。
/*停止位宏定义*/
#define USART_StopBits_1                     ((uint16_t)0x0000)
#define USART_StopBits_0_5                   ((uint16_t)0x1000)
#define USART_StopBits_2                     ((uint16_t)0x2000)
#define USART_StopBits_1_5                   ((uint16_t)0x3000)
  • 4、USART_Parity
    第四个是奇偶校验位,奇偶校验和数据位宽的关系上面已经介绍,看自己需求配置。
/*奇偶校验宏定义*/
#define USART_Parity_No                      ((uint16_t)0x0000)
#define USART_Parity_Even                    ((uint16_t)0x0400)
#define USART_Parity_Odd                     ((uint16_t)0x0600)
  • 5、USART_Mode
/*USART模式选择*/
#define USART_Mode_Rx                        ((uint16_t)0x0004)
#define USART_Mode_Tx                        ((uint16_t)0x0008)

接下来选择USART的模式,发送、接收或者是发送接收都配置,一般都是发送和接收都配置,其赋值和选择Pin一样,可以用'|'来选择多个。其配置如下所示:

USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;	//收发模式
  • 6、 USART_HardwareFlowControl
    最后是否选择硬件流控,开头也说了这里不用,关于硬件流控可以去百度一下,以及USART和UART的区别所在。
/*硬件流控选项*/
#define USART_HardwareFlowControl_None       ((uint16_t)0x0000)
#define USART_HardwareFlowControl_RTS        ((uint16_t)0x0100)
#define USART_HardwareFlowControl_CTS        ((uint16_t)0x0200)
#define USART_HardwareFlowControl_RTS_CTS    ((uint16_t)0x0300)
  • 7、关于串口传输的一些概念:
    起始位:先发出一个逻辑”0”的信号,表示传输字符的开始。
    资料位:紧接着起始位之后。资料位的个数可以是4、5、6、7、8等,构成一个字符。通常采用ASCII码。从最低位开始传送,靠时钟定位。
    奇偶校验位:资料位加上这一位后,使得“1”的位数应为偶数(偶校验)或奇数(奇校验),以此来校验资料传送的正确性。
    停止位:它是一个字符数据的结束标志。可以是1位、1.5位、2位的高电平。 由于数据是在传输线上定时的,并且每一个设备有其自己的时钟,很可能在通信中两台设备间出现了小小的不同步。因此停止位不仅仅是表示传输的结束,并且提供计算机校正时钟同步的机会。适用于停止位的位数越多,不同时钟同步的容忍程度越大,但是数据传输率同时也越慢。
    空闲位:处于逻辑“1”状态,表示当前线路上没有资料传送。
    波特率:是衡量资料传送速率的指标。表示每秒钟传送的符号数(symbol)。一个符号代表的信息量(比特数)与符号的阶数有关。例如资料传送速率为120字符/秒,传输使用256阶符号,每个符号代表8bit,则波特率就是120baud,比特率是120*8=960bit/s。这两者的概念很容易搞错。

printf函数重定向

在C语言中,我们经常用printf函数来打印字符由我们的显示器来显示,使用起来很方便,这里我们也可以对printf函数重新定向,让他们可以打印串口数据,这里重定向的意思是指本来库函数fputc()是把字符输出到调试器控制窗口中去的,但用户把输出设备改成了UART端口,这样一来,所有基于fputc()函数的printf()系列函数输出都被重定向到UART端口上去了。

但要注意的是,此处如果要使用printf函数,需使用Keil的微库,将如下图片中Use MicroLIB复选框的勾打上即可。

stm32CUbemx的USART2禁用 stm32f4 usart_引脚_03

//printf函数重定向
int fputc(int ch,FILE *f)
{
  USART_SendData(USART1,(unsigned char)ch);
  while(USART_GetFlagStatus(USART1,USART_FLAG_TC)==RESET);
  return ch;
}

总结

到此USART的配置已经完成,可以发现,STM32的很多功能使用的步骤不外乎查看芯片手册对应硬件引脚等,查看库函数对应功能配置,也可以查看一些样例程序慢慢熟悉。如何使用可以看最后的样例,此处并没有用到串口中断以及DMA功能,只是常用的简单配置,先从易处入手,开始实践,以后可以慢慢了解STM32F407串口的更多功能。
完整代码如下:

void USART1_Config(u32 baudrate)
{
  //GPIO端口设置
  GPIO_InitTypeDef GPIO_InitStructure;
	USART_InitTypeDef USART_InitStructure;

	RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA,ENABLE); //使能GPIOA时钟
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1,ENABLE);//使能USART1时钟

	//串口1对应引脚复用映射
	GPIO_PinAFConfig(GPIOA,GPIO_PinSource9,GPIO_AF_USART1); //GPIOA9复用为USART1
	GPIO_PinAFConfig(GPIOA,GPIO_PinSource10,GPIO_AF_USART1); //GPIOA10复用为USART1

	//USART1端口配置
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9 | GPIO_Pin_10; //GPIOA9与GPIOA10
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;//复用功能
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;	//速度50MHz
	GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; //推挽复用输出
	GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP; //上拉
	GPIO_Init(GPIOA,&GPIO_InitStructure); //初始化PA9,PA10

   //USART1 初始化设置
	USART_InitStructure.USART_BaudRate = baudrate;//波特率设置
	USART_InitStructure.USART_WordLength = USART_WordLength_8b;//字长为8位数据格式
	USART_InitStructure.USART_StopBits = USART_StopBits_1;//一个停止位
	USART_InitStructure.USART_Parity = USART_Parity_No;//无奇偶校验位
	USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;//无硬件数据流控制
	USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;	//收发模式
  USART_Init(USART1, &USART_InitStructure); //初始化串口1

  USART_Cmd(USART1, ENABLE);  //使能串口1
}

//printf函数重定向
int fputc(int ch,FILE *f)
{
  USART_SendData(USART1,(unsigned char)ch);
  while(USART_GetFlagStatus(USART1,USART_FLAG_TC)==RESET);
  return ch;
}

main函数中调用测试测试:

#include "usart.h"
int main()
{
  USART1_Config(115200);
  for(;;)
  printf("hello world\n");
}