串口dma
8 个可独立配置的 DMA 通道。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-VchCudlf-1689952378831)(./picture/dma.png)]
实例代码
串口dma使用的是串口绑定方式实现串口的dma数据传输
bsp_uart_dma.h
#ifndef _BSP_UART_DMA_H_
#define _BSP_UART_DMA_H_
#include<stdio.h>
#include<stdint.h>
#include "n32l40x.h"
#define BUFF_SIZE 48
//调试串口指定
#define DEBUG_UART USART1
//dma接收数据和中断接收数据不可以同时使用
typedef enum
{
UART1_DMA_RECV,//串口1接收
UART1_DMA_SEND,//串口1发送
UART2_DMA_RECV,//串口2接收
UART3_DMA_RECV,//串口3接收
UART_DMA_NUM,
}em_uart_dma_t;
typedef struct
{
DMA_ChannelType* dma_ch_rx;//dma 发送通道
uint32_t dma_remap_rx;//串口接收映射的dma通道
uint16_t dma_irq_rx;//dma rx 中断编号
uint32_t send_or_recv;//发送还是接收
} uart_dma_t;
/*
一键初始化所有串口
*/
void bsp_uart_dma_config(uart_dma_t *puartx,uint32_t reg_data,const uint32_t *buff,const uint16_t len);
uart_dma_t* bsp_uart_dma_get_handler(em_uart_dma_t id);
void bsp_uart_dma_send_ex(uart_dma_t *puartx,uint8_t *data,uint16_t len);
#endif
bsp_uart_dma.c
#include <stdio.h>
#include <math.h>
#include <string.h>
#include "bsp_include.h"
#include "uart/bsp_uart_dma.h"
//这里的通道和外设随便映射,没得固定的映射关系
static uart_dma_t s_uart_dma_s[UART_DMA_NUM]= {
//UART1
{ DMA_CH4,DMA_REMAP_USART1_RX,DMA_Channel4_IRQn,DMA_DIR_PERIPH_SRC},
{ DMA_CH5,DMA_REMAP_USART1_TX,DMA_Channel5_IRQn,DMA_DIR_PERIPH_DST},
//UART2
{ DMA_CH2,DMA_REMAP_USART2_RX,DMA_Channel2_IRQn,DMA_DIR_PERIPH_SRC},
//UART3
{ DMA_CH3,DMA_REMAP_USART3_RX,DMA_Channel3_IRQn,DMA_DIR_PERIPH_SRC},
};
uart_dma_t* bsp_uart_dma_get_handler(em_uart_dma_t id)
{
if(UART_DMA_NUM>id)
return s_uart_dma_s+id;
else
return 0;
}
void bsp_uart_dma_nvic_config(uart_dma_t *puartx)
{
NVIC_InitType NVIC_InitStructure;
NVIC_InitStructure.NVIC_IRQChannel = puartx->dma_irq_rx;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
}
void bsp_uart_dma_config(uart_dma_t *puartx,uint32_t reg_data,const uint32_t *buff,const uint16_t len)
{
DMA_InitType DMA_InitStructure;
// USARTy_Tx_DMA_Channel (triggered by USARTy Tx event) Config
//使能时钟
RCC_EnableAHBPeriphClk(RCC_AHB_PERIPH_DMA, ENABLE);
DMA_StructInit(&DMA_InitStructure);
DMA_DeInit(puartx->dma_ch_rx);
DMA_InitStructure.PeriphAddr = reg_data;
DMA_InitStructure.MemAddr = buff;
DMA_InitStructure.Direction = puartx->send_or_recv;//外设是源数据
if(DMA_DIR_PERIPH_DST==puartx->send_or_recv)//发送模式就是默认发送数量为0
{
DMA_InitStructure.BufSize = 0;
}
else
{
DMA_InitStructure.BufSize = len;
}
DMA_InitStructure.PeriphInc = DMA_PERIPH_INC_DISABLE;//外设地址自动增加关闭
DMA_InitStructure.DMA_MemoryInc = DMA_MEM_INC_ENABLE; //内存地址自动增加
DMA_InitStructure.PeriphDataSize = DMA_PERIPH_DATA_SIZE_BYTE;//数据宽度
DMA_InitStructure.MemDataSize = DMA_MemoryDataSize_Byte;//数据宽度
DMA_InitStructure.CircularMode = DMA_MODE_NORMAL;//工作模式-普通模式
DMA_InitStructure.Priority = DMA_PRIORITY_MEDIUM;//中等优先级
DMA_InitStructure.Mem2Mem = DMA_M2M_DISABLE;//不是内存到内存的传输方式
DMA_Init(puartx->dma_ch_rx, &DMA_InitStructure);
//dma 通道映射
DMA_RequestRemap(puartx->dma_remap_rx, DMA, puartx->dma_ch_rx, ENABLE);
//中断分组
bsp_uart_dma_nvic_config(puartx);
//使能dma中断
DMA_ConfigInt(puartx->dma_ch_rx,DMA_INT_TXC,ENABLE);
//通道使能
DMA_EnableChannel(puartx->dma_ch_rx, ENABLE);
}
void bsp_uart_dma_send_ex(uart_dma_t *puartx,uint8_t *data,uint16_t len)
{
//通道使能
DMA_EnableChannel(puartx->dma_ch_rx, DISABLE);
DMA_SetCurrDataCounter(puartx->dma_ch_rx,len);
//通道使能
DMA_EnableChannel(puartx->dma_ch_rx, ENABLE);
}
/**
DMA_Channel1_IRQHandler
DMA_Channel2_IRQHandler
DMA_Channel3_IRQHandler
DMA_Channel4_IRQHandler
DMA_Channel5_IRQHandler
DMA_Channel6_IRQHandler
DMA_Channel7_IRQHandler
DMA_Channel8_IRQHandler
*/
void bsp_uart_dam_irq_handler(uint32_t DMA_IT)
{
//DMA_INT_HTX1 这个是个变量
if( DMA_GetIntStatus(DMA_IT, DMA))
{
DMA_ClrIntPendingBit(DMA_IT, DMA);
}
}
//发送/接收 dma
void DMA_Channel4_IRQHandler(void)
{
bsp_uart_dam_irq_handler(DMA_INT_TXC4);
}
//发送/接收 dma
void DMA_Channel5_IRQHandler(void)
{
bsp_uart_dam_irq_handler(DMA_INT_TXC5);
}