寄存器
DMA_ISR
- DMA 中断状态寄存器( DMA interrupt status register )
- TEIFx:通道x的传输错误标志
- HTIFx:通道x的半传输标志
- TCIFx:通道x的传输完成标志
- GIFx: 通道x的全局中断标志 (TE、HT或TC事件)
DMA_IFCR
- DMA中断标志清除寄存器(DMA interrupt flag clear register)
- CTEIFx:清除通道x的传输错误标志
- CHTIFx:清除通道x的半传输标志
- CTCIFx:清除通道x的传输完成标志
- CGIFx: 清除通道x的全局中断标志
DMA_CCRx
- DMA通道x配置寄存器(DMA channel x configuration register)
- MEM2MEM:存储器到存储器模式 (Memory to memory mode)
- PL[1:0]:通道优先级 (Channel priority level)
- MSIZE[1:0]:存储器数据宽度 (Memory size)
- PSIZE[1:0]:外设数据宽度 (Peripheral size)
- MINC:存储器地址增量模式 (Memory increment mode)
- PINC:外设地址增量模式 (Peripheral increment mode)
- CIRC:循环模式 (Circular mode)
- DIR:数据传输方向 (Data transfer direction)
- TEIE:允许传输错误中断 (Transfer error interrupt enable)
- HTIE:允许半传输中断 (Half transfer interrupt enable)
- TCIE:允许传输完成中断 (Transfer complete interrupt enable)
- EN:通道开启 (Channel enable)
DMA_CNDTRx
- DMA通道x传输数量寄存器(DMA channel x number of data register)
- NDT[15:0]:数据传输数量 (Number of data to transfer)
数据传输数量为0至65535。这个寄存器只能在通道不工作(DMA_CCRx的EN=0)时写入。通道开启后该寄存器变为只读,指示剩余的待传输字节数目。寄存器内容在每次DMA传输后递减。
数据传输结束后,寄存器的内容或者变为0;或者当该通道配置为自动重加载模式时,寄存器的内容将被自动重新加载为之前配置时的数值。
当寄存器的内容为0时,无论通道是否开启,都不会发生任何数据传输。
DMA_CPARx
- DMA通道x外设地址寄存器(DMA channel x peripheral address register)
DMA_CMARx
- DMA通道x存储器地址寄存器(DMA channel x memory address register)
DMA_InitTypeDef 结构体
typedef struct
{
uint32_t DMA_PeripheralBaseAddr; // 外设地址
uint32_t DMA_MemoryBaseAddr; // 存储器地址
uint32_t DMA_DIR; // 传输方向
uint32_t DMA_BufferSize; // 传输数目
uint32_t DMA_PeripheralInc; // 外设地址增量模式
uint32_t DMA_MemoryInc; // 存储器地址增量模式
uint32_t DMA_PeripheralDataSize; // 外设数据宽度
uint32_t DMA_MemoryDataSize; // 存储器数据宽度
uint32_t DMA_Mode; // 模式选择
uint32_t DMA_Priority; // 通道优先级
uint32_t DMA_M2M; // 存储器到存储器模式
}DMA_InitTypeDef;
typedef struct
{
__IO uint32_t CCR;
__IO uint32_t CNDTR;
__IO uint32_t CPAR;
__IO uint32_t CMAR;
} DMA_Channel_TypeDef;
例程
外设到存储器
uint8_t ReceiveBuff[100];
void USART1_DMA_Config(void){
RCC->APB2ENR |= (uint32_t)0x05; // 使能GPIOA/AFIO时钟
GPIOA->CRH |= (uint32_t)0x0B << 4; // 配置PA9复用推挽输出,最高50MHZ
GPIOA->CRH |= (uint32_t)0x04 << 8; // 配置PA10浮空输入
RCC->APB2ENR |= (uint32_t)0x01 << 14; // 使能USART1时钟
USART1->CR1 |= (uint16_t)0x00 << 12; // 一个起始位,8个数据位
USART1->CR2 |= (uint16_t)0x00 << 12; // 一个停止位
USART1->CR3 |= (uint16_t)0x00 << 8; // 禁用CTS,RTS硬件流控制
USART1->CR3 |= (uint16_t)0x0040; // 使能USART1 DMA接收
USART1->BRR = (uint16_t)0x1D4C; // 波特率9600
USART1->CR1 |= (uint16_t)0x0B; // 收/发使能
NVIC->ISER[1] |= (uint32_t)0x01 << (37-32); // 使能USART1中断,中断号是37
NVIC->IP[9] |= (uint32_t)0x40; // 配置优先级主1子1
USART1->CR1 |= (uint16_t)0x01 << 0; // 使能USART1
RCC->APB2ENR |= (uint32_t)0x01 << 0; // 使能DMA1时钟
DMA1_Channel5->CPAR = USART1_BASE + 0x04; // 外设地址
DMA1_Channel5->CMAR = (uint32_t)ReceiveBuff;// 存储器地址
DMA1_Channel5->CCNDTR |= (uint16_t)0x1388; // 数据传输数量
DMA1_Channel5->CCR |= (uint32_t)0x00 << 14; // 禁止存储器到存储器
DMA1_Channel5->CCR |= (uint32_t)0x01 << 12; // 优先级:中
DMA1_Channel5->CCR |= (uint32_t)0x00 << 10; // 存储器数据宽度8位
DMA1_Channel5->CCR |= (uint32_t)0x00 << 8; // 外设数据宽度8位
DMA1_Channel5->CCR |= (uint32_t)0x01 << 7; // 存储器地址自增
DMA1_Channel5->CCR |= (uint32_t)0x00 << 6; // 外设地址不自增
DMA1_Channel5->CCR |= (uint32_t)0x01 << 5; // 循环模式
DMA1_Channel5->CCR |= (uint32_t)0x00 << 4; // 从外设读
DMA1_Channel5->CCR |= (uint32_t)0x00 << 3; // 禁止传输错误中断
DMA1_Channel5->CCR |= (uint32_t)0x00 << 2; // 禁止半传输中断
DMA1_Channel5->CCR |= (uint32_t)0x00 << 1; // 禁止传输完成中断
DMA1_Channel5->CCR |= (uint32_t)0x01 << 0; // 开启该DMA通道
//NVIC->ISER[0] |= (uint32_t)0x01 << 15; // 使能DMA1_Channel5中断,中断号是15
//NVIC->IP[3] |= (uint32_t)0x40 << 23; // 配置优先级主1子1
}
void USART1_IRQHandler(void){
uint8_t ucTemp;
if(USART1->SR & (uint16_t)0x10){ // IDLE总线空闲标志
DMA1_Channel5->CCR &= ~((uint32_t)0x01 << 0); // 关闭该DMA通道
ucTemp = (uint8_t)(USARTx->DR & (uint16_t)0x01FF); // 读取一次数据,清除IDLE
DMA1_Channel5->CCR |= (uint32_t)0x01 << 0; // 开启该DMA通道
}
}
void DMA1_Channel5_IRQHandler(void){
}