DMA简介
cubeMX配置
-
DMA_Request
:外设的通道 -
Channel
:一般通道都为默认的 -
Direction
:传输方向- Peripheral To Memory:外设到内存
- Memory To Peripheral:内存到外设
- Memory To Memory:内存到内存
-
Priority
:DMA优先级- Low:低
- Medium:中
- High:高
当发生多个 DMA 通道请求时,就意味着有先后响应处理的顺序问题,这个就由仲裁器也管理。仲裁器管理 DMA 通道请求分为两个阶段。第一阶段属于软件阶段,可以在 DMA_CCRx 寄存器中设置,有 4 个等级:非常高、高、中和低四个优先级。第二阶段属于硬件阶段,如果两个或以上的 DMA 通道请求设置的优先级一样,则他们优先级取决于通 道编号,编号越低优先权越高,比如通道 0 高于通道 1。
-
Mode
:- Normal:表示单次传输,传输一次后终止传输,配置并产生中断。
- Circular:表示循环传输,传输完成后又重新开始继续传输。
-
Increment Address
:- Peripheral:表示外设地址自增。
- Memory:表示内存地址自增。
串口发送数据是将数据不断存进串口的发送数据寄存器(USARTx_TDR)。所以外接的地址是不递增。而内存储器存储的是要发送的数据,所以地址指针要递增才能将所以的数据发送出去。
-
Data Width
:- Byte:一个字节。
- Half Word:半字,两字节。
- Word:一个字,四字节。
DAM中断一般都被强制使能了,也可以通过Force DMA channels Interrupts
来取消。
keil使用流程
在响应的外设中找到DMA模式,调用相关函数即可。
HAL库
Handler
typedef struct __DMA_HandleTypeDef
{
DMA_Channel_TypeDef *Instance; /*!< Register base address */
DMA_InitTypeDef Init; /*!< DMA communication parameters */
HAL_LockTypeDef Lock; /*!< DMA locking object */
__IO HAL_DMA_StateTypeDef State; /*!< DMA transfer state */
void *Parent; /*!< Parent object state */
void (* XferCpltCallback)( struct __DMA_HandleTypeDef * hdma); /*!< DMA transfer complete callback */
void (* XferHalfCpltCallback)( struct __DMA_HandleTypeDef * hdma); /*!< DMA Half transfer complete callback */
void (* XferErrorCallback)( struct __DMA_HandleTypeDef * hdma); /*!< DMA transfer error callback */
void (* XferAbortCallback)( struct __DMA_HandleTypeDef * hdma); /*!< DMA transfer abort callback */
__IO uint32_t ErrorCode; /*!< DMA Error code */
DMA_TypeDef *DmaBaseAddress; /*!< DMA Channel Base Address */
uint32_t ChannelIndex; /*!< DMA Channel Index */
} DMA_HandleTypeDef;
StateTypeDef
typedef enum
{
HAL_DMA_STATE_RESET = 0x00U, /*!< DMA not yet initialized or disabled */
HAL_DMA_STATE_READY = 0x01U, /*!< DMA initialized and ready for use */
HAL_DMA_STATE_BUSY = 0x02U, /*!< DMA process is ongoing */
HAL_DMA_STATE_TIMEOUT = 0x03U /*!< DMA timeout state */
}HAL_DMA_StateTypeDef;
DMA状态控制函数
// 使能DMA非中断模式
HAL_StatusTypeDef HAL_DMA_Start (DMA_HandleTypeDef *hdma, uint32_t SrcAddress, uint32_t DstAddress, uint32_t DataLength);
// 终止DMA
HAL_StatusTypeDef HAL_DMA_Abort(DMA_HandleTypeDef *hdma);
// 等待DMA传输完成
HAL_StatusTypeDef HAL_DMA_PollForTransfer(DMA_HandleTypeDef *hdma, uint32_t CompleteLevel, uint32_t Timeout);
// 获取DMA状态
HAL_DMA_StateTypeDef HAL_DMA_GetState(DMA_HandleTypeDef *hdma);
// 获取DMA错误
uint32_t HAL_DMA_GetError(DMA_HandleTypeDef *hdma);
// 使能DMA(非中断模式)
#define __HAL_DMA_ENABLE(__HANDLE__)
// 失能DMA
#define __HAL_DMA_DISABLE(__HANDLE__)
// 获取DMA的传输计数器
#define __HAL_DMA_GET_COUNTER(__HANDLE__) ((__HANDLE__)->Instance->CNDTR)
DMA中断控制函数
// 使能DMA中断模式
HAL_StatusTypeDef HAL_DMA_Start_IT(DMA_HandleTypeDef *hdma, uint32_t SrcAddress, uint32_t DstAddress, uint32_t DataLength);
// 终止中断模式的DMA
HAL_StatusTypeDef HAL_DMA_Abort_IT(DMA_HandleTypeDef *hdma);
// 使能DMA中断
// 三种DMA中断(DMA_IT_TC传完 / DMA_IT_HT传一半 / DMA_IT_TE出错)
#define __HAL_DMA_ENABLE_IT(__HANDLE__, __INTERRUPT__)
// 失能DMA中断
#define __HAL_DMA_DISABLE_IT(__HANDLE__, __INTERRUPT__)
// 获取中断使能状态
#define __HAL_DMA_GET_IT_SOURCE(__HANDLE__, __INTERRUPT__)
DMA回调函数
必须将回调函数注册到handler里,当中断发生时由HAL_DMA_IRQHandler()
函数调用
// DMA传输完成
void TransferCpltCallback( struct __DMA_HandleTypeDef * hdma);
// DMA传输一半
void TransferHalfCpltCallback( struct __DMA_HandleTypeDef * hdma);
// 传输错误
void TransferErrorCallback( struct __DMA_HandleTypeDef * hdma);
// 传输停止
void TransferAbortCallback( struct __DMA_HandleTypeDef * hdma);
------ BY Flier
2023.10.17