找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 7370|回复: 0
收起左侧

STM32F407串口USART配置详细教程 附源程序

[复制链接]
ID:763998 发表于 2020-6-19 15:49 | 显示全部楼层 |阅读模式

USART的概述

2.1.1 什么是USART?USART的作用?

              USART:通用同步异步收发器。

              USART的作用:能够灵活地与外部设备进行全双工数据交换

2.1.2 USART的特征

<1> 全双工异步通信

<2> 可配置为 16 倍过采样或 8 倍过采样

<3> 小数波特率发生器系统

<4> 数据字长度可编程( 8 位或 9 位)

<5> 停止位可配置 - 支持 1 或 2 个停止位

<6> 发送器和接收器具有单独使能位

<7>传输检测标志:

— 接收缓冲区已满

— 发送缓冲区为空

— 传输结束标志

<8>十个具有标志位的中断源:

— CTS 变化

— LIN 停止符号检测

发送数据寄存器为空

发送完成

接收数据寄存器已满

接收到线路空闲

— 溢出错误

— 帧错误

— 噪声错误

— 奇偶校验错误




      • USART功能描述

任何USART双向通信均需要至少两个引脚:

接收数据输入引脚 (RX)

发送数据引脚输出 (TX)

              正常 USART 模式下

                            发送或接收前保持空闲线路

                            起始位

                            数据(字长 8 位或 9 位),最低有效位在前

                            用于指示帧传输已完成的 0.5 个、 1 个、 1.5 个、 2 个停止位

              TX引脚在起始位工作期间处于低电平状态。在停止位工作期间处于高电平状态。

2.2 USART的框架

2.2.1发送数据过程

数据发送过程.png

放大后的各个部分:

GPIO部分:

映射部分:

USART部分:

2.2.2接收数据过程

数据接收过程.png

放大后的各个部分:

GPIO部分:

映射部分:

USART部分:

2.2.3 发送与接收过程解读

GPIO要配为复用功能

复用与通用的区别:这里的外设就是USART

发送过程:

  • 内核把数据交给USART的发送数据寄存器(TDR
  • TDR通过并行总线,一次性写入到发送移位寄存器中
  • 发送移位寄存器移位一位一位的传输数据,直到数据发送完毕。
  • 发送移位寄存器没有数据时,TDR才把数据一次写入。

接收过程:

  • 接收移位寄存器从外部获取每一位数据
  • 当移位数据寄存器挤满8位或9位数据时,通过并行总线,一次发送到接收数据寄存器(RDR
  • 只能等移位寄存器凑够8位或9位数据时,才会把数据发送到RDR,内核此时才能读取到正确的数据。

注意:

              发送数据寄存器(TDR)与接收数据寄存器(RDR)是两个寄存器,写代码时只有DR,DR代表发送数据寄存器还是接收数据寄存器,取决于所在函数是接收还是发送。

2.2.4 USART映射解读

查看原理图,可知USART1的发送TX与接收RX对应引脚分别为PA9\PA10。

这也是M3默认的映射引脚。

与PA9与PA10可知我们选择的复用寄存器是GPIOx_AFRH

由图可知,

  • 配置PA9PA10为复用功能
  • 找引脚对应的复用功能寄存器,PA9\PA10对应AFRH寄存器
  • AFRH中找引脚对应控制位,PA9?AFRH9[3:0]PA10?AFRH10[3:0]
  • 通过映射图可知,USART1对应的值为AF7
  • AF7写入PA9\PA10对应控制位的位置

2.3 USART波特率的配置

2.3.1 配置波特率公式

              fCK看USART挂载的外设总线,可知84MHz

OVER8根据控制寄存器1的位15可知,默认采用16倍过采样,OVER8=0

USARTDIV根据下面公式,算得:

2.3.2 实际配置波特率过程

《1》确定需要配置的波特率、采用默认过采用模式

《2》根据公式1,可求出USARTDIV

《3》USARTDIV是写入到波特率寄存器 (USART_BRR)的浮点数,由于寄存器不能直接写入浮点数,所以需要把整数和小数分开写入到USART_BRR中。

《4》查看寄存器USART_BRR可知,12位控制整数,4位控制小数。

《5》USARTDIV的一个浮点数,进行强制转换为整型,即可获得它的整数部分DIV_Mantissa,最后通过USATRDIV公式,可算出小数部分DIV_Fraction。

《6》在写入整数部分时,整数位要左移4位,因为从位4开始写入整数部分,小数部分直接写入。

2.4 软件设计

2.4.1 USART配置流程

              《1》开GPIOA\USART1时钟

              《2》配置GPIOA为复用推挽输出

              《3》映射PA9与PA10到USART_TX\USART_RX

              《4》配置波特率

              《5》配置USART模块

2.4.2 USART模块配置

  • 使能发送器、接受器
  • 使能USATR
  • 其他位使用默认值。如:16倍过采样、8位字长、1位停止位等

2.4.3 USAR1初始化函数

  1. /**********************************************************************
  2. *函数名:USART1_Init
  3. *功  能:串口初始化
  4. *参  数:波特率
  5. *返  回:无
  6. *备  注:
  7. PA9  -发送--USART1_TX
  8. PA10 -接受--USART1_RX
  9. 以芯片为对象,出去的叫发送,进来的叫接收
  10. **********************************************************************/
  11. void USART1_Init(int baud)
  12. {
  13.               float usartdiv;
  14.               u32 DIV_Mantissa,DIV_Fraction;
  15.               //1.开启时钟
  16.               RCC->APB2ENR |= 1<<4;              //开启USART1时钟                           
  17.               RCC->AHB1ENR |= 1<<0;              //开启PA端口时钟                                         
  18.               //2.配置GPIO
  19.               GPIOA->MODER &=~(3<<2*9);                            // 复用
  20.               GPIOA->MODER |= (2<<2*9);                           
  21.               GPIOA->MODER &=~(3<<2*10);            
  22.               GPIOA->MODER |= (2<<2*10);            
  23.               GPIOA->OTYPER &=~(1<<9);                            // 推挽
  24.               GPIOA->OTYPER &=~(1<<10);                           
  25.               GPIOA->OSPEEDR &=~(3<<2*9);              // 25M
  26.               GPIOA->OSPEEDR |=1<<2*9;                           
  27.               GPIOA->OSPEEDR &=~(3<<2*10);
  28.               GPIOA->OSPEEDR |=1<<2*10;                           
  29.               GPIOA->PUPDR &=~(3<<2*9);  // 无上下拉
  30.               GPIOA->PUPDR &=~(3<<2*10);
  31.               //3.端口映射
  32.               GPIOA->AFR[1] &=~(0xf<<4);            
  33.               GPIOA->AFR[1] |=(7<<4);                                         
  34.               GPIOA->AFR[1] &=~(0xf<<8);            
  35.               GPIOA->AFR[1] |=(7<<8);                                         
  36.               //4.设置波特率
  37.               usartdiv=84*1000000/(16.0*baud);
  38.               DIV_Mantissa=usartdiv;// 整数部分
  39.               DIV_Fraction=(usartdiv-DIV_Mantissa)*16;// 小数部分
  40.               USART1->BRR = DIV_Mantissa<<4|DIV_Fraction;                           
  41.               //5.配置USART1
  42.               USART1->CR1 |= 1<<2; // 接收使能
  43.               USART1->CR1 |= 1<<3; // 发送使能
  44.               USART1->CR1 |= 1<<13;// USART1使能
  45. 2.4.4 USART1发送与接收字节符函数
  46. /**********************************************************************
  47. *函数名:USART1_Send_Byte
  48. *功  能:发送数据给串口软件
  49. *参  数:数据
  50. *返  回:无
  51. *备  注:
  52. 寄存器                            状态                                                                                    位
  53. USART->SR              等待发送完成                             6,7
  54. **********************************************************************/
  55. void USART1_Send_Byte(u8 data)
  56. {
  57.               while(!(USART1->SR & 1<<6));//等待发送完成
  58.               USART1->DR = data;
  59. }
  60. /**********************************************************************
  61. *函数名:USART1_Receive_Byte
  62. *功  能:接收从串口软件发送过来的数据
  63. *参  数:无
  64. *返  回:数据
  65. *备  注:
  66. 寄存器                            状态                                                                                    位
  67. USART->SR              等待接收完成                             5
  68. **********************************************************************/
  69. u8 USART1_Receive_Byte(void)
  70. {
  71.               u8 data;
  72.               while(!(USART1->SR & 1<<5));//等待接收完成
  73.               data = USART1->DR;
  74.               return data;
  75. }
  76. 2.4.5 USART1发送与接收字符串函数
  77. /**********************************************************************
  78. *函数名:USART1_Send_String
  79. *功  能:发送字符串数据给串口软件
  80. *参  数:字符串数据
  81. *返  回:无
  82. *备  注:
  83. 寄存器                            状态                                                                                    位
  84. USART->SR              等待发送完成                             6,7
  85. **********************************************************************/
  86. void USART1_Send_String(u8 *data)
  87. {
  88.               while(*data != '\0')//是否字符串结束标志符
  89.               {
  90.                             USART1_Send_Byte(*data);
  91.                             data++;//指向下一个字符
  92.               }
  93. }
  94. u8 USART1_receiveBuf[128];
  95. /**********************************************************************
  96. *函数名:USART1_Receive_String
  97. *功  能:接收从串口软件发送给内核发数据
  98. *参  数:缓冲区数组,存放数据
  99. *返  回:无
  100. *备  注:
  101. 寄存器                            状态                                                                                    位
  102. USART->SR              等待接收完成                             5
  103. **********************************************************************/
  104. void USART1_Receive_String(void)
  105. {
  106.               static u8 i=0;
  107.               u8 data;
  108.               while(1)
  109.               {
  110.                             data = USART1_Receive_Byte();//接收一个字符
  111.                             if(data == '\n')
  112.                             {
  113.                                           USART1_receiveBuf[ i]='\0';//添加字符串结束标志符
  114.                                           i=0;//索引清零
  115.                                          return;
  116.                             }
  117.                             USART1_receiveBuf[i++] = data;//把字符存放在字符数组中
  118.               }
  119. }</i>
复制代码

2.5 补充

2.5.1 问答

<1>串口是什么?有什么用?

串口是一种串行全双通信接口,同步或异步收发数据,但一般我们只使用异步功能。

常用于与外部设备通信、交互信息。外部若有串口通信接口,就可以与单片机进行通信,如ESP8266模块、RS485模块等。


<2>同步与异步的理解?

同步与异步基于两个设备讨论:

同步:它们有共同的时钟线,由时钟线控制收发

异步:它们没有公共的时钟线,需要双方配置一样的波特率,保证收发的准确。


<3>串行与并行

串行:

只有一根线或两个根数据线,一次只能收发一位数据。两根线的设计是为了两个设备能同时收发一位数据。

并行:

有多根数据线,一般是8的倍数,假设是8根数据线,一次可传送一个字节(8位)的数据。


<4>单工、半双工、全双工

单共:

一方只能接收,另一方只能发送,从始至终发送方向不变,单方向固定。例如:广播与收音机。广播只能发出信号,收音机只能接收信号,两者互换不能正常工作。

半双工:

某一时间段,一方发送。另一方接收;另一个时间段,一方接收,另一方发送。双方都可以发送和接收,但不能同时发送或接收。例如:对讲机。

全双工:

双方可以都可以同时收发。例如:电话


<5>波特率是什么为什么要配置波特率?

              一秒钟能传输的二级进制位数。假设9600代表1秒钟可以一次传输9600位。即9.6Kbit。

              异步通信双方需要有个约定,发送方以多少速度(波特率)发送数据过去(例如9600),接收方就必须以对应的速度(速度)接收,从而保证读取到正确的数据。


<6>如何保证数据准确发送过去呢

              USART串口通信自带有通信协议,一帧数据位10位或11位,常常使用10位作为一帧数据。

              一帧数据的构成:

  • 1个启动位(低电平)
  • 数据帧(8位或9位,如果开启奇偶校验,最高位是奇偶检验位,位7或位8,但是一般不开启)
  • 停止位(高电平,0.5位、1位、1.5位、2位,一般选1位停止位)
  • 综上,一般串口一帧数据为10(1个启动位、8个数据位、1个停止位)


<7>知识领悟

模块学习心得:

  • 掌握基本概念
  • 理解并记住模块的特性
  • 模块框图的工作流程,信号走向,逻辑(重点)
  • 看懂模块的时序图,理解其他相关知识
  • 会配置寄存器(即使上面的不是很理解,但是尽量理解)
复用与通用.png

3.USART.docx

1.74 MB, 下载次数: 10, 下载积分: 黑币 -5

程序.7z

293.03 KB, 下载次数: 25, 下载积分: 黑币 -5

评分

参与人数 1黑币 +50 收起 理由
admin + 50 共享资料的黑币奖励!

查看全部评分

回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表