STM32(七)串口通信-UART

一、通信接口

  • 通信是指计算机与外界的信息传输,既包括计算机与计算机之间的传输,也包括计算机与外部设备,如终端、打印机和磁盘等设备之间的传输。在通信领域内,数据通信中按每次传送的数据位数,通信方式可分为:并行通信串行通信

STM32(七)串口通信-UART_第1张图片

二、串行通信

  • 串行通信是指计算机主机与外设之间以及主机系统与主机系统之间数据的串行传送。使用一条数据线,将数据一位一位地依次传输,每一位数据占据一个固定的时间长度。其只需要少数几条线就可以在系统间交换信息,特别适用于计算机与计算机、计算机与外设之间的远距离通信。
  • 串口通信时,发送和接收到的每一个字符实际上都是一次一位的传送的,每一位为1或者为0。

STM32(七)串口通信-UART_第2张图片

三、STM32串口简介

  • 串口作为 MCU 的重要外部接口,同时也是软件开发重要的调试手段,其重要性不言而喻。现在基本上所有的 MCU 都会带有串口,STM32 自然也不例外。
  • STM32 的串口资源相当丰富的,功能也相当强劲。ALIENTEK MiniSTM32 开发板所使用的 STM32F103RCT6 最多可提供 5 路串口,有分数波特率发生器、支持同步单线通信和半双工单线通讯、支持 LIN、支持调制解调器操作、智能卡协议和 IrDA SIR ENDEC 规范、具有 DMA等。

STM32(七)串口通信-UART_第3张图片

四、STM32串口设置的一般步骤

  • 1) 串口时钟使能,GPIO 时钟使能
  • 2) 串口复位
  • 3) GPIO 端口模式设置
  • 4) 串口参数初始化
  • 5) 开启中断并且初始化 NVIC(如果需要开启中断才需要这个步骤)
  • 6) 使能串口
  • 7) 编写中断处理函数

五、步骤详解

(一)串口时钟使能

串口是挂载在 APB2 下面的外设,所以使能函数为: RCC_APB2PeriphClockCmd(); 

(二)串口复位

当外设出现异常的时候可以通过复位设置,实现该外设的复位,然后重新配置,这个外设达到让其重新工作的目的。一般在系统刚开始配置外设的时候,都会先执行复位该外设的操作。复位的是在函数 USART_DeInit() ;中完成。

(三)串口参数初始化

串口初始化是通过 USART_Init() ;函数实现的, voidUSART_Init(USART_TypeDef* USARTx, USART_InitTypeDef* USART_InitStruct); 这个函数的的第一个入口参数是指定初始化的串口标号,这里选择 USART1。 第二个入口参数是一个 USART_InitTypeDef 类型的结构体指针,这个结构体指针的成员变量用来设置串口的一些参数。一般的实现格式为: 

  1. USART_InitStructure.USART_BaudRate = bound; //波特率; 
  2. USART_InitStructure.USART_WordLength = USART_WordLength_8b;//字长为 8 位数据格式 
  3. USART_InitStructure.USART_StopBits = USART_StopBits_1; //一个停止位 
  4. USART_InitStructure.USART_Parity = USART_Parity_No; //无奇偶校验位 
  5. USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None; //无硬件数据流控制 
  6. USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx; //收发模式 
  7. USART_Init(USART1, &USART_InitStructure); //初始化串口 
  • 从上面的初始化格式可以看出初始化需要设置的参数为:波特率,字长,停止位,奇偶校验位,硬件数据流控制,模式(收,发)。 

(四)数据发送与接收

STM32 的发送与接收是通过数据寄存器 USART_DR 来实现的,这是一个双寄存器,包含了 TDR 和 RDR。当向该寄存器写数据的时候,串口就会自动发送,当收到收据的时候,也是存在该寄存器内。 

STM32 库函数操作 USART_DR 寄存器发送数据的函数是: void USART_SendData(USART_TypeDef* USARTx, uint16_t Data); 通过该函数向串口寄存器 USART_DR 写入一个数据。 

STM32 库函数操作 USART_DR 寄存器读取串口接收到的数据的函数是: uint16_tUSART_ReceiveData(USART_TypeDef* USARTx); 通过该函数可以读取串口接受到的数据。 

(五)串口状态

读取串口状态的函数是: FlagStatus USART_GetFlagStatus(USART_TypeDef* USARTx, uint16_t USART_FLAG);
这个函数的第二个入口参数非常关键,它是标示我们要查看串口的哪种状态,操作库函数的方法是:USART_GetFlagStatus(USART1, USART_FLAG_RXNE); 
我们要判断发送是否完成(TC),操作库函数的方法是: USART_GetFlagStatus(USART1, USART_FLAG_TC); 

(六)串口使能

串口使能是通过函数 USART_Cmd()来实现的,使用方法是: USART_Cmd(USART1, ENABLE); //使能串口 

(七)开启串口响应中断

有些时候当我们还需要开启串口中断,那么我们还需要使能串口中断,使能串口中断的函数是: 
void USART_ITConfig(USART_TypeDef* USARTx, uint16_t USART_IT, FunctionalState NewState) ;
这个函数的第二个入口参数是标示使能串口的类型,也就是使能哪种中断,因为串口的中断类型有很多种。比如在接收到数据的时候(RXNE 读数据寄存器非空),我们要产生中断,那么我们开启中断的方法是: 
USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);//开启中断,接收到数据中断我们在发送数据结束的时候(TC,发送完成)要产生中断,那么方法是: USART_ITConfig(USART1,USART_IT_TC,ENABLE); 

(八)获取相应中断状态

当我们使能了某个中断的时候,当该中断发生了,就会设置状态寄存器中的某个标志位。经常我们在中断处理函数中,要判断该中断是哪种中断,使用的函数是:ITStatus USART_GetITStatus(USART_TypeDef* USARTx, uint16_t USART_IT) 
比如我们使能了串口发送完成中断,那么当中断发生了, 我们便可以在中断处理函数中调用这个函数来判断到底是否是串口发送完成中断,方法是: USART_GetITStatus(USART1, USART_IT_TC) 返回值是 SET,说明是串口发送完成中断发生。

六、串口代码驱动

#include "stm32f10x.h"
#include "sys.h"
#include "usart.h"
#include "delay.h"
#include "LED.h"
void My_Uart_Init(void)
{
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_USART1,ENABLE);	//时钟使能
	GPIO_InitTypeDef GPIO_InitStruct;
	//uart_tx  PA9
	GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF_PP;	//复用推挽输出
	GPIO_InitStruct.GPIO_Pin = GPIO_Pin_9;
	GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOA,&GPIO_InitStruct);
	//uart_rx  PA10
	GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IN_FLOATING;	//浮空输入
	GPIO_InitStruct.GPIO_Pin = GPIO_Pin_10;
	GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOA,&GPIO_InitStruct);
	
	NVIC_InitTypeDef NVIC_InitStruct;
	NVIC_InitStruct.NVIC_IRQChannel = USART1_IRQn;	//USART1中断优先级管理
	NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE;	
	NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = 3;
	NVIC_InitStruct.NVIC_IRQChannelSubPriority = 3;
	NVIC_Init(&NVIC_InitStruct);
	
	USART_InitTypeDef USART_InitStruct;
	USART_InitStruct.USART_BaudRate = 115200;		//波特率
	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;		//1个停止位
	USART_InitStruct.USART_WordLength = USART_WordLength_8b;	//8字长
	USART_Init(USART1,&USART_InitStruct);
	
	USART_ITConfig(USART1,USART_IT_RXNE,ENABLE);	//开启接收中断
	USART_Cmd(USART1,ENABLE);	//串口使能
}

void USART1_IRQHandler(void)
{
	u8 res;
	if(USART_GetITStatus(USART1,USART_IT_RXNE))
	{
		res = USART_ReceiveData(USART1);
		USART_SendData(USART1,res);
		LED1=!LED1;
		LED0=!LED0;
		delay_ms(100);
	}
}

int main(void)
{
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); //设置中断分组
	delay_init();
	LED_Init();
	My_Uart_Init();
	while(1)
	{
		LED0=!LED0;
	}
}

 

你可能感兴趣的:(STM32)