STM32F103xE的USART异步数据传输示例
USART全称Universal Synchronous/Asynchronous Receiver/Transmitter
,是一种可以进行同步/异步通信的串行设备接口。
通过查阅STM32官方手册得之,STM32f10x系列一共有五个USART传输串口。其中USART1、USART2、USART3为同步/异步串行通信接口,USART4、USART5为异步串行通信接口。
STM32外设的初始化步骤基本上是:
- 使能外设时钟
- 配置外设所需要的I/O端口
- 配置外设
- 使能外设
根据这个步骤首先我们使能外设时钟
使能外设时钟
查阅手册
通过该图我们看到USART1位于总线APB2上面,而USART2、3和UART4、5位于总线APB1上面。
因此我们开启USART1的时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1,ENABLE);//开启USART1时钟
配置外设所需I/O端口
通过查阅STM32官方手册得之,STM32f10x系列一共有五个USART传输串口。其中USART1、USART2、USART3为同步/异步串行通信接口,USART4、USART5为异步串行通信接口。
在这里我们将使用USART1同步/异步串行通信接口为例,进行介绍。既然想通过USART1通信接口发送数据,那肯定GPIO引脚呀,因此继续在官方手册中查找
该表格清楚明了的说明了USART1的各个引脚。其中TX(Transmit data
发送数据输出)、RX(Receive data
接受数据输入)、CK(Clock
发送时钟输出)、CTS(Clear to Send
允许发送)、RTS(Request to Send
请求发送)分别对应于PA09、PA10、PA08、PA11、PA12。
因此我们配置I/O端口:
GPIO_InitTypeDef GPIO_InitStrue;
//时钟使能
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
//GPIO10使能TX
GPIO_InitStrue.GPIO_Mode=GPIO_Mode_AF_PP;//复用推挽输出
GPIO_InitStrue.GPIO_Pin=GPIO_Pin_10; //10脚
GPIO_InitStrue.GPIO_Speed=GPIO_Speed_50MHz;//IO口速度为50MHz
GPIO_Init(GPIOB,&GPIO_InitStrue); //根据设定参数初始化GPIOB_10
//GPIO10使能RX
GPIO_InitStrue.GPIO_Mode=GPIO_Mode_IN_FLOATING;//浮空输入
GPIO_InitStrue.GPIO_Pin=GPIO_Pin_11;//11脚
GPIO_InitStrue.GPIO_Speed=GPIO_Speed_50MHz;//IO口速度为50MHz
GPIO_Init(GPIOB,&GPIO_InitStrue); //根据设定参数初始化GPIOB_11
配置外设
在这里外设当然是USART1啦。我们只需要根据自己的需要配置就行啦。主要的配置项有波特率
,有无硬件控制流
,发送/接受
,有无奇偶校验
,停止位
,数据位
。
其中波特率指的是数据传输到速度指每秒钟发送多少bit的数据;硬件控制流指是否通过CTS和RTS控制数据传输;有无奇偶校验则比较简单就是是否对传输的数据进行奇偶校验;因为USART接口传输需要对数据进行封装,即在原有的数据中加上开始位,在原始数据的尾部加上停止位,因此停止位值得就是停止位的长度;数据位指的是每次传输中有效数据的长度。
一个配置的示例:
USART_InitStrue.USART_BaudRate=9600;//波特率9600
USART_InitStrue.USART_HardwareFlowControl=USART_HardwareFlowControl_None;//无硬件流控制
USART_InitStrue.USART_Mode=USART_Mode_Rx|USART_Mode_Tx;//使能发送、接收
USART_InitStrue.USART_Parity=USART_Parity_No;//无基偶校验
USART_InitStrue.USART_StopBits=USART_StopBits_1;//停止位1位
USART_InitStrue.USART_WordLength=USART_WordLength_8b;//数据8位
USART_Init(USART1,&USART_InitStrue);//根据设定初始化USART1
使能外设
直接使能USART即可
USART_Cmd(USART1,ENABLE);
接下来配置USART1的中断
USART_ITConfig(USART1,USART_IT_RXNE,ENABLE);//开中断USART1
NVIC_InitStrue.NVIC_IRQChannel=USART1_IRQn;//通道
NVIC_InitStrue.NVIC_IRQChannelCmd=ENABLE;//使能
NVIC_InitStrue.NVIC_IRQChannelPreemptionPriority=1;//抢占优先级
NVIC_InitStrue.NVIC_IRQChannelSubPriority=1;//子优先级
NVIC_Init(&NVIC_InitStrue);
以及中断服务函数
在该函数中我们首先判断中断类型,是否为接受中断;如果是接受中断则接受字符并通过USART1发送出去,最后我们使用了一个while函数来确保数据成功发送。
//中断服务函数
void USART1_IRQHandler(void)
{
u8 USART1_in;
if(USART_GetITStatus(USART1,USART_IT_RXNE))
{
USART1_in=USART_ReceiveData(USART1);
USART_SendData(USART1, USART1_in);//向串口3发送数据
while(USART_GetFlagStatus(USART1,USART_FLAG_TC)!=SET);//等待发送结束
}
}
废话少说,直接上最终代码
配置IO引脚、USART、中断向量优先级等参数:
//串口初始化
void USART1_init()
{
GPIO_InitTypeDef GPIO_InitStrue;
USART_InitTypeDef USART_InitStrue;
NVIC_InitTypeDef NVIC_InitStrue;
//时钟使能
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1,ENABLE);
//GPIO10使能TX
GPIO_InitStrue.GPIO_Mode=GPIO_Mode_AF_PP;//复用推挽输出
GPIO_InitStrue.GPIO_Pin=GPIO_Pin_10; //10脚
GPIO_InitStrue.GPIO_Speed=GPIO_Speed_50MHz;//IO口速度为50MHz
GPIO_Init(GPIOB,&GPIO_InitStrue); //根据设定参数初始化GPIOB_10
//GPIO10使能RX
GPIO_InitStrue.GPIO_Mode=GPIO_Mode_IN_FLOATING;//浮空输入
GPIO_InitStrue.GPIO_Pin=GPIO_Pin_11;//11脚
GPIO_InitStrue.GPIO_Speed=GPIO_Speed_50MHz;//IO口速度为50MHz
GPIO_Init(GPIOB,&GPIO_InitStrue); //根据设定参数初始化GPIOB_11
//USART初始化
USART_InitStrue.USART_BaudRate=9600;//波特率9600
USART_InitStrue.USART_HardwareFlowControl=USART_HardwareFlowControl_None;//无硬件流控制
USART_InitStrue.USART_Mode=USART_Mode_Rx|USART_Mode_Tx;//使能发送、接收
USART_InitStrue.USART_Parity=USART_Parity_No;//无基偶校验
USART_InitStrue.USART_StopBits=USART_StopBits_1;//停止位1位
USART_InitStrue.USART_WordLength=USART_WordLength_8b;//数据8位
USART_Init(USART1,&USART_InitStrue);//根据设定初始化USART1
//USART1使能
USART_Cmd(USART1,ENABLE);
//开中断
USART_ITConfig(USART1,USART_IT_RXNE,ENABLE);//开中断USART1
NVIC_InitStrue.NVIC_IRQChannel=USART1_IRQn;//通道
NVIC_InitStrue.NVIC_IRQChannelCmd=ENABLE;//使能
NVIC_InitStrue.NVIC_IRQChannelPreemptionPriority=1;//抢占优先级
NVIC_InitStrue.NVIC_IRQChannelSubPriority=1;//子优先级
NVIC_Init(&NVIC_InitStrue);
}
中断接受函数
//中断服务函数
void USART1_IRQHandler(void)
{
u8 USART1_in;
if(USART_GetITStatus(USART1,USART_IT_RXNE))
{
USART1_in=USART_ReceiveData(USART1);
USART_SendData(USART1, USART1_in);//向串口3发送数据
while(USART_GetFlagStatus(USART1,USART_FLAG_TC)!=SET);//等待发送结束
}
}
将使用USART1同步/异步串行通信接口为例,进行介绍。既然想通过USART1通信接口发送数据,那肯定GPIO引脚呀,因此继续在官方手册中查找
废话少说,直接上代码
配置IO引脚、USART、中断向量优先级等参数:
//串口初始化
void USART1_init()
{
GPIO_InitTypeDef GPIO_InitStrue;
USART_InitTypeDef USART_InitStrue;
NVIC_InitTypeDef NVIC_InitStrue;
//时钟使能
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);
RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART1,ENABLE);
//GPIO10使能TX
GPIO_InitStrue.GPIO_Mode=GPIO_Mode_AF_PP;//复用推挽输出
GPIO_InitStrue.GPIO_Pin=GPIO_Pin_10; //10脚
GPIO_InitStrue.GPIO_Speed=GPIO_Speed_50MHz;//IO口速度为50MHz
GPIO_Init(GPIOB,&GPIO_InitStrue); //根据设定参数初始化GPIOB_10
//GPIO10使能RX
GPIO_InitStrue.GPIO_Mode=GPIO_Mode_IN_FLOATING;//浮空输入
GPIO_InitStrue.GPIO_Pin=GPIO_Pin_11;//11脚
GPIO_InitStrue.GPIO_Speed=GPIO_Speed_50MHz;//IO口速度为50MHz
GPIO_Init(GPIOB,&GPIO_InitStrue); //根据设定参数初始化GPIOB_11
//USART初始化
USART_InitStrue.USART_BaudRate=9600;//波特率9600
USART_InitStrue.USART_HardwareFlowControl=USART_HardwareFlowControl_None;//无硬件流控制
USART_InitStrue.USART_Mode=USART_Mode_Rx|USART_Mode_Tx;//使能发送、接收
USART_InitStrue.USART_Parity=USART_Parity_No;//无基偶校验
USART_InitStrue.USART_StopBits=USART_StopBits_1;//停止位1位
USART_InitStrue.USART_WordLength=USART_WordLength_8b;//数据8位
USART_Init(USART1,&USART_InitStrue);//根据设定初始化USART1
//USART1使能
USART_Cmd(USART1,ENABLE);
//开中断
USART_ITConfig(USART1,USART_IT_RXNE,ENABLE);//开中断USART1
NVIC_InitStrue.NVIC_IRQChannel=USART1_IRQn;//通道
NVIC_InitStrue.NVIC_IRQChannelCmd=ENABLE;//使能
NVIC_InitStrue.NVIC_IRQChannelPreemptionPriority=1;//抢占优先级
NVIC_InitStrue.NVIC_IRQChannelSubPriority=1;//子优先级
NVIC_Init(&NVIC_InitStrue);
}
中断接受函数
//中断服务函数
void USART1_IRQHandler(void)
{
u8 USART1_in;
if(USART_GetITStatus(USART1,USART_IT_RXNE))
{
USART1_in=USART_ReceiveData(USART1);
USART_SendData(USART1, USART1_in);//向串口3发送数据
while(USART_GetFlagStatus(USART1,USART_FLAG_TC)!=SET);//等待发送结束
}
}