串口通讯目录

  • 物理层
  • 协议层
  • USART简介
  • 开发板与上位机的连接
  • 代码讲解:
    • 一.初始化结构体
    • 二.NVIC配置中断优先级
    • 三.USART配置函数讲解
    • 四.传输数据的函数:
      • 1.发送一个字节
      • 2.发送字符串
      • 3.重定向printf函数发送字符串
      • 4.重定向getchar函数接收字符
      • 5.通过中断接收
    • 结语

串口通讯(Serial Communication)是一种设备间非常常用的串行通讯方式,因为它简单便捷,因此大部分电子设备都支持该通讯方式,其通讯协议可分层为协议层和物理层。物理层规定通信协议中具有机械、电子功能的特性,从而确保原始数据在物理媒体的传播;协议层主要规定通讯逻辑,统一双方的数据打包、解包标准。通俗的讲物理层规定我们用嘴巴还是肢体交流,协议层规定我们用中文还是英文交流。下面分析一下串口通讯协议的物理层和协议层。

物理层

1.通讯结构
串口通讯的物理层的主要标准是RS-232标准,其规定了信号的用途、通讯接口及信号的电平标准,其通讯结构如下:

在设备内部信号是以TTL电平标准传输的,设备之间是通过RS-232电平标准传输的,而且TTL电平需要经过电平转换芯片才能转化为RS-232电平,RS-232电平转TTL电平也是如此。
2.电平标准
根据使用的电平标准不同,串口通讯可分为 RS-232标准 及TTL标准,具体标准如下:

在电子电路中常使用TTL的电平标准,但其抗干扰能力较弱,为了增加串口的通讯距离及抗干扰能力,使用RS-232电平标准在设备之间传输信息,经常使用MA3232芯片对TTL电平及RS-232电平进行相互转换。

协议层

1.数据包
串口通讯的数据包由发送设备通过自身的TXD接口传输到接收设备得RXD接口,在协议层中规定了数据包的内容,具体包括起始位、主体数据(8位或9位)、校验位以及停止位,通讯的双方必须将数据包的格式约定一致才能正常收发数据。

2.波特率
由于异步通信中没有时钟信号,所以接收双方要约定好波特率,即每秒传输的码元个数,以便对信号进行解码,常见的波特率有4800、9600、115200等。STM32中波特率的设置通过串口初始化结构体来实现。
3.起始和停止信号
数据包的首尾分别是起始位和停止位,数据包的起始信号由一个逻辑0的数据位表示,停止位信号可由0.5、1、1.5、2个逻辑1的数据位表示,双方需约定一致。STM32中起始和停止信号的设置也是通过串口初始化结构体来实现。
4.有效数据
有效数据规定了主题数据的长度,一般为8或9位,其在STM32中也是通过串口初始化结构体来实现的。
5.数据校验
在有效数据之后,有一个可选的数据校验位。由于数据通信相对更容易受到外部干扰导致传输数据出现偏差,可以在传输过程加上校验位来解决这个问题。校验方法有奇校验(odd)、偶校验(even)、 0 校验(space)、 1 校验(mark)以及无(noparity)。这些也都可以在串口初始化结构体中实现的。

USART简介

USART(通用同步异步收发器)是一个串行通信设备,可以灵活地与外部设备进行全双工数据交换。有别于 USART 还有一个UART,它是在 USART 基础上裁剪掉了同步通信功能,只有异步通信。简单区分同步和异步就是看通信时需不需要对外提供时钟输出,我们平时用的串口通信基本都是 UART。USART 在 STM32 应用最多莫过于“打印”程序信息,一般在硬件设计时都会预留一USART 通信接口连接电脑,用于在调试程序是可以把一些调试信息“打印”在电脑端的串口调试助手工具上,从而了解程序运行是否正确、如果出错哪具体哪里出错等等。
STM32中一共有5个USART,如示:

USART的USB转串口原理图如下:

USART1的发送和接收端口是事先连接好的,如果要使用其他USART只需要将相应的发送接收端口按图连接好即可。
USART有多个中断请求事件:

开发板与上位机的连接

开发板与上位机之间通过USB线连接,所以在上位机上要配置一个USB转串口 的驱动,以便把USB传输过来的电平转换为TTL电平,TTL电平才能与串口调试助手建立联系。一般使用CH341驱动作为win10下的USB转串口,驱动安装成功的情况下接入USB会在计算机的设备管理器的端口中发现串口:

(win7系统一般选择CH340作为USB转串口驱动。)

代码讲解:

固件库编程的一大好处就是我们可以根据固件库函数来学习外设的相关知识,而且固件库函数的编写都是建立在对底层寄存器操作上的,所以通过讲解代码可以更好理解串口通讯相关知识。

一.初始化结构体

typedef struct {uint32_t USART_BaudRate; // 波特率uint16_t USART_WordLength; // 字长uint16_t USART_StopBits; // 停止位uint16_t USART_Parity; // 校验位uint16_t USART_Mode; // USART 模式uint16_t USART_HardwareFlowControl; // 硬件流控制} USART_InitTypeDef;

USART初始化结构体中的相应变量都对应着数据包中的相对内容。

二.NVIC配置中断优先级

我们在串口接收信息时采用了触发中断事件,所以要配置一下串口中断的优先级:

NVIC_Configuration(void)
{NVIC_InitTypeDef NVIC_InitStructure;/* 嵌套向量中断控制器组选择 */NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);/* 配置USART为中断源 */NVIC_InitStructure.NVIC_IRQChannel = DEBUG_USART_IRQ;/* 抢断优先级*/NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;/* 子优先级 */NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;/* 使能中断 */NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;/* 初始化配置NVIC */NVIC_Init(&NVIC_InitStructure);
}

中断相关的知识之前详细讲过,此处就不再累赘讲述。
中断知识链接

三.USART配置函数讲解

USART配置函数的主要作用是打开串口与相应的GPIO引脚,配置好相应串口信息与GPIO引脚的工作模式,以便信息的传输与接收。

void DEBUG_USART_Config(void)
{GPIO_InitTypeDef GPIO_InitStructure;USART_InitTypeDef USART_InitStructure;/* 第一步:初始化GPIO */// 打开串口GPIO的时钟DEBUG_USART_GPIO_APBxClkCmd(DEBUG_USART_GPIO_CLK, ENABLE);// 将USART Tx的GPIO配置为推挽复用模式GPIO_InitStructure.GPIO_Pin = DEBUG_USART_TX_GPIO_PIN;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_Init(DEBUG_USART_TX_GPIO_PORT, &GPIO_InitStructure);// 将USART Rx的GPIO配置为浮空输入模式GPIO_InitStructure.GPIO_Pin = DEBUG_USART_RX_GPIO_PIN;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;GPIO_Init(DEBUG_USART_RX_GPIO_PORT, &GPIO_InitStructure); /* 第二步:配置串口的初始化结构体 */// 打开串口外设的时钟DEBUG_USART_APBxClkCmd(DEBUG_USART_CLK, ENABLE);// 配置串口的工作参数// 配置波特率USART_InitStructure.USART_BaudRate = DEBUG_USART_BAUDRATE;// 配置 针数据字长USART_InitStructure.USART_WordLength = USART_WordLength_8b;// 配置停止位USART_InitStructure.USART_StopBits = USART_StopBits_1;// 配置校验位USART_InitStructure.USART_Parity = USART_Parity_No ;// 配置硬件流控制USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;// 配置工作模式,收发一起USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;// 完成串口的初始化配置USART_Init(DEBUG_USARTx, &USART_InitStructure);/*--------------------------------------------------------*/// 串口中断优先级配置NVIC_Configuration();// 使能串口接收中断USART_ITConfig(DEBUG_USARTx, USART_IT_RXNE, ENABLE);
/*--------------------------------------------------------*//* 第三步:使能串口 */   // 使能串口USART_Cmd(DEBUG_USARTx, ENABLE);
}

第一步:打开了GPIO的时钟,设置发送和接收引脚的信息,将Tx(发送引脚)配置为推挽复用模式用来发送数据,Rx(接收引脚)配置为浮空输入模式用来接收数据。
第二步:首先打开USART1 的时钟,根据USART初始化结构体成员配置相关的信息,之后利用初始化函数将初始化结构体中的信息写入相应寄存器中,然后的话就是引用NVIC_Configuration()函数配置串口中断优先级,打开相应的串口接收中断,中断接收函数的参数如下:

第三步 :最后相当于打开总电源——使能串口

USART配置函数完成后代表,USART1 的接收和发送准备工作已经准备就绪,接下来就是,串口与上位机之间的信息传递了,信息的发送和接收都有相对于的函数。

四.传输数据的函数:

开发板与上位机之间的数据传输可以有多种方法,下面一一介绍:

1.发送一个字节

以USART_SendData(pUSARTx,ch); 函数为基础建立的函数可以向上位机发送一个字节的数据,利用FlagStatus USART_GetFlagStatus(USART_TypeDef* USARTx, uint16_t USART_FLAG) 读取发送数据寄存器的状态来 等待发送寄存器将数据成功发送。

void Usart_SendByte( USART_TypeDef * pUSARTx, uint8_t ch)
{/* 发送一个字节数据到USART */USART_SendData(pUSARTx,ch);/* 等待发送数据寄存器为空 */while (USART_GetFlagStatus(pUSARTx, USART_FLAG_TXE) == RESET);
}
2.发送字符串

本质是利用上面的字节发送函数逐位发送字符串中的内容

void USART_SendString(USART_TypeDef * pUSARTx, char *str)
{unsigned int   k=0;while(*(str+k)!='\0'){USART_SendData(pUSARTx, *(str+k));/* 等待发送数据寄存器为空 */while (USART_GetFlagStatus(pUSARTx, USART_FLAG_TXE) == RESET);k++;}while(USART_GetFlagStatus(pUSARTx,USART_FLAG_TC)==RESET);   /* TC:传输完成标志 */
}
3.重定向printf函数发送字符串

关于重定向的知识之前总结过,链接:重定向知识。重定向后的printf()函数功能强大,具有向串口调试助手打印数据的功能,使用方法和c语言时一样,比如printf("欢迎来到小全全的串口实验\n");就可以将“欢迎来到小全全的串口实验”这句话发送到上位机中,而且换行符“\n”还具有换行作用。

/* 重定向printf函数 */
int fputc(int ch, FILE *f)
{USART_SendData( DEBUG_USARTx,  (uint8_t) ch);/* 等待发送完毕 */while (USART_GetFlagStatus(DEBUG_USARTx, USART_FLAG_TXE) == RESET); return ch;
}
4.重定向getchar函数接收字符

具体操作与重定向后的printf函数类似,比如可以通过如下代码向上位机发送已经接收到的数据:

x=getchar();
printf("接收到的字符是:%c\n",x);

重定义如下:

///重定向c库函数scanf到串口,重写向后可使用scanf、getchar等函数
int fgetc(FILE *f)
{/* 等待串口输入数据 */while (USART_GetFlagStatus(DEBUG_USARTx, USART_FLAG_RXNE) == RESET);return (int)USART_ReceiveData(DEBUG_USARTx);
}

在使用此函数作为接收数据时记得关闭串口得接收中断!!!

5.通过中断接收

stm32f10x_it.c中编写USART1中断源相对应得中断函数,利用了固件库函数中的
USART_ReceiveData(DEBUG_USARTx);接收函数
USART_SendData(DEBUG_USARTx, x);发送函数
USART_GetITStatus(DEBUG_USARTx, USART_IT_RXNE);判断标志位函数

/* #define  DEBUG_USART_IRQn         USART1_IRQn #define  DEBUG_USART_IRQHandler   USART1_IRQHandler */
void DEBUG_USART_IRQHandler(void)
{uint16_t  x;/* 判断是否收到中断信号 */if(USART_GetITStatus(DEBUG_USARTx, USART_IT_RXNE) == SET){x = USART_ReceiveData(DEBUG_USARTx);USART_SendData(DEBUG_USARTx, x);}}

结语

以固件库函数编程的思路讲解,未能顾及到众多寄存器的讲解,我认为进行固件库编程本身就是学习操作寄存器的过程,很多时候我们不需要知道如何操作寄存器,只要了解如何操作固件库函数即可。(吹爆固件库编程)

STM32—串口通讯详解相关推荐

  1. delphi 串口通信发送_STM32第五章串口通讯详解

    点击上方"果果小师弟",选择"置顶/星标公众号"干货福利,第一时间送达! 串口通信是串行通信里面的异步方式.串行通信是相对于并行通信来说的.串口是一个事实存在的 ...

  2. STM32串口通信详解以及通信异常或者卡死常见问题分析

    STM32串口通信详解以及通信异常或者卡死常见问题分析 目录 STM32串口通信详解以及通信异常或者卡死常见问题分析 一.常见的异常问题 二.STM32的串口简介 1.串口的通讯方式 ①按数据传输方向 ...

  3. STM32_USART 串口通讯详解

    对51单片机有了解的都知道51单片机的串口通讯工作原理,我们单片机使用的电平TTL电平,为了使我们的的单片机与PC进行通信,就需要一个电平转换芯片,把TTL电平转换为USB电平(使用的USB接口,如果 ...

  4. STM32串口通信详解(嵌入式学习)

    STM32串口通信 1.通信基础知识 1.1 时钟信号区分 同步通信 异步通信 波特率 总线协议(电气协议) 1.2 通信方式划分 串行通信 并行通信 1.3 通信方向划分 单工通信 半双工通信 全双 ...

  5. OpenMV串口通讯详解

    官方教程:串口通讯上:串口通讯下:OpenMV的Uart类函数介绍 目录 材料准备 官方示例代码解析 UART()函数介绍 usart.write()函数介绍 time.sleep_ms(x)函数介绍 ...

  6. c#串口通讯详解(附源码)

    串口通讯 串口通讯是计算机传输数据的一种通讯方式,只不过是以比特位来传输数据的 串口通讯的相关参数 波特率: 波特率的大小代表每秒钟可以传输多少个二进制位,如波特率是9600,能每秒传输9600二进制 ...

  7. STM32串口使用详解

    一.关于串口需要了解的几个知识点: 1.波特率:在串行通讯中,数据是按位进行传送的,因此传送速率用每秒钟传送格式位的数目来表示,称为波特率.    波特率决定了串口传输的速度,1波特=1bps(位/秒 ...

  8. 51单片机串口通讯详解

    串口,作为单片机程序开发中最常用.最方便,也是应用最广泛的程序调试方法:无论是作为调试工具,打印出调试信息,还是对功能模块进行通信,串口是每个单片机开发人员最常用的单片机外设. 由于大部分51单片机不 ...

  9. STM32 —— 串口通讯

    STM32 -- 串口通讯 什么是串口通讯 串口通讯(Serial Communication)是一种设备间非常常用的串行通讯方式,因为它简单便捷,因此大部分电子设备都支持该通讯方式,其通讯协议可分层 ...

最新文章

  1. 调用接口的方法 java_java调用接口的方法
  2. python类继承可以有多个父类_Python3基础 多重继承 一个子类继承于多个父类
  3. GPS Essentials
  4. android9系统webview崩溃,Android WebView已开始在Android 9上崩溃
  5. 项目复审——Beta阶段
  6. android:id = @+id 用法,@+id/android:list和@android:id/list的写法
  7. 怎样实现短信验证功能
  8. python配什么数据库_python中常见数据库有哪些
  9. 解决Myeclipse10 Building Workspace速度慢的问题
  10. OO CSS的个人理解
  11. MCMC 改进粒子滤波算法及其在目标跟踪中的应用
  12. pdfFactory 7PDF 虚拟打印机官方注册码版下载
  13. Visual Odometry
  14. R 回归分析 非线性回归模型
  15. 自制太阳能手机充电器
  16. Foxmail:修改签名和模板(邮箱、邮件)
  17. 背代码可以学好编程吗?下面的回答看的我一脸懵逼!
  18. 七夕节其实是最古老的异地恋
  19. 平面设计分析之图形创意解析
  20. 使用Petalinux实现ZYNQ的linux程序开发(实现简单的socket通信程序)

热门文章

  1. 经典兔子问题(又名斐波那契数列)
  2. php 预编译,预编译的prepare statements 管理, 实现和思路
  3. 经验分享:兢兢业业工作5年的我不敌半年新人,原来“迪赛智慧数”才是升职加薪的关键!
  4. NTFS(文件恢复)最简单情况
  5. windows防火墙
  6. 小程序开发可以用什么语言?
  7. 小组取什么名字好_寓意兴旺的公司名字取什么名字好
  8. Python数据类型(一)数字类型
  9. 记录一下gitHub跑项目的步骤
  10. 腾讯 美团 字节 抖音 面经