绵绵STM32学习——USART

1. 概述

1.1 处理器与外部设备通信方式

1.1.1并行通信

  • 传输原理:数据各个位同时传输。
  • 优点:速度快
  • 缺点:占用引脚资源多

1.1.2 串行通信(本文重点讲解此通信方式

  • 传输原理:数据按位顺序传输
  • 优点:占用引脚资源少
  • 缺点:速度相对较慢

1.2 串行通信的数据传输方向

1.2.1 单工

数据传输只支持数据在一个方向上的传输

1.2.2 半双工

允许数据在两个方向上传输,但是,在某一时刻,只允许数据在一个方向上传输,他实际上是一种切换方向的单工通信

1.2.3 全双工

允许数据同时在两个方向上传输,因此,全双工通信时两个单工通信方式的结合,他要求发送设备和接收设备都有独立的接收和发送能力
在这里插入图片描述

1.3 串行通信的通信方式

1.3.1 同步通信

  • 带时钟同步信号传输(SPI,IIC通信接口)

1.3.2 异步通信

  • 不带时钟同步信号(UART:通用异步收发器,单总线)
    常见的串行通信接口
    在STM32中有UART和USART两种收发器,其中UART为通用异步收发器,USART为通用同步异步收发器(即可用与同步或者异步收发)

1.4 UART异步通信

1.4.1 引脚连接方法

在这里插入图片描述在这里插入图片描述
在这里插入图片描述

1.4.2 特点

  • 全双工异步通信。
  • 分数波特率发生器系统,提供精确的波特率。
    -发送和接受共用的可编程波特率,最高可达4.5Mbits/s
  • 可编程的数据字长度(8位或者9位);
  • 可配置的停止位(支持1或者2位停止位);
  • 可配置的使用DMA多缓冲器通信。
  • 单独的发送器和接收器使能位。
  • 检测标志:① 接受缓冲器 ②发送缓冲器空 ③传输结束标志
  • 多个带标志的中断源。触发中断。
  • 其他:校验控制,四个错误检测标志。

1.4.3 通信过程

在这里插入图片描述
在这里插入图片描述

2.思路

异步通信在通信时需要先约定好波特率,才能够确保发送和接收数据的完整。
在程序中需要将串口初始化并且使能串口,若需要接收到数据后产生中断则需要加上中断使能函数。
参考正点原子的教程,其还增加了一个校验的功能(其实正常的通信都应该要加上起始位和结束位,确保数据的正确性),定义了一个函数:
bit13~0:接收到的有效数据个数,bit14:接收到0X0D标志,bit15:接收0X0A完成标志。
在这里插入图片描述

3.寄存器说明

3.1 状态寄存器(USART_SR)

在这里插入图片描述RXNE(读数据寄存器非空),当该位被置 1 的时候,就是提示已经有数据被接收到了,并且可以读出来了。这时候我们要做的就是尽快去读取 USART_DR,通过读 USART_DR 可以将该位清零,也可以向该位写 0,直接清除。

TC(发送完成),当该位被置位的时候,表示 USART_DR 内的数据已经被发送完成了。如果设置了这个位的中断,则会产生中断。该位也有两种清零方式: 1)读 USART_SR,写USART_DR。 2)直接向该位写 0。

3.2 数据寄存器(USART_DR)

在这里插入图片描述
DR(8:0):包含了发送或接收的数据。

3.2 波特比率寄存器(USART_BRR)

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

4.库函数说明

项目功能
void USART_Init()串口初始化:波特率,数据字长奇偶校验,硬件流控以及收发使能
void USART_Cmd()使能串口
void USART_ITConfig()使能相关中断
void USART_SendData()发送数据到串口,DR
uint16_t USART_ReceiveData()接受数据,从DR读取接受到的数据
FlagStatus USART_GetFlagStatus()获取状态标志位
void USART_ClearFlag()清除状态标志位
ITStatus USART_GetITStatus()获取中断状态标志位
void USART_ClearITPendingBit()清除中断状态标志位

5. 串口配置代码

  • 串口时钟使能,GPIO时钟使能:RCC_APB2PeriphClockCmd();
  • 串口复位:USART_DeInit(); 这一步不是必须的
  • GPIO端口模式设置:GPIO_Init(); 模式设置为GPIO_Mode_AF_PP
  • 串口参数初始化:USART_Init();
  • 开启中断并且初始化NVIC(如果需要开启中断才需要这个步骤)
    NVIC_Init();
    USART_ITConfig();
  • 使能串口:USART_Cmd();
  • 编写中断处理函数:USARTx_IRQHandler();
  • 串口数据收发:
    void USART_SendData();//发送数据到串口,DR
    uint16_t USART_ReceiveData();//接受数据,从DR读取接受到的数据
  • 串口传输状态获取:
    FlagStatus USART_GetFlagStatus(USART_TypeDef* USARTx, uint16_t USART_FLAG);
    void USART_ClearITPendingBit(USART_TypeDef* USARTx, uint16_t USART_IT);
void My_USART1_Init(void)
{
	GPIO_InitTypeDef GPIO_InitStrue;
	USART_InitTypeDef USART_InitStrue;
	NVIC_InitTypeDef NVIC_InitStrue;
	
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1,ENABLE);
	
	GPIO_InitStrue.GPIO_Mode=GPIO_Mode_AF_PP;
	GPIO_InitStrue.GPIO_Pin=GPIO_Pin_9;
	GPIO_InitStrue.GPIO_Speed=GPIO_Speed_10MHz;
  GPIO_Init(GPIOA,&GPIO_InitStrue);
	
	GPIO_InitStrue.GPIO_Mode=GPIO_Mode_IN_FLOATING;
	GPIO_InitStrue.GPIO_Pin=GPIO_Pin_10;
	GPIO_InitStrue.GPIO_Speed=GPIO_Speed_10MHz;
  GPIO_Init(GPIOA,&GPIO_InitStrue);
	
	USART_InitStrue.USART_BaudRate=115200;
	USART_InitStrue.USART_HardwareFlowControl=USART_HardwareFlowControl_None;
	USART_InitStrue.USART_Mode=USART_Mode_Tx|USART_Mode_Rx;
	USART_InitStrue.USART_Parity=USART_Parity_No;
	USART_InitStrue.USART_StopBits=USART_StopBits_1;
	USART_InitStrue.USART_WordLength=USART_WordLength_8b;
	
	USART_Init(USART1,&USART_InitStrue);
	
	USART_Cmd(USART1,ENABLE);
	
	USART_ITConfig(USART1,USART_IT_RXNE,ENABLE);
	
	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 res;
	 if(USART_GetITStatus(USART1,USART_IT_RXNE))
 {
     res= USART_ReceiveData(USART1); 
     USART_SendData(USART1,res);   
  }
}

加上“USART_RX_STA”校验

if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET)  
   {
   	Res =USART_ReceiveData(USART1);
   	
   	if((USART_RX_STA&0x8000)==0)
   		{
   		if(USART_RX_STA&0x4000)
   			{
   			if(Res!=0x0a)USART_RX_STA=0;
   			else USART_RX_STA|=0x8000;	
   			}
   		else
   			{	
   			if(Res==0x0d)USART_RX_STA|=0x4000;
   			else
   				{
   				USART_RX_BUF[USART_RX_STA&0X3FFF]=Res ;
   				USART_RX_STA++;
   				if(USART_RX_STA>(USART_REC_LEN-1))USART_RX_STA=0;  
   				}		 
   			}
   		}   		 
    } 

参考:

1.正点原子库函数版本实现

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值