【STM32】Initial use of DMA

Introduction to DMA

DMA (Direct Memory Access) is a peripheral of the microcontroller. Its main function
is to move data, but it does not need to occupy the CPU. That is, the CPU can do other things while transmitting data.

Taking the STM32F103 microcontroller as an example,
F03 has two sets of DMAs, DMA1 and DMA2, of which DMA1 has 7 channels and DMA2 has 5 channels.

DMA request

If a peripheral needs to use DMA, it must send a DMA request to the DMA. After the DMA receives the request signal, the controller will give the peripheral a response signal. When the peripheral responds and the DMA controller receives the response signal, the DMA will be started. of transmission until the transmission is completed.

DMA has two controllers, DMA1 and DMA2. DMA1 has 7 channels and DMA2 has 5 channels. The channels of different DMA controllers correspond to different peripheral requests, which determines how we set up the software programming. Specifically See DMA request mapping table.

DMA1 request image for each channel
DMA1 request image for each channel

DMA2 request image for each channel
Insert image description here

aisle

DMA has 12 independently programmable channels, of which DMA1 has 7 channels and DMA2 has 5 channels. Each channel
corresponds to DMA requests of different peripherals. Although each channel can receive requests from multiple peripherals, it
can only receive one at the same time and cannot receive multiple at the same time.

arbiter, priority

When multiple DMA channel requests occur, it means there is a sequence problem of response processing, which is managed by the arbiter. The arbiter manages DMA channel requests in two phases. The first stage belongs to the software stage and can be set in the DMA_CCRx register. It has 4 levels: very high, high, medium and low priority.
The second phase belongs to the hardware phase. If two or more DMA channel requests have the same priority setting, their priority depends on the channel number. The lower the number, the higher the priority. For example, channel 0 is higher than channel 1. In high-capacity products and interconnected products, the DMA1 controller has a higher priority than the DMA2 controller.

A few key points of DMA

There are three directions for DMA to transmit data: 从外设到存储器, 从存储器到外设, 从存储器到存储器. Specific direction DMA_CCR configuration, the peripheral address involved is configured by DMA_CPAR, and the memory address is configured by DMA_CMAR.

Transmission direction

Peripheral to memory

When we use peripheral to memory transfer, to ADC 采集为例. The address of the DMA peripheral register corresponds to the address of the ADC data register DR, and the address of the DMA memory is the address of our custom variable (used to receive and store the data collected by AD). Direction we set the peripheral as the source address.

memory to peripheral

When we use transfer from memory to peripheral, take for 串口向电脑端发送数据example. The address of the DMA peripheral register corresponds to the address of the serial port data register DR. The address of the DMA memory is the address of our custom variable (equivalent to a buffer used to store data sent to the computer through the serial port). Direction We set the peripheral to the target address.

memory to memory

When we use memory-to-memory transfer, 以内部 FLASH 向内部 SRAM 复制数据为例. The address of the DMA peripheral register corresponds to the address of the internal FLASH (we regard the internal FALSH as a peripheral here), and the address of the DMA memory is our custom variable (equivalent to a buffer, used to store data from the internal FLASH data) address. In the direction we set the peripheral (i.e. internal FLASH) as the source address. Different from the above two, here you need to configure DMA_CCR bit 14: MEM2MEM: memory to memory mode to 1 to enable M2M mode.
Insert image description here

The transmission length unit address is added automatically.

Transmission length

Take the serial port sending data to the computer as an example. The source address is the on-chip flash and the destination address is USART->DR. A lot of data can be sent to the computer at one time. The specific amount is configured by DMA_CNDTR. This is a 32-bit register. At most, it can be sent to the computer at one time. 65535 pieces of data were transferred.

The destination and source transfer lengths remain the same

For correct data transmission, the data width stored in the source and destination addresses must be consistent. The serial port data register is 8 bits, so the data we define to be sent must also be 8 bits. The data width of the peripheral is configured by PSIZE[1:0] of DMA_CCRx, which can be 8/16/32 bits. The data width of the memory is configured by MSIZE[1:0] of DMA_CCRx, which can be 8/16/32 bits.

address auto-increment

Under the control of the DMA controller, if data wants to be moved from one place to another in an orderly manner, the increment mode of the data pointers on both sides must be correctly set.

Under the control of the DMA controller, if data wants to be moved from one place to another in an orderly manner, the increment mode of the data pointers on both sides must be correctly set. The address pointer of the peripheral is configured by PINC of DMA_CCRx, and the address pointer of the memory is configured by MINC.

Take the serial port sending data to the computer as an example. There is a lot of data to be sent. After each data is sent, the address pointer of the memory should be increased by 1. However, there is only one serial port data register, so the address pointer of the peripheral device is fixed. The specific increment mode of the data pointer is determined by the actual situation .

Transmission completed, circular transmission

When the data transmission is completed, we can identify it by 查询标志位or 通过中断的方式. Each DMA channel will have corresponding flag bits in DMA 传输过半, 传输完成and . If this type of interrupt is enabled, an interrupt will be generated. 传输错误For detailed description of each flag bit, please refer to the detailed description of DMA interrupt status register DMA_ISR.
There are two modes of transmission completion, one-time transmission or cyclic transmission. One-time transmission is easy to understand, that is, it stops after transmitting once. If you want to transmit again, you must turn off DMA and enable it and then reconfigure it before you can continue to transmit. Cyclic transmission means that after one transmission is completed, the configuration cyclic transmission during the first transmission is restored, and it is repeated continuously. Specifically controlled by the CIRC cycle mode bit of the DMA_CCRx register.

DMA firmware library

Link: DMA firmware library function

DMA configuration process

Main points

1) Enable DMA clock;

2) Configure DMA data parameters;

3) Enable DMA and perform transmission;

4) Wait for the transfer to complete and compare the source data and destination address data.

#DMA配置
void DMA_Config(void)
{
    
    
	DMA_InitTypeDef DMA_InitStructure;
	// 开启 DMA 时钟
	RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);
	// 源数据地址 aSRC_Const_Buffer是使用const定义在内部flash上的一块数组
	DMA_InitStructure.DMA_PeripheralBaseAddr =(uint32_t)aSRC_Const_Buffer;
	 // 目标地址,例:如果是通过串口发送数据那么目标地址可以设置为USART1->DR
	 DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)aDST_Buffer;
	 
	 // 方向:外设到存储器(这里的外设是内部的 FLASH),方向都是相对的,要看目标和源怎么设置了
	 DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;
	 
	 // 传输大小
	 DMA_InitStructure.DMA_BufferSize = BUFFER_SIZE;
	 
	 // 外设,前文设置的外设地址(内部的 FLASH)地址递增
	 DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Enable;
	 
	 // 内存地址递增
	 DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
	 
	 // 外设数据单位
	 DMA_InitStructure.DMA_PeripheralDataSize =DMA_PeripheralDataSize_Word;
	 
	 // 内存数据单位
	 DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Word;
	 
	 // DMA 模式,一次或者循环模式
	 DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;
	 //DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;
	 
	 // 优先级:高
	 DMA_InitStructure.DMA_Priority = DMA_Priority_High;
	 
	 // 使能内存到内存的传输
	 DMA_InitStructure.DMA_M2M = DMA_M2M_Enable;
	 
	 // 配置 DMA 通道
	 DMA_Init(DMA1_Channel6, &DMA_InitStructure);
	 
	 // 使能 DMA
	 DMA_Cmd(DMA1_Channel6, ENABLE);
}

Guess you like

Origin blog.csdn.net/apythonlearner/article/details/132455724