目的:利用串口收发数据
配置文件:#include "stm32f10x_gpio.h"
#include "stm32f10x_rcc.h"
#include "stm32f10x_usart.h"
寄存器:USART_SR:状态寄存器,第5位RXNE,收到数据可以读出时置1,第6位TC, 发送完成时置1,第7位TXE,数据移至移位寄存器置1。
USART_DR:数据寄存器,高23位保留,低9位接收数据,分为发送寄存器TDR, 和接受寄存器RDR
UASRT_BRR:波特率寄存器,高16位保留,0-3位波特率整数部分,4-15位波特 率小数部分。
USART_CR1:控制寄存器,第2位RE接收使能,第3位TE发送使能,第9位 PS,奇偶校验位,奇校验置1,第10位PCE,校验控制使能,位12字长位,一个 起始位,8个数据位,一个停止位置1,n个停止位置0。位13UEUSART使能。
结构体定义:
USART寄存器结构体
typedef struct
{
__IO uint16_t SR;
uint16_t RESERVED0;
__IO uint16_t DR;
uint16_t RESERVED1;
__IO uint16_t BRR;
uint16_t RESERVED2;
__IO uint16_t CR1;
uint16_t RESERVED3;
__IO uint16_t CR2;
uint16_t RESERVED4;
__IO uint16_t CR3;
uint16_t RESERVED5;
__IO uint16_t GTPR;
uint16_t RESERVED6;
} USART_TypeDef;
USART初始化结构体
typedef struct
{
uint32_t USART_BaudRate; //波特率设置
uint16_t USART_WordLength; //字长设置
uint16_t USART_StopBits; //停止位设置
uint16_t USART_Parity; //奇偶校验选择
uint16_t USART_Mode; //串行通信模式设置
uint16_t USART_HardwareFlowControl; /硬件流控制设置
} USART_InitTypeDef;
参数宏定义如下:
#define USART_WordLength_8b ((uint16_t)0x0000)
#define USART_WordLength_9b ((uint16_t)0x1000)
#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)
#define USART_Parity_No ((uint16_t)0x0000)
#define USART_Parity_Even ((uint16_t)0x0400)
#define USART_Parity_Odd ((uint16_t)0x0600)
#define USART_Mode_Rx ((uint16_t)0x0004)
#define USART_Mode_Tx ((uint16_t)0x0008)
#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)
中断向量结构体配置与之前相同
注意配置时NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;
库函数:
USART_Init(USART_TypeDef* USARTx, USART_InitTypeDef* USART_InitStruct)USART初始为指定值,参数为USART结构体,USART初始化结构体。
其中USARTx有宏定义(x可为1~5)
#define USART1 ((USART_TypeDef *) USART1_BASE)
这里的USART1_BASE是
#define USART1_BASE (APB2PERIPH_BASE + 0x3800)是USART1的基地址,是一个无符号32位的数,将其进行强制类型转换,变为USART寄存器结构体的指针,也就指向了该结构体,对其操作也就是操作其中的寄存器,其余的也类似。
USART_DeInit(USART_TypeDef* USARTx)USART初始化为缺省值
USART_StructInit(USART_InitTypeDef* USART_InitStruct)USART1初始化
USART_Cmd(USART_TypeDef* USARTx, FunctionalState NewState)USART使能函数,参数USART寄存器结构体,使能变量
USART_ITConfig(USART_TypeDef* USARTx, uint16_t USART_IT, FunctionalState NewState)USART中断配置函数,参数USART寄存器结构体指针,标志位类型,使能状态变量
USART_DMACmd(USART_TypeDef* USARTx, uint16_t USART_DMAReq, FunctionalState NewState)
USART_SendData(USART_TypeDef* USARTx, uint16_t Data)USART发送函数,参数USART寄存器结构体,发送数据无符号16位
uint16_t USART_ReceiveData(USART_TypeDef* USARTx)USART接收函数,参数USART寄存器结构体,返回值无符号16位数值
ITStatus USART_GetITStatus(USART_TypeDef* USARTx, uint16_t USART_IT)USART检测标志位,参数USART寄存器结构体指针,和要查看的标志位,返回标志位状态
其中:
#define USART_FLAG_CTS ((uint16_t)0x0200)
#define USART_FLAG_LBD ((uint16_t)0x0100)
#define USART_FLAG_TXE ((uint16_t)0x0080)
#define USART_FLAG_TC ((uint16_t)0x0040)
#define USART_FLAG_RXNE ((uint16_t)0x0020)
#define USART_FLAG_IDLE ((uint16_t)0x0010)
#define USART_FLAG_ORE ((uint16_t)0x0008)
#define USART_FLAG_NE ((uint16_t)0x0004)
#define USART_FLAG_FE ((uint16_t)0x0002)
#define USART_FLAG_PE ((uint16_t)0x0001)
USART_ClearFlag(USART_TypeDef* USARTx, uint16_t USART_FLAG)USART清除标志位,参数USART寄存器结构体指针,要清除的标志位
USART_ClearITPendingBit(USART_TypeDef* USARTx, uint16_t USART_IT)作用同上
程序代码分析(代码出自FIRE)
USART配置:
void USART1_Config(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
USART_InitTypeDef USART_InitStructure;
/* config USART1 clock */
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1 | RCC_APB2Periph_GPIOA, ENABLE); //开两个时钟,分别为IO时钟和USART时钟
/* USART1 GPIO config */
/* Configure USART1 Tx (PA.09) as alternate function push-pull */
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;//复用功能,推挽输出
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);
/* Configure USART1 Rx (PA.10) as input floating */
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;//浮空输入
GPIO_Init(GPIOA, &GPIO_InitStructure);
/* USART1 mode config */
USART_InitStructure.USART_BaudRate = 115200;//波特率设置
USART_InitStructure.USART_WordLength = USART_WordLength_8b;//8位字长
USART_InitStructure.USART_StopBits = USART_StopBits_1;//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);//初始化
USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);//中断配置,接收中断
USART_Cmd(USART1, ENABLE);//USART使能
}
中断向量配置
void NVIC_Configuration(void)
{
NVIC_InitTypeDef NVIC_InitStructure;
/* Configure the NVIC Preemption Priority Bits */
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_0);
/* Enable the USARTy Interrupt */
NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
}
中断服务函数
void USART1_IRQHandler(void)
{
uint8_t ch;
if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET)
{
//ch = USART1->DR;
ch = USART_ReceiveData(USART1);
printf( "%c", ch ); //接收到的数据直接返回打印
}
}
重新定向printf函数到USART1
int fputc(int ch, FILE *f)
{
USART_SendData(USART1, (uint8_t) ch);
while (USART_GetFlagStatus(USART1, USART_FLAG_TC) == RESET);
return (ch);
}
int fgetc(FILE *f)
{
while (USART_GetFlagStatus(USART1, USART_FLAG_RXNE) == RESET);
return (int)USART_ReceiveData(USART1);
}
小总结:1、使用USART时注意TX RX口的GPIO配置
2、两种方式使用USART,一种使用中断,另一种直接查询标志位