单片机(7)串口通信介绍

261 阅读4分钟

本文已参与「新人创作礼」活动, 一起开启掘金创作之路。

       串口:全称串行接口,也称串行通信接口或串行通讯接口(通常指COM接口),是采用串行通信方式的扩展接口。串行接口 (Serial Interface)是指数据一位一位地顺序传送。其特点是通信线路简单,只要一对传输线就可以实现双向通信(可以直接利用电话线作为传输线),从而大大降低了成本,特别适用于远距离通信,但传送速度较慢。

       STM32的串行通信接口:

  1. UART:通用同步收发器。
  2. USART:通用同步异步收发器。 (大容量STM32F10x系列芯片包含两个UART与三个USART)

USART概述

       USART框图:

在这里插入图片描述

       相关初始化:

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;

奇偶校验位:偶校验:输送的8位数据的1如果为偶数则为0,奇数为1。(使1为偶数) 奇校验:输送的8位数据的1如果为奇数则为0,偶数为1。(使1为奇数) 作用:提高数据传输的准确性。

波特率:每秒钟传送的码元符号的个数,它是对符号传输速率的一种度量,它用单位时间内载波调制状态改变的次数来表示,1波特即指每秒传输1个符号。(一个数字脉冲就是一个码元,如‘1’,'0'各是一个码元)

通信方式

按输送位数

  1. 并行通信:数据各个位同时传输(速度快但占用引脚多)。

在这里插入图片描述

  1. 串行通信:数据按位顺序传输(速度慢但占用引脚少)。

在这里插入图片描述

按传输方向

  1. 单工:只支持数据单方向传输。

  2. 半双工:允许数据双向传输,但同一时刻数据只能往一个方向传输,即方向可改变的单工通信。

  3. 全双工:允许数据同时在两个方向上传输。

在这里插入图片描述

按传输有无时钟

  1. 同步通信:带时钟同步信号传输(SPI,IIC通信接口)。

在这里插入图片描述

在约定的通信速率下,发送端和接收端的时钟信号频率始终保持一致(同步),保证了通信双方在发送和接收数据时具有完全一致的定时关系。

  1. 异步通信:不带时钟同步信号(UART通用异步收发器,单总线)。

在这里插入图片描述

同步通信与异步通信区别:

  1. 同步通信要求接收端时钟频率和发送端时钟频率一致,发送端发送连续的比特流;异步通信时不要求接收端时钟和发送端时钟同步,发送端发送完一个字节后,可经过任意长的时间间隔再发送下一个字节;
  2. 同步通信效率高,异步通信效率较低。(异步通信必须在每一个字符的开始和结束的地方加上标志,即加上开始位和停止位);
  3. 同步通信较复杂,双方时钟的允许误差较小;异步通信简单,双方时钟可允许一定误差;
  4. 同步通信可用于点对多点,异步通信只适用于点对点。

USART初始化步骤

  1. 串口时钟使能,GPIO时钟使能;
  2. GPIO端口模式设置;
  3. 串口参数初始化;
  4. 开启中断并初始化NVIC;(若开启中断)
  5. 使能相应串口;
  6. 编写中断处理函数;
  7. 串口数据收发及传输状态获取。

       例:

void MY_USART1_Init(void)
{
 GPIO_InitTypeDef GPIO_InitStrue;//相应结构体初始化
 USART_InitTypeDef USART_InitStrue;
 NVIC_InitTypeDef NVIC_InitStrue;
 
 RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);//使能GPIO时钟
 RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1,ENABLE);//使能串口时钟
 
 GPIO_InitStrue.GPIO_Mode=GPIO_Mode_AF_PP;//GPIO9的初始化
 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;//GPIO10的初始化
 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_Rx|USART_Mode_Tx;//使能发送与接收
 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 sju;
 if(USART_GetITStatus(USART1,USART_IT_RXNE))//如果接收到数据
 {
  sju=USART_ReceiveData(USART1);//读该串口的数据
  USART_SendData(USART1,sju);//把数据发送出去
 }
}

int main(void)
 { 
  NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//系统优先级分组设置为2
  MY_USART1_Init();
  while(1);
 }

附串口操作相关库函数:

void USART_Init();//串口初始化
void USART_Cmd();//使能串口
void  USART_ITConfig();//使能相关中断

void  USART_SendData();//发送数据到串口
uint16_t USART_ReceiveData();//接收数据

FlagStatus USART_GetFlagStatus();//获取状态标志位
void USART_ClearFlag();//清除状态标志位
ITStatus USART_GetITStatus();//获取中断状态标志位
void USART_ClearITPendingBit();//清除状态标志位