STM32-串口通信实验

一、通信接口背景知识

1.通信的两种方式:
①并行通信

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

②串行通信

  • 传输原理:数据按位顺序传输。
  • 优点:占用引脚资源少
  • 缺点:速度相对较慢
    在这里插入图片描述
    2.串行通信
    按照数据传送的方向,分为:
  • 单工:数据传输只支持数据在一个方向上传输
  • 半双工:允许数据在两个方向上传输,但是,在某一时刻,只允许数据在一个方向上传输,它实际上是一种切换方向的单工通信
  • 全双工:允许数据同时在两个方向上传输,因此,全双工通信是两个单工通信方式的结合,它要求发送设备和接收设备都有独立的接收和发送能力。

3.串行通信的通信方式

  • 同步通信:带时钟同步信号传输
    如SPI,IIC通信接口
  • 异步通信:不带时钟同步信号
    如UART(通用异步收发器),单总线
    在这里插入图片描述
    4.常见的串行通信接口:
通信标准引脚说明通信方式通信方向
UART(通用异步收发器)TXD:发送端、RXD:接受端、GND:公共地异步通信全双工
单总线(1-wire)DQ:发送/接受端异步通信半双工
SPISCK:同步时钟、MISO:主机输入,从机输出、MOSI:主机输出,从机输入同步通信全双工
I2CSCL:同步时钟、SDA:数据输入/输出端同步通信半双工

二、STM32串口通信基础

1.STM32的串口通信接口

  • UART:通用异步收发器
  • USART:通用同步异步收发器
  • 大容量STM32F10x系列芯片,包含3个USART和2个UART
    2.UART异步通信方式引脚连接方法
  • RXD:数据输入引脚。数据接受。
  • TXD:数据发送引脚。数据发送。
    在这里插入图片描述
串口号RXDTXD
1PA10PA9
2PA3PA2
3PB11PB10
4PC11PC10
5PD2PC12

3.UART异步通信方式特点:

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

4.串口通信过程
在这里插入图片描述
传输速度由波特率决定。
5.STM32串口异步通信需要定义的参数:
①起始位
②数据位(8位或者9位)
③奇偶校验位(第9位)

  • 奇校验:如前面传输了奇数个1,则奇偶校验位设置为0;如前面传输了偶数个1,则奇偶校验位设置为1。
  • 偶校验:如前面传输了奇数个1,则奇偶校验位设置为1;如前面传输了偶数个1,则奇偶校验位设置为0。
    ④停止位(1,15,2位)
    ⑤波特率设置
    在这里插入图片描述
    6.USART框图
    在这里插入图片描述

三、 STM32串口常用寄存器和库函数

1.常用的串口相关寄存器
①USART_SR状态寄存器
②USART_DR数据寄存器
③USART_BRR波特率寄存器
④USART_CRx控制寄存器
2.波特率计算方法
T X / R x 波特率 = f P C L K x ( 16 ∗ U S A R T D I V ) T_X/R_x波特率=\frac{f_{PCLK_x}}{(16*USARTDIV)} TX/Rx波特率=(16USARTDIV)fPCLKx

  • 上式中, f P C L K x f_{PCLK_x} fPCLKx是给串口的时钟(PCLK1用于USART2、3、4、5,PCLK1用于USART1);USARTDIV是一个无符号定点数,我们只要得到USARTDIV的值,就可以得到串口波特率寄存器USART->BRR的值,反过来,我们得到USART->BRR的值,也可以推导出USARTDIV的值。但我们更关心的是如何从USARTDIV的值得到USART_BRR的值,因为一般我们知道的是波特率和 P C L K x PCLK_x PCLKx的时钟,要求的就是USART_BRR的值。
  • 假设我们的串口1要设置为115200的波特率,而PCLK2的时钟为72M。这样,我们根据上面的公式有:
    U S A R T D I V = 72000000 / ( 115200 ∗ 16 ) = 39.0625 USARTDIV=72000000/(115200*16)=39.0625 USARTDIV=72000000/(11520016)=39.0625
    那么得到:
    DIV_Fraction=16*0.0625=1=0X01(小数部分)
    DIV_Mantissa=39=0X27(整数部分)
    这样,我们就得到了USART->BRR的值为0X0271。只要设置串口1的BRR寄存器值为0X0271就可以得到115200的波特率。
    3.串口操作相关库函数(省略入口参数):
void USART_Init();//串口初始化:波特率、数据字长、奇偶校验、硬件流控以及收发使能
void USART_Cmd();//使能串口
void USART_ITConfig();//使能相关中断

void USART_SendData();//发送数据到串口,DR
unit16_t USART_ReceiveData();//接受数据,从DR读取接受到的数据

FlagStatus USART_GetFlagStatus();//获取状态标志位
void USART_ClearFlag();//消除状态标志位
ITStatus USART_GetITStatus();//获取中断状态标志位
void USART_ClearITPendingBit();//清除中断状态标志位
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;

4.串口配置的一般步骤
①串口时钟使能,GPIO时钟使能

RCC_APB2PeriphClockCmd();

②串口复位

USART_DeInit();//这一步不是必须的

③GPIO模式设置

GPIO_Init();//模式设置为GPIO_Mode_AF_PP

注意:需要查中文参考手册看设置为什么模式
在这里插入图片描述
(8.1.11外设的GPIO配置)

④串口参数初始化

USART_Init();

⑤开启中断并且初始化NVIC(如果需要开启中断才需要这个步骤)

NVIC_Init();
USART_ITConfig();

⑥使能串口

USART_Cmd();

⑦编写中断处理函数

USARTx_IRQHandler();

⑧串口数据收发

void USART_SendData();//发送数据到串口,DR
unit16_t USART_ReceiveData();//接受数据,从DR读取接受到的数据

⑨串口传输状态获取

FlagStatus USART_GetFlagStatus(USART_Typedef*USARTx,unit16_t USART_FLAG);
void USART_ClearITPendingBit(USART_TypeDef*USARTx,unit16_t USART_IT);

四、串口配置一般步骤

#include "stm32f10x.h"

void My_USART1_Init(void)
{
	GPIO_InitTypeDef GPIO_InitStructure;
	USART_InitTypeDef USART_InitStructure;
	NVIC_InitTypeDef NVIC_InitStructure;
	
	//使能GPIO和串口时钟
//	RCC_APB2PeriphResetCmd(RCC_APB2Periph_GPIOA,ENABLE);
//	RCC_APB2PeriphResetCmd(RCC_APB2Periph_USART1,ENABLE);
//	
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1|RCC_APB2Periph_GPIOA, ENABLE);	//使能USART1,GPIOA时钟
	
	//GPIO模式设置
	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);
	GPIO_InitStructure.GPIO_Pin=GPIO_Pin_10;
	GPIO_InitStructure.GPIO_Mode=GPIO_Mode_IN_FLOATING;
	GPIO_Init(GPIOA,&GPIO_InitStructure);
	
	//串口参数初始化
	USART_InitStructure.USART_BaudRate=115200;
	USART_InitStructure.USART_HardwareFlowControl=USART_HardwareFlowControl_None;//
	USART_InitStructure.USART_Mode=USART_Mode_Rx|USART_Mode_Tx;//
	USART_InitStructure.USART_Parity=USART_Parity_No;//无奇偶校验
	USART_InitStructure.USART_StopBits=USART_StopBits_1;//设置1位停止位
	USART_InitStructure.USART_WordLength=USART_WordLength_8b;//字长为8
	USART_Init(USART1,&USART_InitStructure);
	
	//使能串口
	USART_Cmd(USART1,ENABLE);
	
	//开启中断
	USART_ITConfig(USART1,USART_IT_RXNE,ENABLE);
	
	//初始化NVIC
	NVIC_InitStructure.NVIC_IRQChannel=USART1_IRQn;//在stm32f10x.h中有
	NVIC_InitStructure.NVIC_IRQChannelCmd=ENABLE;
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=1;
	NVIC_InitStructure.NVIC_IRQChannelSubPriority=1;
	NVIC_Init(&NVIC_InitStructure);
}

//编写中断服务函数
//在startup_stm32f10x_hd.s中写了格式
void USART1_IRQHandler(void)
{
	u8 res;
	if (USART_GetITStatus(USART1,USART_IT_RXNE))
	{
	res=USART_ReceiveData(USART1);
	USART_SendData(USART1,res);
	}
}



 int main(void)
 {	
	//中断优先级分组
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
	My_USART1_Init();
	 
	 USART_SendData(USART1,0xaa);
	 
	while(1);
 }
  • 2
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值