STM32 通用同步/异步通信

时间:2024-10-08 07:05:38

一、串行通信简介

        CPU与外围设备之间的信息交换称为通信。基本的通信方式有并行通信串行通信两种。STM32单片机提供了功能强大的串行通信模块,即通用同步/异步收发器USART)。

1.串行通信

        串行通信是数据字节一位一位地依次传送的通信方式。串行通信的速度慢,但占用的传输线条数少,适用于远距离的数据传送。

        从硬件上看,串行通信有单工半双工全双工通信

  • 单工通信就是数据只允许向一个方向进行传送。
  • 半双工通信就是数据允许向两个方向进行传送,但一个设备的传送和接收过程不能同时进行。
  • 全双工通信就是数据允许向两个方向进行传送,且一个设备的传送和接收过程可以同时进行。

2.串行异步通信和串行同步通信

         串行通信按照串行数据的时钟控制方式分为异步通信和同步通信。

        串行异步通信是一种常用的串行通信方式,一次通信传送一个字符帧。在发送字符时,发送的字符之间的时间间隔可以是任意的,接收端时刻做好接受的准备。串行异步通信的优点是通信设备简单价格低廉,但因为具有起始位和停止位,所以传输效率较低。串行异步通信只适用于点对点

        串行同步通信要求在进行通信前先建立同步,发送频率和接收方的接收频率要同步。串行同步通信的传输速度较快,可用于点对多,多用于同一PCB上芯片级之间的通信。缺点是需要使用专用的时钟控制线来实现同步。

3.串行异步通信的数据传输形式

        串行异步通信需要制定一些共同遵守的约定,其中最重要的是字长波特率

        字长可以是8位或者9位,起始位为低电平,停止位为高电平,空闲帧全为1。发送和接收由一个共用的波特率发生器驱动。

        波特率即数据的传送速率。在串行异步通信中,每秒钟传送的二进制数的位数称为波特率,单位是比特/秒(bit/s),或波特(baud)。波特率的倒数就是每一位的传送时间,称为位传送时间,单位为秒(s)。

        

二、STM32的USART

1.USART的特点

  • 同步/异步全双工通信,低位先行。
  • 可配置数据位长度(8位/9位)。
  • 可配置停止位长度(0.5/1/1.5/2)。
  • 可选的校验位(无校验/奇校验/偶校验)。
  • 可配置波特率。
  • 支持硬件流控制。 

2.USART的结构

        STM32有3~5个全双工的串行异步通信接口USART,简称串口。USART主要有发送引脚(RX)、接收引脚(TX)、清除发送(nCTS)、发送请求(nRTS)和发送器时钟输出(CK)等引脚来与外部设备相连,同时,其内部还包含了各种寄存器和功能模块等。

        常用的引脚有RX发送引脚TX接收引脚,使用这两个引脚,一般就可以实现双向通信。

 3.USART的使用方式

        

 三、USART的使用流程

        STM32的USART一般使用异步通信方式,使用流程如下:

  1. 配置GPIO
  2. 配置USART
  3. 配置NVIC
  4. 编写中断服务函数(用于接收数据和进行其他操作)
  5. 发送数据
  6. 配置printf重定向(按需要选择配置或者不配置)
#include "stm32f10x.h"                  // Device header


/**********************************初始化USART1***********************************/
void Serial1_Init(void)
{
	RCC_APB2PeriphClockCmd (RCC_APB2Periph_GPIOA |RCC_APB2Periph_USART1,ENABLE );
    //开启GPIO和USART1时钟
	


	GPIO_InitTypeDef GPIO_InitStructure;
	GPIO_InitStructure.GPIO_Mode =GPIO_Mode_AF_PP;         //复用推挽输出
	GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
	GPIO_InitStructure.GPIO_Pin=GPIO_Pin_9;                //配置发送引脚PA9
	GPIO_Init(GPIOA,&GPIO_InitStructure);                 
	
	GPIO_InitStructure.GPIO_Mode =GPIO_Mode_IPU;           //上拉输入
	GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;        
	GPIO_InitStructure.GPIO_Pin=GPIO_Pin_10;               //配置接收引脚PA10
	GPIO_Init(GPIOA,&GPIO_InitStructure);                      
	


	USART_InitTypeDef USART_InitStructure;
	USART_InitStructure.USART_BaudRate=9600;                     //波特率,选择9600
	USART_InitStructure.USART_HardwareFlowControl=USART_HardwareFlowControl_None;
                                                                 //硬件流控制,不使用
	USART_InitStructure.USART_Mode=USART_Mode_Tx|USART_Mode_Rx ; //配置为发送和接收模式
	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_ITConfig (USART1 ,USART_IT_RXNE ,ENABLE);               //开启USART1的接收中断
	

	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);               //选择优先级分组
	

	NVIC_InitTypeDef NVIC_InitStructure;                          //配置NVIC,使用到中断都要配置
	NVIC_InitStructure.NVIC_IRQChannel=USART1_IRQn;
	NVIC_InitStructure.NVIC_IRQChannelCmd=ENABLE ;
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=1;
	NVIC_InitStructure.NVIC_IRQChannelSubPriority=1;
	NVIC_Init(&NVIC_InitStructure);                         
	
	USART_Cmd (USART1,ENABLE );                                   //使能USART1                            
}


/*********************************USART1中断服务函数*********************************/
void USART1_IRQHandler(void)                                      
{
	 
	if(USART_GetITStatus (USART1,USART_IT_RXNE )==SET)  
	{
        uint8_t value = 0;
		value=USART_ReceiveData (USART1);                         //接收数据       
		 
		 
        //其他操作


		USART_ClearITPendingBit (USART1,USART_IT_RXNE );
	}
}


/*************************************发送数据***************************************/
    USART_SendData(USART1, Byte);	                          	   //发送数据的操作
	while (USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET);  //等待发送完成


/*************************************printf重定向***********************************/
int fputc(int ch,FILE *f)          
{
	USART_SendData(USART1, ch);	                          	       //发送数据的操作
	while (USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET);  //等待发送完成
	return ch;
}
//printf重定向到串口,需要在该文件#include <stdio.h>,作用是printf操作会将数据打印到串口