串口USART:同步异步串行全双公
通常为96-N-8-1(9600波特率,无校验位,8个有效数据位,1位停止位)
串行通信:一位一位进行传输(传输线少,成本低)
并行通信:多条数据线同时传递数据,一次性传递过去数据 (抗干扰能力弱)
异步通信:以字符为单位(间隔任意)字符里的数据间隔一定;发送接受时的时钟可以不一致(要相似);抗干扰能力强
同步通信:由一方控制另一方的时钟
半双工:RX-TX进行时,另一方的RX-TX不能进行,只能进行一个
全双工:RX-TX进行时,另一方的RX-TX也可以进行
速率:比特率:每秒钟传输二进制代码的位数
接收发送时双方要共地
UART:异步收发器;去掉了同步通信功能
看下图:
nRTS、nCTS硬件流控制(一般不用)(1)
数据发送:数据寄存器DR-发送寄存器TDR-发送移位寄存器(2)
数据接收:移位寄存器-接收数据寄存器RDR-数据寄存器DR(2)
发送器控制,接收器控制(3)
4为波特率



软件设计流程:
- 使能串口时钟以及GPIO端口时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1,ENABLE);
- GPIO端口模式设置,设置串口对应的引脚为复用功能
- 初始化串口参数(波特率;字长;停止位;校验位;USART模式;硬件流控制)
cs
typedef struct
{
uint32_t USART_BaudRate; //配置 USART 通信波特率
uint16_t USART_WordLength;//传输或接收的数据位数量
此参数可以是 @ref USART_Word_Length 中的一个值
uint16_t USART_StopBits;//指定传输的停止位数量
//此参数可以是 @ref USART_Stop_Bits 中的一个值
uint16_t USART_Parity; // 指定奇偶校验模式
// 此参数可以是 @ref USART_Parity 中的一个值;当启用奇偶校验时,计算出的校验位会插入到传输数据的最高有效位(MSB)位置(当字长设为9位时为第9位; 当字长设为8位时为第8位)
uint16_t USART_Mode; // 指定接收或发送模式或者接发同时
uint16_t USART_HardwareFlowControl; //指定硬件流控制模式
参数是 USART_Hardware_Flow_Control 中的一个值
} USART_InitTypeDef;
- 使能串口
cs
/**
* @brief 启用或禁用 USART 外设
* @param USARTx: 指向 USART_TypeDef 结构体的指针,标识目标 USART 外设
* @param NewState: 新状态,取值为 ENABLE 或 DISABLE
*/
void USART_Cmd(USART_TypeDef* USARTx, FunctionalState NewState)
- 设置串口中断类型并使能
cs
/**
* @brief 配置 USART 的中断使能状态
* @param USARTx: 指向 USART_TypeDef 结构体的指针,标识目标 USART 外设
* @param USART_IT: 指定要配置的 USART 中断源
* 可取值为 @ref USART_Interrupt_Sources 中的一个或多个值的组合
* @param NewState: 新状态,取值为 ENABLE 或 DISABLE
* @retval 无
*/
void USART_ITConfig(USART_TypeDef* USARTx, uint16_t USART_IT, FunctionalState NewState)
- 设置串口中断优先级使能串口通信(NVIC模块)
- 编写串口中断服务函数(判断用了那种串口中断类型标志位的状态)
cs
/**
* @brief 检查指定的 USART 中断状态标志
* @param USARTx: 指向 USART_TypeDef 结构体的指针,标识目标 USART 外设
* @param USART_IT: 指定要检查的 USART 中断源
* 可取值为 @ref USART_Interrupt_Sources 中的一个值
* @retval ITStatus: 中断状态
* - SET: 中断标志被设置
* - RESET: 中断标志未被设置
*/
ITStatus USART_GetITStatus(USART_TypeDef* USARTx, uint16_t USART_IT)
- 接收函数:uint16_t USART_ReceiveData(USART_TypeDef* USARTx)
- 发送函数: void USART_SendData(USART_TypeDef* USARTx, uint16_t Data)
- 串口的标志位:
- 发送标志位:USART_IT_TXE:发送寄存器-1为空;可进行数据发送
USART_IT_TC:发送完成标志位-1为发送完成
- 接收标志位:USART_IT_RXNE:接受寄存器-1为空;可进行数据接收
代码实现:USART1与PC机对话
USART1_RX_STA
就像一个 "光标",指示下一个数据的存储位置
cs
#include "usart1.h"
//注意,读取USARTx->SR能避免莫名其妙的错误
u8 USART1_RX_BUF[USART1_REC_LEN]; //接收缓冲,最大USART_REC_LEN个字节.
//接收状态
//bit15, 接收完成标志
//bit14, 接收到0x0d
//bit13~0, 接收到的有效字节数目
u16 USART1_RX_STA=0; //接收状态标记
/*******************************************************************************
* 函 数 名 : USART1_Init
* 函数功能 : USART1初始化函数
* 输 入 : bound:波特率
* 输 出 : 无
*******************************************************************************/
void USART1_Init(u32 bound)
{
//GPIO端口设置
GPIO_InitTypeDef GPIO_InitStructure;
USART_InitTypeDef USART_InitStructure;
NVIC_InitTypeDef NVIC_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1,ENABLE);
/* 配置GPIO的模式和IO口 */
GPIO_InitStructure.GPIO_Pin=GPIO_Pin_9;//TX //串口输出PA9
GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AF_PP; //复用推挽输出
GPIO_Init(GPIOA,&GPIO_InitStructure); /* 初始化串口输入IO */
GPIO_InitStructure.GPIO_Pin=GPIO_Pin_10;//RX //串口输入PA10
GPIO_InitStructure.GPIO_Mode=GPIO_Mode_IN_FLOATING; //模拟输入
GPIO_Init(GPIOA,&GPIO_InitStructure); /* 初始化GPIO */
//USART1 初始化设置
USART_InitStructure.USART_BaudRate = bound;//波特率设置
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
USART_ClearFlag(USART1, USART_FLAG_TC);//清除TC位
USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);//开启相关中断
//Usart1 NVIC 配置
NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;//串口1中断通道
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=3;//抢占优先级3
NVIC_InitStructure.NVIC_IRQChannelSubPriority =3; //子优先级3
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ通道使能
NVIC_Init(&NVIC_InitStructure); //根据指定的参数初始化VIC寄存器、
}
/*******************************************************************************
* 函 数 名 : USART1_IRQHandler
* 函数功能 : USART1中断函数
* 输 入 : 无
* 输 出 : 无
*******************************************************************************/
void USART1_IRQHandler(void) //串口1中断服务程序
{
u8 r;
if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET) //接收中断
{
r =USART_ReceiveData(USART1);//(USART1->DR); //读取接收到的数据
if((USART1_RX_STA&0x8000)==0)//接收未完成
{
if(USART1_RX_STA&0x4000)//接收到了0x0d
{
if(r!=0x0a)USART1_RX_STA=0;//接收错误,重新开始
else USART1_RX_STA|=0x8000; //接收完成了
}
else //还没收到0X0D
{
if(r==0x0d)USART1_RX_STA|=0x4000;
else
{
USART1_RX_BUF[USART1_RX_STA&0X3FFF]=r;//前13位用来存储数据
USART1_RX_STA++;//位数加1指向下一个存储位置
if(USART1_RX_STA>(USART1_REC_LEN-1))USART1_RX_STA=0;//接收数据错误,重新开始接收
}
}
}
}
}
主函数代码
cs
#include "system.h"
#include "SysTick.h"
#include "led.h"
#include "usart1.h"
int main()
{
u8 i=0;
u16 t=0;
u16 len=0;
SysTick_Init(72);
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); //中断优先级分组 分2组
USART1_Init(115200);
LED_Init();
while(1)
{
if(USART1_RX_STA&0x8000)//接受完成
{
len=USART1_RX_STA&0x3fff;//得到此次接收到的数据长度
for(t=0;t<len;t++)
{
USART_SendData(USART1, USART1_RX_BUF[t]); //向串口1发送数据
while(USART_GetFlagStatus(USART1,USART_FLAG_TC)!=SET);//等待发送结束
}
USART1_RX_STA=0;//为了将15位值0方便下次接受
}
i++;
if(i%20==0)
{
LED1=!LED1;
}
delay_ms(10);
}
}
printf重定义:

要记得引用头文件
#include "stdio.h"
在usart.c文件中添加
cs
int fputc(int ch,FILE *p) //函数默认的,在使用printf函数时自动调用
{
USART_SendData(USART1,(u8)ch);
while(USART_GetFlagStatus(USART1,USART_FLAG_TXE)==RESET);
return ch;
}
主函数
cs
int main()
{
u8 i=0;
u16 data=1234;
float fdata=12.34;
char str[]="Hello World!";
SysTick_Init(72);
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); //中断优先级分组 分2组
LED_Init();
USART1_Init(115200);
while(1)
{
i++;
if(i%50==0)
{
LED1=!LED1;
printf("输出整型数data=%d\r\n",data);
printf("输出浮点型数fdata=%0.2f\r\n",fdata);
printf("输出十六进制数data=%X\r\n",data);
printf("输出八进制数data=%o\r\n",data);
printf("输出字符串str=%s\r\n",str);
}
delay_ms(10);
}
}