UART串口通信

一、通信特点

异步、串行、全双工

一般描述某种通信的特点为: 同步/异步 , 串行/并行 , 半双工/全双工
同步:要求一个芯片控制另一芯片的时序,一般,两者之间至少采用一个总线连接以控制时钟(“时钟线”),
其中主机主动控制时钟线(通过时钟线输出),从机被动接受时钟线(通过时钟线输入)。
异步:双方不会通过总线连接时钟,异步通信要求双方使用独立的时钟生成装置(波特率发生器),生成相 同的通信速度。
串行:在每个数据方向上仅有一根数据线。每次仅传输一位数据。 并行:在每个数据方向上有多根数据线。每次可以传输数据的多个位(一般是8/16位)
半双工:数据线仅有一组,同一时刻,只有一方控制数据线的发送,另一方接收数据(即双方不能同时发送 数据)
全双工:数据线有两组或以上,同一时刻,通信双方都可以给对方发送数据。
一种通信的特点与它的总线构成是相关的。

二、通信应用

  1. 部分无线通信模块具有UART通信接口,比如蓝牙模块、NBIOT模块、WIFI模块、GSM模块、GPS模块
  2. 是一种容易实现的MCU和电脑间的通信方式,用于辅助调试代码 (MCU传送变量、寄存器的值给电脑)
  3. 用于电脑控制MCU(电脑传送 指令数据 给MCU),通过上位机控制下位机

三、接线示意图

在这里插入图片描述
TX:发送引脚
RX:接收引脚

三、UART通信协议

一帧数据的构成:起始位+ 数据位 + 校验位 + 停止位
起始位:1位,逻辑’0’
数据位:5~8位,可以在MCU中设置
校验位:0~1位, 无校验/奇校验/偶校验
奇校验:在数据位中有奇数个逻辑‘1’时,该位为0;否则为1
偶校验:在数据位中有偶数个逻辑‘1’时,该位为0;否则为1
停止位:0.5~2位,(传输每个都会占用固定时长),逻辑‘1’
数据传输顺序:先传送数据的低位
通信速度(波特率baud):在单片机应用,常用通信速度有2400、4800、9600、19200、115200 bit/s

四、STM32F4 串口使用

1、资源分布

查看芯片的数据手册
一共有6个,分别是USART1和USART6挂载在APB2总线(84MHz)
USART2、USART3、UART4、UART5挂载在APB1总线(42MHz)

USART:表示通用同步异步收发器(由于其同步功能应用较少,一般不使用其同步功能)
UART :表示通用异步收发器

2、特性

查看芯片的参考手册 第26章 USART

主要特性:
同步\异步、串行、全双工
过采样倍数可以设置(16倍/8倍)
可以编程设置该接口的通信速度
数据字长度可编程(8 位或 9 位) (这里的数据字包含 数据位 + 校验位)
发送器和接收器具有单独使能位
传输检测标志:(通过查看这些标志,可以确定发生过的事件;若发生了这些事件,则该外设的状态寄存器SR的特定位会被置位)
— 接收缓冲区已满
— 发送缓冲区为空
— 传输结束标志
四个错误检测标志:(SR上有相应的位)
— 溢出错误
— 噪声检测
— 帧错误
— 奇偶校验错误
十个具有标志位的中断源(指该外设有最多10种可以触发中断的事件)

3、UART框图

在这里插入图片描述
结合框图和USARTx->CR1寄存器可以确定,对USARTx外设常见配置有:

  1. 数据帧格式设置(起始位、数据位、校验位、停止位)
  2. 通信速度设置
  3. 发送器和接收器使能
  4. 使能USARTx

框图中可以看出发送寄存器和接收寄存器共同构成DR(数据寄存器),CPU通过对USARTx->DR进行写/读操作可以分别实现发送/接收 数据。
由于串行通信传输一个字节数据需要一定的时间,在上一帧数据传输完成前,不可以立刻传送下一帧数据(强行传输会导致数据丢失)。所以在传输数据时,需要查询发送器/接收器状态,确认是否发生了 一帧数据传送完成 或 准备好接收一帧数据 的事件。

4、使用方法

在这里插入图片描述
当相应的GPIO引脚被复用为USRATx的Tx和Rx后,将由此USARTx外设控制这两个GPIO引脚,实现串口通信中的发送和接收(即这两个GPIO引脚将不再受到GPIOx->ODR等寄存器的影响了),开发板相关原理图如下。
在这里插入图片描述

5、相关库函数

附:引脚复用库函数
void GPIO_PinAFConfig (GPIO_TypeDef *GPIOx, uint16_t GPIO_PinSource, uint8_t GPIO_AF)
改变指定引脚的映射功能(复用功能)【该操作需要在将GPIO引脚配置为复用模式后使用】
比如,将PA9复用为USART1_Tx
(所有引脚的详细复用功能参考芯片数据手册 第3.7表格—复用功能映射)
GPIO_PinAFConfig (GPIOA, GPIO_PinSource9, GPIO_AF_USART1);

UART库函数
1、void USART_Init (USART_TypeDef *USARTx, USART_InitTypeDef *USART_InitStruct)
基于参数USART_InitStruct 初始化USARTx外设
2、void USART_Cmd (USART_TypeDef *USARTx, FunctionalState NewState)
USARTx外设使能
3、void USART_SendData (USART_TypeDef *USARTx, uint16_t Data)
通过串口发送数据(一个字节)
4、uint16_t USART_ReceiveData (USART_TypeDef *USARTx)
通过串口接收数据(一个字节)
5、void USART_ClearFlag (USART_TypeDef *USARTx, uint16_t USART_FLAG)
清除USARTx的挂起标志
6、FlagStatus USART_GetFlagStatus (USART_TypeDef *USARTx, uint16_t USART_FLAG)
查询USARTx的指定事件是否发生

6、函数实例

(1)初始化
USART1_init();

  1. 激活GPIOx时钟
  2. 将使用到引脚配置复用模式
  3. 将这些引脚映射到USARTx(此后,PA9和PA10作为USART1的发送和接收引脚)
  4. 激活USARTx时钟
  5. USARTx库函数初始化
    USART_Init ()
  6. 使能USARTx
    USART_Cmd ()
/***********************************
函数名:uart1_init
参数:u32 baud 波特率
返回值:无
功能:uart1初始化
备注:pa9 (usart1_tx)
			pa10(usart1_rx)
***********************************/
void uart1_init(u32 baud)
{
		//创建一个清单
	GPIO_InitTypeDef gpio_InitStruct;
	USART_InitTypeDef usart_InitStruct;
	
	/*将PA9,PA10作为USART1的Tx和Rx*/
	//1.激活GPIOA时钟
	RCC_AHB1PeriphClockCmd (RCC_AHB1Periph_GPIOA, ENABLE);
	//2.配置PA9和PA10为复用模式
		//填写清单
	gpio_InitStruct.GPIO_Mode = GPIO_Mode_AF ;
	gpio_InitStruct.GPIO_OType = GPIO_OType_PP ;
	gpio_InitStruct.GPIO_Pin = GPIO_Pin_9 | GPIO_Pin_10 ;
	gpio_InitStruct.GPIO_PuPd = GPIO_PuPd_NOPULL ;
	gpio_InitStruct.GPIO_Speed = GPIO_Low_Speed ;
		//导入清单,完成配置
	GPIO_Init (GPIOA, &gpio_InitStruct);
	//3.将PA9和PA10映射到USART1
	GPIO_PinAFConfig (GPIOA, GPIO_PinSource9, GPIO_AF_USART1);
	GPIO_PinAFConfig (GPIOA, GPIO_PinSource10, GPIO_AF_USART1);
	/*激活,初始化,使能USART1*/
	//4.激活USART1
	RCC_APB2PeriphClockCmd (RCC_APB2Periph_USART1, ENABLE);
	//5.配置USART1
		//填写清单
	usart_InitStruct.USART_BaudRate 						= baud ;
	usart_InitStruct.USART_HardwareFlowControl 	= USART_HardwareFlowControl_None ;
	usart_InitStruct.USART_Mode 								= USART_Mode_Rx | USART_Mode_Tx ;
	usart_InitStruct.USART_Parity 							= USART_Parity_No ;
	usart_InitStruct.USART_StopBits 						= USART_StopBits_1 ;
	usart_InitStruct.USART_WordLength 					= USART_WordLength_8b ;
		//导入清单,完成配置
	USART_Init (USART1, &usart_InitStruct);
	//6.使能USART1
	USART_Cmd (USART1, ENABLE);
}

(2)发送一个字节

/***********************************
函数名:uart1_sendByte
参数:u8 data 待发送内容
返回值:无
功能:通过串口1发送单字节
备注:等待发送完成
***********************************/
void uart1_sendByte(u8 data)
{
	//1.往DR写入数据
	USART_SendData (USART1, data);
	//2.等待本帧的数据位发送完成,清除标志位
	while(SET != USART_GetFlagStatus (USART1, USART_FLAG_TXE));
	//之后对DR进行写操作,TXE标志位自动清除
}

(3)发送一个字符串

/***********************************
函数名:uart1_sendString
参数:const char *str 指向待发送的字符串
返回值:无
功能:通过串口1发送字符串
备注:字符串(多次调用发送单字节函数)
调用次数 和 字符串长度有关
***********************************/
//(const) char *p / char str[] / (const) u8 *p / u8 str[]
void uart1_sendString(const char *str)
{
	//多次调用发送单字节函数
	while(*str != '\0')
	{
		uart1_sendByte(*str);
		str++;
	}
	//由于上方结构未发送'\0',补发'\0'
	uart1_sendByte('\0');
}

(4)接收一个字节

/***********************************
函数名:uart1_recvByte
参数:无
返回值:u8 接收到数据
功能:通过串口1接收单字节
备注:等待可以接收
			该函数具有阻塞特性
***********************************/
u8 uart1_recvByte(void)
{
	//1.等待可以接收一帧数据,考虑清除标志位
	while(SET !=  USART_GetFlagStatus (USART1, USART_FLAG_RXNE));
	//2.USARTx库函数接收数据,清除RXNE标志位
	return USART_ReceiveData (USART1);
}

(5)接收一个字符串

/***********************************
函数名:uart1_recvString
参数:char *p 指向接收字符串的空间
返回值:无
功能:通过串口1接收字符串
备注:等待可以接收
			该函数具有阻塞特性
若接收电脑端XCOM发送字符串,由于该软件
无法发送字符串,但可以勾选发送新行
***********************************/
void uart1_recvString(char *p)
{
	u8 data;
	do
	{
		//调用接收单字节函数
		data = uart1_recvByte();
		*p = data;
		p++;
	}
	while( (data != '\0') && (data != '\n') );//&& (data != '\n') 若不是电脑端发送可以不要
	//!((data == '\0') || (data == '\n'))
	*p = '\0';	//补充接收'\0'是考虑到会接收到'\n'的情况
}

五、实战《上位机控制开发板小灯》

思路:电脑通过串口与开发板相连,电脑通过串口发送指令(eg:LED_ON),开发板接收指令识别并进行LED灯的操作。
工程代码:
百度云链接:https://pan.baidu.com/s/1f3mj-WE-XMzHI-AMdW_oRg
提取码:aaaa

  • 42
    点赞
  • 389
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值