USART串口通讯
串口通讯
- 1. 通讯概念
- 1.1 串行通讯与并行通讯
- 1.2 全双工、半双工及单工通讯
- 1.3 同步通讯与异步通讯
- 1.4 通讯速率
- 2. 串口通讯
- 2.1 串口通讯协议----物理层
- 2.2 串口通讯协议----协议层
- 3. USART串口
- 3.1 USART功能框图
- 3.2 USART 初始化结构体详解
- 3.3 USART 硬件设置
- 3.4 USART 开发步骤
- 4. DMA 直接存储区访问
- 4.1 DMA 简介
- 4.2 DMA 功能框图
- 4.3 DMA 数据配置
- 4.4 DMA 中断
- 4.5 DMA 开发步骤
1. 通讯概念
1.1 串行通讯与并行通讯
按数据传送的方式,通讯可分为
串行通讯
与并行通讯
,并行通讯就像多个车道的公路,可以同时传输多个数据位的数据,而串行通讯就像单个车道的公路,同一时刻只能传输一个数据位的数据。
串行通讯
是指设备之间通过少量数据信号线 (一般是 8 根以下),地线以及控制信号线,按数据位形式一位一位地传输数据的通讯方式。
并行通讯
一般是指使用 8、16、32 及 64 根或更多的数据线进行传输的通讯方式。
很明显,因为一次可传输多个数据位的数据,在数据传输速率相同的情况下,并行通讯传输的数据量要大得多,而串行通讯则可以节省数据线的硬件成本 (特别是远距离时) 以及 PCB 的布线面积。不过由于并行传输对同步要求较高,且随着通讯速率的提高,信号干扰的问题会显著影响通讯性能。
1.2 全双工、半双工及单工通讯
根据数据通讯的方向,通讯又分为
全双工
、半双工
及单工
通讯,它们主要以信道的方向来区分:
通 讯 方式 说明 全双工
在同一时刻,两个设备之间可以同时收发数据,如日常的打电话。 半双工
两个设备之间可以收发数据,但不能在同一时刻进行,需要分时进行,如对讲机。 单工
在任何时刻都只能进行一个方向的通讯,即一个固定为发送设备,另一个固定为接收设备,如广播。
1.3 同步通讯与异步通讯
根据通讯的数据同步方式,又分为
同步
和异步
两种,可以根据通讯过程中是否有使用到时钟信号进行简单的区分:
通讯方式 同步通讯
异步通讯
说明 要求通信双方共用同一时钟信号,在总线上保持统一的时序和周期完成信息传输 不需要时钟信号,而是在数据信号中加入开始位和停止位等一些同步信号,以便使接收端能够正确地将每一个字符接收下来,某些通信中还需要双方约定传输速率 优点 可以实现高速率、大容量的数据传输,以及点对多点传输 没有时钟信号硬件简单,双方时钟可允许一定误差 缺点 要求发送时钟和接收时钟保持严格同步,收发双方时钟允许的误差较小,同时硬件复杂 通信速率较低,只适用点对点传输
1.4 通讯速率
在数字通信系统中,通信速率(传输速率)指数据在信道中传输的速度,它分为两种:
传信率
和传码率
。
传信率(比特率)
每秒钟传输的信息量,即每秒钟传输的二进制位数,单位为 bit/s(即比特每秒) 传码率(波特率)
每秒钟传输的码元个数,单位为 Baud(即波特每秒)
比特率
和波特率
这两个概念又常常被人们混淆。波特率
被传输的是码元,码元是信号被调制后的概念,每个码元都可以表示一定 bit 的数据信息量。举个例子,在 TTL 电平标准的通信中,用 0V 表示逻辑 0,5V 表示逻辑 1,这时候这个码元就可以表示两种状态。如果电平信号 0V、2V、4V 和 6V 分别表示二进制数 00、01、10、11,这时候每一个码元就可以表示四种状态。由上述可以看出,码元携带一定的比特信息,所以比特率和波特率的关系可以用以下式子表示:
其中 M 表示码元承载的信息量。我们也可以理解 M 为码元的进制数。
举个例子:波特率为 100 Baud,即每秒传输 100 个码元,如果码元采用十六进制编码(即M=16,代入上述式子),那么这时候的比特率就是 400 bit/s。如果码元采用二进制编码(即 M=2,代入上述式子),那么这时候的比特率就是 100 bit/s。
可以看出采用二进制时,波特率和比特率数值上相等。但是要注意,它们的相等只是数值相等,其意义上不同,看波特率和波特率单位就知道。
2. 串口通讯
2.1 串口通讯协议----物理层
串口通讯的物理层有很多标准及变种,其中 RS-232 标准主要规定了信号的用途、通讯接口以及信号的电平标准。使用 RS-232 标准的串口设备间常见的通讯结构:
在上面的通讯方式中,两个通讯设备的“DB9 接口”之间通过串口信号线建立起连接,串口信号线中使用“RS-232 标准”传输数据信号。由于 RS-232 电平标准的信号不能直接被控制器直接识别,所以这些信号会经过一个“电平转换芯片”转换成控制器能识别的“TTL 标准”的电平信号,才能实现通讯。
根据通讯使用的电平标准不同,串口通讯可分为
TTL 标准
及RS-232 标准
:
通讯标准 电平标准 (发送端) 5V TTL
逻辑 1:2.4V-5V 逻辑 0:0~0.5V RS-232
逻辑 1:-15V~-3V 逻辑 0:+3V~+15V
DB9 接口中的公头及母头的各个引脚的标准信号线接法见图:
在目前的其它工业控制使用的串口通讯中,一般只使用 RXD、TXD 以及 GND 三条信号线,直接传输数据信号。而 RTS、CTS、DSR、DTR 及 DCD 信号都被裁剪掉了,可以直接忽略它们。
RS-485
是一种工业控制环境中常用的通讯协议,它具有抗干扰能力强、传输距离远的特点。RS-485 通讯协议由 RS-232 协议改进而来,协议层不变,只是改进了物理层,因而保留了串口通讯协议应用简单的特点。RS-485 协议主要是把 RS-232 的信号改进成差分信号,从而大大提高了抗干扰特性。
在 RS-485 通讯网络中,节点中的串口控制器使用 RX 与 TX 信号线连接到收发器上,而收发器通过差分线连接到网络总线,串口控制器与收发器之间一般使用 TTL 信号传输,收发器与总线则使用差分信号来传输。发送数据时,串口控制器的 TX 信号经过收发器转换成差分信号传输到总线上,而接收数据时,收发器把总线上的差分信号转化成 TTL 信号通过 RX 引脚传输到串口控制器中。
RS-485 通讯网络的最大传输距离可达 1200 米,总线上可挂载 128 个通讯节点,而由于 RS-485 网络只有一对差分信号线,它使用差分信号来表达逻辑,当 AB 两线间的电压差为-6V~-2V 时表示逻辑 1,当电压差为 +2V~+6V 表示逻辑 0,在同一时刻只能表达一个信号,所以它的通讯是半双工
形式的。
2.2 串口通讯协议----协议层
串口通讯的数据包由发送设备通过自身的 TXD 接口传输到接收设备的 RXD 接口。在串口通讯的协议层中,规定了数据包的内容,它由
启始位
、主体数据
、校验位
以及停止位
组成,通讯双方的数据包格式要约定一致才能正常收发数据,其组成见图:
串口通信协议数据包组成可以分为
波特率
和数据帧格式
两部分:
异步通讯中由于没有时钟信号,所以两个通讯设备之间需要约定好波特率。波特率表示每秒钟传送的码元符号的个数,所以它决定了数据帧里面每一个位的时间长度。两个要通信的设备的波特率一定要设置相同,我们常见的波特率是 4800、9600、115200 等。
数据帧格式:
2.1起始位和停止位:
串口通信的一个数据帧是从起始位开始,直到停止位。数据帧中的起始位是由一个逻辑 0 的数据位表示,而数据帧的停止位可以是 0.5、1、1.5 或 2 个逻辑 1 的数据位表示,只要双方约定一致即可。
2.2有效数据位:
数据帧的起始位之后,就接着是数据位,也称有效数据位,这就是我们真正需要的数据,有效数据位通常会被约定为 5、6、7 或者 8 个位长。有效数据位是低位(LSB)在前,高位(MSB)在后。
2.3校验位:
校验位可以认为是一个特殊的数据位。校验位一般用来判断接收的数据位有无错误,检验方法有:奇检验、偶检验、0 检验、1 检验以及无检验。
奇校验
是指有效数据为和校验位中“1”的个数为奇数,比如一个 8 位长的有效数据为:10101001,总共有 4 个“1”,为达到奇校验效果,校验位设置为“1”,最后传输的数据是 8 位的有效数据加上 1 位的校验位总共 9 位。
偶校验
与奇校验要求刚好相反,要求帧数据和校验位中“1”的个数为偶数,比如数据帧:11001010,此时数据帧“1”的个数为 4 个,所以偶校验位为“0”。
0 校验
是指不管有效数据中的内容是什么,校验位总为“0”,1 校验
是校验位总为“1”
无校验
是指数据帧中不包含校验位。
3. USART串口
3.1 USART功能框图
① USART 信号引脚:
TX:
发送数据输出引脚RX:
接收数据输入引脚。SW_RX:
数据接收引脚,只用于单线和智能卡模式,属于内部引脚,没有具体外部引脚。nRTS:
请求发送 (Request To Send),n 表示低电平有效。如果使能 RTS 流控制,当 USART接收器准备好接收新数据时就会将 nRTS 变成低电平;当接收寄存器已满时,nRTS 将被设置为高电平。该引脚只适用于硬件流控制。nCTS:
清除发送 (Clear To Send),n 表示低电平有效。如果使能 CTS 流控制,发送器在发送下一帧数据之前会检测 nCTS 引脚,如果为低电平,表示可以发送数据,如果为高电平则在发送完当前数据帧之后停止发送。该引脚只适用于硬件流控制。SCLK:
发送器时钟输出引脚。这个引脚仅适用于同步模式。
② 数据寄存器:
- USART 数据寄存器 (USART_DR) 只有低 9 位有效,并且第 9 位数据是否有效要取决于 USART 控制寄存器 1(USART_CR1) 的 M 位设置,当 M 位为 0 时表示 8 位数据字长,当 M 位为 1 表示 9 位数据字长,我们一般使用 8 位数据字长。
- USART_DR 包含了已发送的数据或者接收到的数据。USART_DR 实际是包含了两个寄存器,一个专门用于发送的可写
TDR
,一个专门用于接收的可读RDR
。当进行发送操作时,往 USART_DR 写入数据会自动存储在 TDR 内;当进行读取操作时,向 USART_DR 读取数据会自动提取 RDR 数据。- TDR 和 RDR 都是介于系统总线和移位寄存器之间。串行通信是一个位一个位传输的,发送时把 TDR 内容转移到发送移位寄存器,然后把移位寄存器数据每一位发送出去,接收时把接收到的每一位顺序保存在接收移位寄存器内然后才转移到 RDR。
- USART 支持 DMA 传输,可以实现高速数据传输。
③ 控制器:
USART 有专门控制发送的发送器、控制接收的接收器,还有唤醒单元、中断控制等等。使用 USART 之前需要向 USART_CR1 寄存器的 UE 位置 1 使能 USART。发送或者接收数据字长可选 8 位或 9 位,由 USART_CR1 的 M 位控制。
发送器,
当 USART_CR1 寄存器的发送使能位 TE 置 1 时,启动数据发送,发送移位寄存器的数据会在 TX引脚输出,如果是同步模式 SCLK 也输出时钟信号。
一个字符帧发送需要三个部分:起始位 + 数据帧 + 停止位。起始位是一个位周期的低电平,位周期就是每一位占用的时间;数据帧就是我们要发送的 8 位或 9 位数据,数据是从最低位开始传输的;停止位是一定时间周期的高电平。停止位时间长短是可以通过 USART 控制寄存器 2(USART_CR2) 的 STOP[1:0] 位控制,可选 0.5个、1 个、1.5 个和 2 个停止位。默认使用 1 个停止位。2 个停止位适用于正常 USART 模式、单线模式和调制解调器模式。0.5 个和 1.5 个停止位用于智能卡模式。
当发送使能位 TE 置 1 之后,发送器开始会先发送一个空闲帧 (一个数据帧长度的高电平),接下来就可以往 USART_DR 寄存器写入要发送的数据。在写入最后一个数据后,需要等待 USART 状态寄存器 (USART_SR) 的 TC 位为 1,表示数据传输完成,如果 USART_CR1 寄存器的 TCIE 位置 1,将产生中断。
选择 8 位字长,使用 1 个停止位时,具体发送字符时序图见图:
在发送数据时,编程的时候有几个比较重要的标志位
接收器,
如果将 USART_CR1 寄存器的 RE 位置 1,使能 USART 接收,使得接收器在 RX 线开始搜索起始位。在确定到起始位后就根据 RX 线电平状态把数据存放在接收移位寄存器内。接收完成后就把接收移位寄存器数据移到 RDR 内,并把 USART_SR 寄存器的 RXNE 位置 1,同时如果 USART_CR2 寄存器的 RXNEIE 置 1 的话可以产生中断。
为得到一个信号真实情况,需要用一个比这个信号频率高的采样信号去检测,称为过采样,这个采样信号的频率大小决定最后得到源信号准确度,一般频率越高得到的准确度越高,但为了得到越高频率采样信号也越困难,运算和功耗等等也会增加,所以一般选择合适就好。接收器可配置为不同过采样技术,以实现从噪声中提取有效的数据。USART_CR1 寄存器的 OVER8 位用来选择不同的过采样方法,如果 OVER8 位设置为 1 采用 8 倍过采样,即用 8 个采样信号采样一位数据;如果 OVER8 位设置为 0 采用 16 倍过采样,即用 16 个采样信号采样一位数据。USART 的起始位检测需要用到特定序列。如果在 RX 线识别到该特定序列就认为是检测到了起始位。起始位检测对使用 16 倍或 8 倍过采样的序列都是一样的。该特定序列为:1110X0X0X0000,其中 X 表示电平任意,1 或 0 皆可。
8 倍过采样速度更快,最高速度可达 fPCLK/8,fPCLK 为 USART 时钟,使用第 4、5、6 次脉冲的值决定该位的电平状态。
16 倍过采样速度虽然没有 8 倍过采样那么快,但得到的数据更加精准,其最大速度为 fPCLK/16,使用第 8、9、10 次脉冲的值决定该位的电平状态。
④ 时钟与波特率:
波特率通过以下公式得出:
波特率 = f P L C K 8 × ( 2 − O V E R 8 ) × U S A R T D I V 波特率 = \frac{f_{PLCK}}{8 \times (2 - OVER8) \times USARTDIV} 波特率=8×(2−OVER8)×USARTDIVfPLCK
其中,fPLCK 为 USART 时钟(84MHz / 42MHz);OVER8 为 USART_CR1 寄存器的 OVER8 位对应的值,USARTDIV 是一个存放在波特率寄存器 (USART_BRR) 的一个无符号定点数。其中 DIV_Mantissa[11:0] 位定义 USARTDIV 的整数部分,DIV_Fraction[3:0] 位定义 USARTDIV 的小数部分,DIV_Fraction[3] 位只有在 OVER8 位为 0 时有效,否则必须清零。
例如,如果 OVER8=0,DIV_Mantissa=24 且 DIV_Fraction=10,此时 USART_BRR 值为 0x18A;那么 USARTDIV 的小数位 10/16=0.625;整数位 24,最终 USARTDIV 的值为 24.625。如果 OVER8=0 并且知道 USARTDIV 值为 27.68,那么 DIV_Fraction=16*0.68=10.88,最接近的正整数为 11,所以 DIV_Fraction[3:0] 为 0xB;DIV_Mantissa= 整数 (27.68)=27,即位 0x1B。如果 OVER8=1 情况类似,只是把计算用到的权值由 16 改为 8。
当我们使用 16 倍过采样时即 OVER8=0,为得到 115200bps 的波特率,解得 USARTDIV=45.57,可算得 DIV_Fraction=0x9(0.57 * 2 4 2^4 24=9.12 取整,在 BRR 寄存器中,表示小数位的有 4 位),DIV_Mantissa=0x2D,即应该设置 USART_BRR 的值为 0x2D9。在计算 DIV_Fraction 时经常出现小数情况,经过我们取舍得到整数,这样会导致最终输出的波特率较目标值略有偏差。下面我们从 USART_BRR 的值为 0x2D9 开始计算得出实际输出的波特率大小。由 USART_BRR 的 值 为 0x2D9, 可 得 DIV_Fraction=45,DIV_Mantissa=9, 所 以 USARTDIV=45+9/16=45.5625,所以实际波特率为:115226;这个值跟我们的目标波特率相差很小,这么小的误差在正常通信的允许范围内。8 倍过采样时计算情况原理是一样的。
校验控制,
当使用校验位时,串口传输的长度将是 8 位的数据帧加上 1 位的校验位总共 9 位,此时 USART_CR1 寄存器的 M 位需要设置为 1,即 9 数据位。将 USART_CR1 寄存器的 PCE 位置 1 就可以启动奇偶校验控制,奇偶校验由硬件自动完成。启动了奇偶校验控制之后,在发送数据帧时会自动添加校验位,接收数据时自动验证校验位。接收数据时如果出现奇偶校验位验证失败,会见 USART_SR 寄存器的 PE 位置 1,并可以产生奇偶校验中断。使能了奇偶校验控制后,每个字符帧的格式将变成:起始位 + 数据帧 + 校验位 + 停止位。
中断控制,
USART 有多个中断请求事件,具体见表:
3.2 USART 初始化结构体详解
USART 初始化结构体
USART_BaudRate 波特率设置。一般设置为 9600、19200、115200。根据设定值计算得到 USARTDIV 值,并设置 USART_BRR 寄存器值。 USART_WordLength 数据帧字长,可选 8 位或 9 位。设定 USART_CR1 寄存器的 M 位的值。如果没有使能奇偶校验控制,一般使用 8 数据位;如果使能了奇偶校验则一般设置为 9 数据位。 USART_StopBits 停止位设置,可选 0.5 个、1 个、1.5 个和 2 个停止位,设定 USART_CR2 寄存器的 STOP[1:0] 位的值,一般选择 1 个停止位。 USART_Parity 奇偶校验控制选择,可选 USART_Parity_No(无校验)、USART_Parity_Even(偶校验) 以及 USART_Parity_Odd(奇校验),它设定 USART_CR1 寄存器的 PCE 位和 PS 位的值。 USART_Mode USART 模式选择,有 USART_Mode_Rx 和 USART_Mode_Tx,允许使用逻辑或运算选择两个,它设定 USART_CR1 寄存器的 RE 位和 TE 位。 USART_HardwareFlowControl 硬件流控制选择,只有在硬件流控制模式才有效,可选有使能 RTS、使能 CTS、同时使能 RTS 和 CTS、不使能硬件流。
USART 时钟初始化结构体
USART_Clock 同步模式下 SCLK 引脚上时钟输出使能控制,可选禁止时钟输出(USART_Clock_Disable) 或开启时钟输出 (USART_Clock_Enable);如果使用同步模式发送,一般都需要开启时钟。它设定 USART_CR2 寄存器的 CLKEN 位的值。 USART_CPOL 同步模式下 SCLK 引脚上输出时钟极性设置,可设置在空闲时 SCLK 引脚为低电平 (USART_CPOL_Low) 或高电平 (USART_CPOL_High)。它设定 USART_CR2 寄存器的 CPOL 位的值。 USART_CPHA 同步模式下 SCLK 引脚上输出时钟相位设置,可设置在时钟第一个变化沿捕获数据 (USART_CPHA_1Edge) 或在时钟第二个变化沿捕获数据。它设定 USART_CR2 寄存器的CPHA 位的值。USART_CPHA 与 USART_CPOL 配合使用可以获得多种模式时钟关系。 USART_LastBit 选择在发送最后一个数据位的时候时钟脉冲是否在 SCLK 引脚输出,可以是不输出脉冲 (USART_LastBit_Disable)、输出脉冲 (USART_LastBit_Enable)。它设定 USART_CR2 寄存器的 LBCL 位的值。
3.3 USART 硬件设置
RS-232,
为利用 USART 实现开发板与电脑通信,需要用到一个USB 转 USART 的 IC(CH340G芯片)
,CH340G 是一个 USB 总线的转接芯片,实现 USB 转 USART、USB 转 IrDA红外或者 USB 转打印机接口,我们使用其 USB 转 USART 功能。
RS-485,
板采用MAX3485CSA
作为收发器器,该芯片支持 3.3V 供电,最大传输速度可达 10Mbps,支持多达 32 个节点,并且有输出短路保护。A、B 总线接口,用于连接 485 总线,RXD 是接收输出端,TXD 是发送数据收入端,RE是接收使能信号(低电平有效),DE 是发送使能信号(高电平有效)。
当 RE 引脚为低电平时,485 芯片处于接收状态,当 DE 引脚为高电平时芯片处于发送状态。通过控制 PG8 的输出电平即可控制 485 的收发状态
3.4 USART 开发步骤
4. DMA 直接存储区访问
4.1 DMA 简介
DMA(直接存储区访问)
为实现数据高速在外设寄存器与存储器之间或者存储器与存储器之间传输提供了高效的方法。之所以称之为高效,是因为 DMA 传输实现高速数据移动过程无需任何 CPU 操作控制,也没有中断处理方式那样保留现场和恢复现场的过程,通过硬件为 RAM 与 I/O 设备开辟一条直接传送数据的通路,能使 CPU 的效率大为提高。从硬件层次上来说,DMA 控制器是独立于 Cortex-M4 内核的,有点类似 GPIO、USART 外设一般,只是 DMA 的功能是可以快速移动内存数据。DMA 支持
外设到存储器传输
、存储器到外设传输
和存储器到存储器传输
三种传输模式。外设
一般指外设的数据寄存器,比如 ADC、SPI、I2C、DCMI 等等外设的数据寄存器,存储器
一般是指片内 SRAM、外部存储器、片内 Flash 等等。
外设到存储器传输
就是把外设数据寄存器内容转移到指定的内存空间。比如进行 ADC 采集时我们可以利用 DMA 传输把 AD 转换数据转移到我们定义的存储区中,这样对于多通道采集、采样频率高、连续输出数据的 AD 采集是非常高效的处理方法。存储区到外设传输
就是把特定存储区内容转移至外设的数据寄存器中,这种多用于外设的发送通信。存储器到存储器传输
就是把一个指定的存储区内容拷贝到另一个存储区空间。功能类似于 C 语言内存拷贝函数 memcpy,利用 DMA 传输可以达到更高的传输效率,特别是 DMA 传输是不占用 CPU 的,可以节省很多 CPU 资源。
4.2 DMA 功能框图
DMA 支持
外设到存储器传输
、存储器到外设传输
和存储器到存储器传输
三种传输模式,这要得益于 DMA 控制器是采样 AHB 主总线的,可以控制 AHB 总线矩阵来启动 AHB 事务。DMA 有以下一些特性:
① 双 AHB 主总线架构,一个用于存储器访问,另一个用于外设访问。
② 仅支持 32 位访问的 AHB 从编程接口。
③ 每个 DMA 控制器有 8 个数据流,每个数据流有多达 8 个通道(请求)。
④ 每个数据流有单独的四级 32 位先进先出存储器缓冲区(FIFO),可用于 FIFO 模式或直接模式。
⑤ 通过硬件可以将每个数据流配置为:
1,支持外设到存储器、存储器到外设和存储器到存储器传输的常规通道。
2,支持在存储器方双缓冲的双缓冲区通道。
⑥ 8 个数据流中的每一个都连接到专用硬件 DMA 通道(请求)。
⑦ DMA 数据流请求之间的优先级可用软件编程(4 个级别:非常高、高、中、低),在软件优先级相同的情况下可以通过硬件决定优先级(例如,请求 0 的优先级高于请求 1)
⑧ 每个数据流也支持通过软件触发存储器到存储器的传输(仅限 DMA2 控制器)
⑨可供每个数据流选择的通道请求数多达 8 个。此选择可由软件配置,允许多个外设启动 DMA 请求。
⑩ 要传输的数据项的数目可以由 DMA 控制器或外设管理:
1,DMA 流控制器:要传输的数据项的数目是 1 到 65535,可用软件编程。
2,外设流控制器:要传输的数据项的数目未知并由源或目标外设控制,这些外设通过硬件发出传输结束的信号。
⑪ 独立的源和目标传输宽度(字节、半字、字):源和目标的数据宽度不相等时,DMA 自动封装/解封必要的传输数据来优化带宽。这个特性仅在 FIFO 模式下可用。
⑫ 对源和目标的增量或非增量寻址。
⑬ 支持 4 个、8 个和 16 个节拍的增量突发传输。突发增量的大小可由软件配置,通常等于外设 FIFO 大小的一半。
⑭ 每个数据流都支持循环缓冲区管理。
⑮ 5 个事件标志(DMA 半传输、DMA 传输完成、DMA 传输错误、DMA FIFO 错误、直接模式错误),进行逻辑或运算,从而产生每个数据流的单个中断请求。
1.外设通道选择:
每个 DMA 控制器具有 8 个数据流,每个数据流对应 8 个外设请求。在实现 DMA 传输之前,DMA 控制器会通过 DMA 数据流 x配置寄存器DMA_SxCR
(x 为 0~7,对应 8 个 DMA 数据流) 的 CHSEL[2:0] 位选择对应的通道作为该数据流的目标外设。外设通道选择要解决的主要问题是决定哪一个外设作为该数据流的源地址或者目标地址。
每个外设请求都占用一个数据流通道,相同外设请求可以占用不同数据流通道。比如 SPI3_RX 请求,即 SPI3 数据发送请求,占用 DMA1 的数据流 0 的通道 0,因此当我们使用该请求时,我们需要在把
DMA_S0CR 寄存器的 CHSEL[2:0] 设置为“000”
,此时相同数据流的其他通道不被选择,处于不可用状态,比如此时不能使用数据流 0 的通道 1 即 I2C1_RX 请求等等。SPI3_RX 请求不仅仅在数据流 0 的通道 0,同时数据流 2 的通道 0 也是 SPI3_RX 请求,实际上其他外设基本上都有两个对应数据流通道,这两个数据流通道都是可选的,这样设计是尽可能提供多个数据流同时使用情况选择。
2.仲裁器:
一个 DMA 控制器对应 8 个数据流,数据流包含要传输数据的源地址、目标地址、数据等等信息。如果我们需要同时使用同一个 DMA 控制器 (DMA1 或 DMA2) 多个外设请求时,那必然需要同时使用多个数据流,那究竟哪一个数据流具有优先传输的权利呢?这就需要仲裁器来管理判断了。仲裁器管理数据流方法分为两个阶段。第一阶段属于软件阶段,我们在配置数据流时可以通过寄存器设定它的优先级别,具体配置 DMA_SxCR 寄存器 PL[1:0] 位,可以设置为非常高、高、中和低四个级别。第二阶段属于硬件阶段,如果两个或以上数据流软件设置优先级一样,则他们优先级取决于数据流编号,编号越低越具有优先权,比如数据流 2 优先级高于数据流 3。
3.FIFO:
每个数据流都独立拥有四级 32 位 FIFO(先进先出存储器缓冲区)。DMA 传输具有FIFO 模式
和直接模式
。
直接模式
在每个外设请求都立即启动对存储器传输。在直接模式下,如果 DMA 配置为存储器到外设传输那 DMA 会见一个数据存放在 FIFO 内,如果外设启动 DMA 传输请求就可以马上将数据传输过去。FIFO
对于要求源地址和目标地址数据宽度不同时非常有用,比如源数据是源源不断的字节数据,而目标地址要求输出字宽度的数据,即在实现数据传输时同时把原来 4 个 8 位字节的数据拼凑成一个 32 位字数据。此时使用 FIFO 功能先把数据缓存起来,分别根据需要输出数据。FIFO 另外一个作用使用于突发 (burst) 传输。
4.存储器端口
/5.外设端口:
DMA 控制器实现双 AHB 主接口,更好利用总线矩阵和并行传输。DMA 控制器通过存储器端口和外设端口与存储器和外设进行数据传输 。DMA 控制器的功能是快速转移内存数据,需要一个连接至源数据地址的端口和一个连接至目标地址的端口。
DMA2
的存储器端口和外设端口都是连接到 AHB 总线矩阵,可以使用 AHB 总线矩阵功能。DMA2 存储器和外设端口可以访问相关的内存地址,包括有内部 Flash、内部 SRAM、AHB1 外设、AHB2 外设、APB2 外设和外部存储器空间。DMA1
的存储区端口相比 DMA2 的要减少 AHB2 外设的访问权,同时 DMA1 外设端口是没有连接至总线矩阵的,只有连接到 APB1 外设,所以 DMA1 不能实现存储器到存储器传输。
6.编程端口:
AHB 从器件编程端口是连接至 AHB2 外设的。AHB2 外设在使用 DMA 传输时需要相关控制信号。
4.3 DMA 数据配置
DMA 传输模式:
DMA2 支持全部三种传输模式,而 DMA1 只有外设到存储器和存储器到外设两种模式。模式选择可以通过DMA_SxCR 寄存器的 DIR[1:0]
位控制,进而将DMA_SxCR 寄存器的 EN 位置 1 就可以使能 DMA 传输
。在DMA_SxCR 寄存器的 PSIZE[1:0] 和 MSIZE[1:0]
位分别指定外设和存储器数据宽度大小,可以指定为字节 (8 位)、半字 (16 位) 和字 (32 位),我们可以根据实际情况设置。直接模式要求外设和存储器数据宽度大小一样,实际上在这种模式下 DMA 数据流直接使用 PSIZE,MSIZE 不被使用。
源地址和目标地址:
DMA 数据流 x 外设地址DMA_SxPAR(x 为 0~7) 寄存器用来指定外设地址
,它是一个 32 位数据有效寄存器。DMA 数据流 x 存储器 0 地址DMA_SxM0AR(x 为 0~7) 寄存器和 DMA 数据流 x 存储器 1 地址 DMA_SxM1AR(x 为 0~7) 寄存器用来存放存储器地址
,其中DMA_SxM1AR 只用于双缓冲模式
,DMA_SxM0AR 和 DMA_SxM1AR 都是 32 位数据有效的。
外设到存储器传输模式
,即设置 DMA_SxCR 寄存器的 DIR[1:0] 位为“00”,DMA_SxPAR 寄存器为外设地址,也是传输的源地址,DMA_SxM0AR 寄存器为存储器地址,也是传输的目标地址。存储器到外设传输模式
,即设置 DMA_SxCR 寄存器的 DIR[1:0] 位为“01”,DMA_SxM0AR 寄存器作为为源地址,DMA_SxPAR 寄存器作为目标地址。存储器到存储器传输模式
,即设置 DMA_SxCR 寄存器的 DIR[1:0] 位为“10”,采用与外设到存储器模式相同配置。
流控制器:
流控制器主要涉及到一个控制 DMA 传输停止
问题。DMA 传输在DMA_SxCR 寄存器的 EN 位
被置 1 后就进入准备传输状态,如果有外设请求 DMA 传输就可以进行数据传输。很多情况下,我们明确知道传输数据的数目,比如要传 1000 个或者 2000 个数据,这样我们就可以在传输之前设置 DMA_SxNDTR 寄存器为要传输数目值,DMA 控制器在传输完这么多数目数据后就可以控制 DMA 停止传输。
DMA 数据流 x 数据项数DMA_SxNDTR(x 为 0~7) 寄存器
用来记录当前仍需要传输数目,它是一个 16 位数据有效寄存器,即最大值为 65535,这个值在程序设计是非常有用也是需要注意的地方。我们在编程时一般都会明确指定一个传输数量,在完成一次数目传输后 DMA_SxNDTR 计数值就会自减,当达到零时就说明传输完成。
如果某些情况下在传输之前我们无法确定数据的数目,那 DMA 就无法自动控制传输停止了,此时需要外设通过硬件通信向 DMA 控制器发送停止传输信号。这里有一个大前提就是外设必须是可以发出这个停止传输信号,只有 SDIO 才有这个功能,其他外设不具备此功能。
循环模式:
循环模式相对应于一次模式。一次模式就是传输一次就停止传输,下一次传输需要手动控制,而循环模式在传输一次后会自动按照相同配置重新传输,周而复始直至被控制停止或传输发生错误。通过DMA_SxCR 寄存器的 CIRC 位可以使能循环模式
。
传输类型:
DMA 传输类型有单次 (Single) 传输和突发 (Burst) 传输。突发传输就是用非常短时间结合非常高数据信号率传输数据,相对正常传输速度,突发传输就是在传输阶段把速度瞬间提高,实现高速传输,在数据传输完成后恢复正常速度,有点类似达到数据块“秒传”效果。为达到这个效果突发传输过程要占用 AHB 总线,保证要求每个数据项在传输过程不被分割,这样一次性把数据全部传输完才释放 AHB 总线;而单次传输时必须通过 AHB 的总线仲裁多次控制才传输完成。
DMA_SxCR 寄存器中PBURST[1:0] 和 MBURST[1:0] 位,
用于分别设置外设和存储器不同节拍数的突发传输,对应为单次传输、4 个节拍增量传输、8 个节拍增量传输和 16 个节拍增量传输。寄存器 DMA_SxCR 寄存器中 PINC 位(第9位)和 MINC 位(第10位),
如果被置 1 则在每次数据传输后数据地址指针自动递增,其增量由 PSIZE 和 MSIZE 值决定,比如,设置 PSIZE 为半字大小,那么下一次传输地址将是前一次地址递增 2。
突发传输与 FIFO 密切相关,突发传输需要结合 FIFO 使用,具体要求 FIFO 阈值一定要是内存突发传输数据量的整数倍。FIFO 阈值选择和存储器突发大小必须配合使用
直接模式:
默认情况下,DMA 工作在直接模式,不使能 FIFO 阈值级别。直接模式在每个外设请求都立即启动对存储器传输的单次传输。直接模式要求源地址和目标地址的数据宽度必须一致,所以只有 PSIZE 控制,而 MSIZE 值被忽略。突发传输是基于 FIFO 的所以直接模式不被支持。另外直接模式不能用于存储器到存储器传输
。在直接模式下,如果 DMA 配置为存储器到外设传输那 DMA 会见一个数据存放在 FIFO 内,如果外设启动 DMA 传输请求就可以马上将数据传输过去。
双缓冲模式:
设置 DMA_SxCR 寄存器的 DBM 位为 1 可启动双缓冲传输模式,并自动激活循环模式。双缓冲不应用与存储器到存储器的传输。双缓冲模式下,两个存储器地址指针都有效,即 DMA_SxM1AR 寄存器将被激活使用。开始传输使用 DMA_SxM0AR 寄存器的地址指针所对应的存储区,当这个存储区数据传输完 DMA 控制器会自动切换至 DMA_SxM1AR 寄存器的地址指针所对应的另一块存储区,如果这一块也传输完成就再切换至 DMA_SxM0AR 寄存器的地址指针所对应的存储区,这样循环调用。
当其中一个存储区传输完成时会把传输完成中断标志 TCIF 位置 1,如果我们使能了 DMA_SxCR 寄存器的传输完成中断,则可以产生中断信号,这个对我们编程非常有用。另外一个非常有用的信息是 DMA_SxCR 寄存器的 CT 位,当 DMA 控制器是在访问使用 DMA_SxM0AR 时 CT=0,此时 CPU 不能访问 DMA_SxM0AR,但可以向 DMA_SxM1AR 填充或者读取数据;当 DMA 控制器是在访问使用 DMA_SxM1AR 时 CT=1,此时 CPU 不能访问 DMA_SxM1AR,但可以向 DMA_SxM0AR 填充或者读取数据。另外在未使能 DMA 数据流传输时,可以直接写 CT 位,改变开始传输的目标存储区。
双缓冲模式应用在需要解码程序的地方是非常有效的。比如 MP3 格式音频解码播放,MP3 是被压缩的文件格式,我们需要特定的解码库程序来解码文件才能得到可以播放的 PCM 信号,解码需要一定的时间,按照常规方法是读取一段原始数据到缓冲区,然后对缓冲区内容进行解码,解码后才输出到音频播放电路,这种流程对 CPU 运算速度要求高,很容易出现播放不流畅现象。如果我们使用 DMA 双缓冲模式传输数据就可以非常好的解决这个问题,达到解码和输出音频数据到音频电路同步进行的效果。
4.4 DMA 中断
每个 DMA 数据流可以在发送以下事件时产生中断:
达到半传输:
DMA 数据传输达到一半时 HTIF 标志位被置 1,如果使能 HTIE 中断控制位将产生达到半传输中断;传输完成:
DMA 数据传输完成时 TCIF 标志位被置 1,如果使能 TCIE 中断控制位将产生传输完成中断;传输错误:
DMA 访问总线发生错误或者在双缓冲模式下试图访问“受限”存储器地址寄存器时 TEIF 标志位被置 1,如果使能 TEIE 中断控制位将产生传输错误中断;FIFO 错误:
发生 FIFO 下溢或者上溢时 FEIF 标志位被置 1,如果使能 FEIE 中断控制位将产生 FIFO 错误中断;直接模式错误:
在外设到存储器的直接模式下,因为存储器总线没得到授权,使得先前数据没有完成被传输到存储器空间上,此时 DMEIF 标志位被置 1,如果使能 DMEIE 中断控制位将产生直接模式错误中断。