1.学会操作 F5438 的 DMA 模块操作,了解 DMA 寄存器的组成
2.掌握 DMA 传输原理和三种传输模式传输过程
3.编程实现利用 DMA 以字节模式将字符串传到上位机
4. 功能:利用 DMA 将数据以 1S 一次的速度传送到发送缓冲器中进行发送
5.现象:在上位机上看到 hello world!输出
1,DMA介绍
2,DMA的特性
3,DMA控制器结构框图
4,DMA寻址方式
5,DMA传输方式
DMA有六种传输模式:单字或者单字节传输;块传输;突发块传输;重复单字或者单字节传输;重复块传输;重复突发块传输。前三个,传输完成后DMAEN自动复位;再次传输时需要重新置位DMAEN位以使能DMA通道。后三个为重复模式,一次传输完成后,DMAEN不复位;再次出发时,可以再次启动数据传输。
六种传输模式通过DMADTx寄存器设置。每个通道都可以独立的配置其传输模式。例如,通道 0 可以配置为单次传输模式,而通道 1 可以配置为突发块传输模式,通道 2 配置为重复块传输模式。传输模式的配置和寻址方式是独立的任何寻址方式都可以使用每种传输模式。
6,实验原理
DMA 是实现将数据从外设或者一个存储区域传到另一个存储区域或者提供给外设备功能。在 DMA 传送数据的过程中是不需要 CPU 干涉,DMA 每传输一个字节或者字需要两个 MCLK 时钟,传输模式如上表所示。
单次模式
当 DMADTX 为 000 的时候进行字节/字传输,每传递一个字节/字都需要一次触发,当 DMASZ为 0 后 DMAEN 自动清除。如果需要重新开始传输需要另外将 DMAEN 置 1。
当 DMADTX 为 100 的时候进行重复单次传输,即每次传输一个字节/字都需要触发一次,但是当 DMASZ 为 0 后,DMAEN 仍然置位。
块传输模式
当 DMADTX 为 001 时候进行块传输,只需要触发一次就可以传输一个块数据,当传输完一个块数据后,DMAEN 自动清除。
当 DMADTX 为 101 时候进行重复块传输,只需要触发一次就可以传输一个块数据,当传输完一个块数据后,DMAEN 仍然置位。
突发块模式
当 DMADTX 为 010 011 的时候进行突发块传输,触发一次可以传输一块数据,在传输过程中每传输四个字节/字,就提供两个时钟给 CPU,CPU 在这里利用率 20%,当 DMASZ 为 0 后 DMAEN自动清除。如果需要重新开始传输需要另外将 DMAEN 置 1。
当 DMADTX 为 110 111 的时候进行重复突发块传输,触发一次可以传输一块数据,在传输过程中每传输四个字节/字,就提供两个时钟给 CPU,CPU 在这里利用率 20%,当 DMASZ 为 0 后DMAEN 仍然置 1。
单次传输,块传输,突发块传输原理差不多 ,以块传输为例。在传输前系统分配三个临时的寄存器,T-SA T-SZ T-DA ,DMASA,DMASZ,DMADA 数值分别赋给对应寄存器,在传输过程中,T-SA DMASZ T-DA 分别进行加/减/不变,当DMASZ为0 后,DMAIFG置位,DMASA,DMADA,T-SZ ,分别赋数值给 T-SA,、T-DA,DMASZ。
7,寄存器设置
DMAxCTL 是对通道配置非常重要的一个寄存器,DMADTX 用来选择传输模式,DMADSTINCRx用来设置目的地址是增,减还是不变。DMASRCINCRX 是用来设置源地址是增,减还是不变。DMADSTBYTE 用来选择每次传输占用目的地址一个字节还是一个字,DMASRCBYTE 用来选择每次传输源地址一个字节还是一个字。
通过设置对应通道的 DMAx TSELx 来选择对应通道的触发源。
每个通道的触发源有DMAxTSELx位进行控制的,这些位必须在DMAEN位为0是进行设置,否则可能出现不可预料的DMA触发。
例如:配置 UTXIFG1 高电平触发,单次传输,每次传输一个字节,将字节数据从数组 String传给发送缓冲器。
DMACTL0 = DMA0TSEL_21; // UTXIFG1 触发
DMA0SA = (int)String1; // 源地址
DMA0DA = UCA1TXBUF_; // 目的地址
DMA0SZ = 15; // 传输大小
DMA0CTL = DMASRCINCR_3 + DMASBDB + DMALEVEL ; // 单字节传输
8,程序流程
9,实验代码
/*************************************************
** 功能: 利用 DMA 将数据以 1S 一次的速度传送到发送缓冲器中进行发送
// | P5.6|- tx ---9600----UART
// | P5.7|- rx --------------
*************************************************************/
#include "msp430x54x.h"
//***********************************************************
const unsigned char String1[60] ="n www.ippipp.com ";
void main(void)
{
WDTCTL = WDT_ADLY_1000; // 看门狗定时 1 秒
P5SEL |= BIT6 + BIT7; // 作为串口输入输出端口
P5DIR |= BIT6;
P5DIR &= ~BIT7;
UCA1CTL1 = UCSWRST;
UCA1CTL0 = UCMODE_0; // 选择 UART 模式
UCA1CTL0 &= ~UC7BIT; // 8bit 字节传输
UCA1CTL1 |= UCSSEL_1; // 选择 ACLK 作为时钟
UCA1BR0 = 0X03; // 32kHz/9600=3.41
UCA1BR1 = 0;
UCA1MCTL = 0x04A;
UCA1CTL1 &= ~UCSWRST;
DMACTL0 = DMA0TSEL_21; // UTXIFG1 触发
DMA0SA = (int)String1; // 源地址
DMA0DA = UCA1TXBUF_; // 目的地址
DMA0SZ = 20; // 传输大小
DMA0CTL = DMASRCINCR_3 + DMASBDB + DMALEVEL ; // 单字节传输
SFRIE1 |= WDTIE;
__bis_SR_register(LPM3_bits + GIE); //进入低功耗模式
}
#pragma vector = WDT_VECTOR // 触发数据传输
__interrupt void WDT_ISR(void)
{
DMA0CTL |= DMAEN; //DMA 模块工作
}
10,实验现象
串口助手显示:www.ippipp.com
注意
在利用串口发送缓冲器中断标志启动触发数据传送时候要注意发送缓冲器中断标志在复位后是空闲状态即中断标志为 1,如果采用边沿触发方式,那么无法完成 DMA 触发。因此要采用电平触发。