USART功能在调试的时候经常会用到,配置也很方便。首先你得知道USART的一些基本知识,这里我没有选择使用硬件流控,所以算是UART,关于USART和UART的区别可以看这篇文章 http://blog.sina.com.cn/s/blog_5eaeb24d01011q57.html 。关于硬件流控可以看看这篇文章 http://www.cnblogs.com/javawebsoa/archive/2013/05/23/3095617.html 。
USART的相关配置和GPIO类似,步骤如下
引脚配置
首先是配置所使用到的引脚,这里我们只需要USART_TX和USART_RX两个引脚,这里我们选择USART1,从芯片手册的截图中我们可以看到,USART1_TX和USART1_RX分别对应PA9和PA10。
引脚的配置和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时钟初始化函数即可。
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复选框的勾打上即可。
//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
");
}