STM32:DMA
1 DMA
DMA全称direct memory access,直接 内存 存取 外设;
作用:提供外设与存储器、存储器与存储器之间的高速数据传输;
特点:不占用CPU资源,能够大量高速处理数据提高效率;
flash(代码运行区),SRAM,AHB,APB1,APB2外设均可作为访问的源或目标;
DMA外设和cortex-M3核心共享D-code总线矩阵,所以DMA才哪哪都可以访问(还没哪里是D-code总线到不了的);
2 DMA寄存器
HFIF、CHTIF、HTIE这三个标志位有点离谱,到底是什么离谱的协议需要判断是否传输到一半然后停下来呢?埋个小雷期待一下;
2.1 DMA外设的通道选择
当dma传输数据[mem2men]使能的话,数据从内存传输到内存,每个通道都可以使用;
默认dma1的优先级高于dma2的优先级,channel_1的优先级高于channel_2的优先级;也可以在PL[13:12]中设置通道优先级;
3 DMA代码
3.1 寄存器封装
stm32f10x.h
typedef struct { __IO uint32_t CCR; __IO uint32_t CNDTR; __IO uint32_t CPAR; __IO uint32_t CMAR; } DMA_Channel_TypeDef; typedef struct { __IO uint32_t ISR; __IO uint32_t IFCR; } DMA_TypeDef; #define DMA1_BASE (AHBPERIPH_BASE + 0x0000) #define DMA1_Channel1_BASE (AHBPERIPH_BASE + 0x0008) #define DMA1_Channel2_BASE (AHBPERIPH_BASE + 0x001C) #define DMA1_Channel3_BASE (AHBPERIPH_BASE + 0x0030) #define DMA1_Channel4_BASE (AHBPERIPH_BASE + 0x0044) #define DMA1_Channel5_BASE (AHBPERIPH_BASE + 0x0058) #define DMA1_Channel6_BASE (AHBPERIPH_BASE + 0x006C) #define DMA1_Channel7_BASE (AHBPERIPH_BASE + 0x0080) #define DMA2_BASE (AHBPERIPH_BASE + 0x0400) #define DMA2_Channel1_BASE (AHBPERIPH_BASE + 0x0408) #define DMA2_Channel2_BASE (AHBPERIPH_BASE + 0x041C) #define DMA2_Channel3_BASE (AHBPERIPH_BASE + 0x0430) #define DMA2_Channel4_BASE (AHBPERIPH_BASE + 0x0444) #define DMA2_Channel5_BASE (AHBPERIPH_BASE + 0x0458) #define DMA1 ((DMA_TypeDef *) DMA1_BASE) #define DMA2 ((DMA_TypeDef *) DMA2_BASE) #define DMA1_Channel1 ((DMA_Channel_TypeDef *) DMA1_Channel1_BASE) #define DMA1_Channel2 ((DMA_Channel_TypeDef *) DMA1_Channel2_BASE) #define DMA1_Channel3 ((DMA_Channel_TypeDef *) DMA1_Channel3_BASE) #define DMA1_Channel4 ((DMA_Channel_TypeDef *) DMA1_Channel4_BASE) #define DMA1_Channel5 ((DMA_Channel_TypeDef *) DMA1_Channel5_BASE) #define DMA1_Channel6 ((DMA_Channel_TypeDef *) DMA1_Channel6_BASE) #define DMA1_Channel7 ((DMA_Channel_TypeDef *) DMA1_Channel7_BASE) #define DMA2_Channel1 ((DMA_Channel_TypeDef *) DMA2_Channel1_BASE) #define DMA2_Channel2 ((DMA_Channel_TypeDef *) DMA2_Channel2_BASE) #define DMA2_Channel3 ((DMA_Channel_TypeDef *) DMA2_Channel3_BASE) #define DMA2_Channel4 ((DMA_Channel_TypeDef *) DMA2_Channel4_BASE) #define DMA2_Channel5 ((DMA_Channel_TypeDef *) DMA2_Channel5_BASE)
DMA_InitTypeDef
/***stm32f10x_dma.h***/ 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; #define DMA_DIR_PeripheralDST ((uint32_t)0x00000010) #define DMA_DIR_PeripheralSRC ((uint32_t)0x00000000) #define IS_DMA_DIR(DIR) (((DIR) == DMA_DIR_PeripheralDST) || \ ((DIR) == DMA_DIR_PeripheralSRC)) #define DMA_PeripheralInc_Enable ((uint32_t)0x00000040) #define DMA_PeripheralInc_Disable ((uint32_t)0x00000000) #define IS_DMA_PERIPHERAL_INC_STATE(STATE) (((STATE) == DMA_PeripheralInc_Enable) || \ ((STATE) == DMA_PeripheralInc_Disable)) #define DMA_MemoryInc_Enable ((uint32_t)0x00000080) #define DMA_MemoryInc_Disable ((uint32_t)0x00000000) #define IS_DMA_MEMORY_INC_STATE(STATE) (((STATE) == DMA_MemoryInc_Enable) || \ ((STATE) == DMA_MemoryInc_Disable)) #define DMA_PeripheralDataSize_Byte ((uint32_t)0x00000000) #define DMA_PeripheralDataSize_HalfWord ((uint32_t)0x00000100) #define DMA_PeripheralDataSize_Word ((uint32_t)0x00000200) #define IS_DMA_PERIPHERAL_DATA_SIZE(SIZE) (((SIZE) == DMA_PeripheralDataSize_Byte) || \ ((SIZE) == DMA_PeripheralDataSize_HalfWord) || \ ((SIZE) == DMA_PeripheralDataSize_Word)) #define DMA_MemoryDataSize_Byte ((uint32_t)0x00000000) #define DMA_MemoryDataSize_HalfWord ((uint32_t)0x00000400) #define DMA_MemoryDataSize_Word ((uint32_t)0x00000800) #define IS_DMA_MEMORY_DATA_SIZE(SIZE) (((SIZE) == DMA_MemoryDataSize_Byte) || \ ((SIZE) == DMA_MemoryDataSize_HalfWord) || \ ((SIZE) == DMA_MemoryDataSize_Word)) #define DMA_Mode_Circular ((uint32_t)0x00000020) #define DMA_Mode_Normal ((uint32_t)0x00000000) #define IS_DMA_MODE(MODE) (((MODE) == DMA_Mode_Circular) || ((MODE) == DMA_Mode_Normal)) #define DMA_Priority_VeryHigh ((uint32_t)0x00003000) #define DMA_Priority_High ((uint32_t)0x00002000) #define DMA_Priority_Medium ((uint32_t)0x00001000) #define DMA_Priority_Low ((uint32_t)0x00000000) #define IS_DMA_PRIORITY(PRIORITY) (((PRIORITY) == DMA_Priority_VeryHigh) || \ ((PRIORITY) == DMA_Priority_High) || \ ((PRIORITY) == DMA_Priority_Medium) || \ ((PRIORITY) == DMA_Priority_Low)) #define DMA_M2M_Enable ((uint32_t)0x00004000) #define DMA_M2M_Disable ((uint32_t)0x00000000) #define IS_DMA_M2M_STATE(STATE) (((STATE) == DMA_M2M_Enable) || ((STATE) == DMA_M2M_Disable))
3.2 函数
DMA_Init()
void DMA_Init(DMA_Channel_TypeDef* DMAy_Channelx, DMA_InitTypeDef* DMA_InitStruct) { uint32_t tmpreg = 0; /* Check the parameters */ assert_param(IS_DMA_ALL_PERIPH(DMAy_Channelx)); assert_param(IS_DMA_DIR(DMA_InitStruct->DMA_DIR)); assert_param(IS_DMA_BUFFER_SIZE(DMA_InitStruct->DMA_BufferSize)); assert_param(IS_DMA_PERIPHERAL_INC_STATE(DMA_InitStruct->DMA_PeripheralInc)); assert_param(IS_DMA_MEMORY_INC_STATE(DMA_InitStruct->DMA_MemoryInc)); assert_param(IS_DMA_PERIPHERAL_DATA_SIZE(DMA_InitStruct->DMA_PeripheralDataSize)); assert_param(IS_DMA_MEMORY_DATA_SIZE(DMA_InitStruct->DMA_MemoryDataSize)); assert_param(IS_DMA_MODE(DMA_InitStruct->DMA_Mode)); assert_param(IS_DMA_PRIORITY(DMA_InitStruct->DMA_Priority)); assert_param(IS_DMA_M2M_STATE(DMA_InitStruct->DMA_M2M)); /*--------------------------- DMAy Channelx CCR Configuration -----------------*/ /* Get the DMAy_Channelx CCR value */ tmpreg = DMAy_Channelx->CCR; /* Clear MEM2MEM, PL, MSIZE, PSIZE, MINC, PINC, CIRC and DIR bits */ tmpreg &= CCR_CLEAR_Mask; /* Configure DMAy Channelx: data transfer, data size, priority level and mode */ /* Set DIR bit according to DMA_DIR value */ /* Set CIRC bit according to DMA_Mode value */ /* Set PINC bit according to DMA_PeripheralInc value */ /* Set MINC bit according to DMA_MemoryInc value */ /* Set PSIZE bits according to DMA_PeripheralDataSize value */ /* Set MSIZE bits according to DMA_MemoryDataSize value */ /* Set PL bits according to DMA_Priority value */ /* Set the MEM2MEM bit according to DMA_M2M value */ tmpreg |= DMA_InitStruct->DMA_DIR | DMA_InitStruct->DMA_Mode | DMA_InitStruct->DMA_PeripheralInc | DMA_InitStruct->DMA_MemoryInc | DMA_InitStruct->DMA_PeripheralDataSize | DMA_InitStruct->DMA_MemoryDataSize | DMA_InitStruct->DMA_Priority | DMA_InitStruct->DMA_M2M; /* Write to DMAy Channelx CCR */ DMAy_Channelx->CCR = tmpreg; /*--------------------------- DMAy Channelx CNDTR Configuration ---------------*/ /* Write to DMAy Channelx CNDTR */ DMAy_Channelx->CNDTR = DMA_InitStruct->DMA_BufferSize; /*--------------------------- DMAy Channelx CPAR Configuration ----------------*/ /* Write to DMAy Channelx CPAR */ DMAy_Channelx->CPAR = DMA_InitStruct->DMA_PeripheralBaseAddr; /*--------------------------- DMAy Channelx CMAR Configuration ----------------*/ /* Write to DMAy Channelx CMAR */ DMAy_Channelx->CMAR = DMA_InitStruct->DMA_MemoryBaseAddr; }
DMA_StructInit()
void DMA_StructInit(DMA_InitTypeDef* DMA_InitStruct) { /*-------------- Reset DMA init structure parameters values ------------------*/ /*CPAR通道外设地址寄存器*/ DMA_InitStruct->DMA_PeripheralBaseAddr = 0; /*CMAR通道存储器地址寄存器*/ DMA_InitStruct->DMA_MemoryBaseAddr = 0; /*CNDTR通道传输数据量寄存器*/ DMA_InitStruct->DMA_BufferSize = 0; DMA_InitStruct->DMA_DIR = DMA_DIR_PeripheralSRC; DMA_InitStruct->DMA_PeripheralInc = DMA_PeripheralInc_Disable; DMA_InitStruct->DMA_MemoryInc = DMA_MemoryInc_Disable; DMA_InitStruct->DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte; DMA_InitStruct->DMA_MemoryDataSize = DMA_MemoryDataSize_Byte; DMA_InitStruct->DMA_Mode = DMA_Mode_Normal; DMA_InitStruct->DMA_Priority = DMA_Priority_Low; DMA_InitStruct->DMA_M2M = DMA_M2M_Disable; }
DMA_Cmd()
/***可能所有外设的使能都是peripheral_cmd()***/ void DMA_Cmd(DMA_Channel_TypeDef* DMAy_Channelx, FunctionalState NewState) { /* Check the parameters */ assert_param(IS_DMA_ALL_PERIPH(DMAy_Channelx)); assert_param(IS_FUNCTIONAL_STATE(NewState)); if (NewState != DISABLE) { /* Enable the selected DMAy Channelx */ DMAy_Channelx->CCR |= DMA_CCR1_EN; } else { /* Disable the selected DMAy Channelx */ DMAy_Channelx->CCR &= (uint16_t)(~DMA_CCR1_EN); } }
DMA_ITConfig()
/***CCR中三个中断函数使能配置,TEIE、HTIE、TCIE;***/ #define DMA_IT_TC ((uint32_t)0x00000002) #define DMA_IT_HT ((uint32_t)0x00000004) #define DMA_IT_TE ((uint32_t)0x00000008) #define IS_DMA_CONFIG_IT(IT) ((((IT) & 0xFFFFFFF1) == 0x00) && ((IT) != 0x00)) void DMA_ITConfig(DMA_Channel_TypeDef* DMAy_Channelx, uint32_t DMA_IT, FunctionalState NewState) { /* Check the parameters */ assert_param(IS_DMA_ALL_PERIPH(DMAy_Channelx)); assert_param(IS_DMA_CONFIG_IT(DMA_IT)); assert_param(IS_FUNCTIONAL_STATE(NewState)); if (NewState != DISABLE) { /* Enable the selected DMA interrupts */ DMAy_Channelx->CCR |= DMA_IT; } else { /* Disable the selected DMA interrupts */ DMAy_Channelx->CCR &= ~DMA_IT; } }
DMA_SetCurrDataCounter()
void DMA_SetCurrDataCounter(DMA_Channel_TypeDef* DMAy_Channelx, uint16_t DataNumber) { /* Check the parameters */ assert_param(IS_DMA_ALL_PERIPH(DMAy_Channelx)); /*--------------------------- DMAy Channelx CNDTR Configuration ---------------*/ /* Write to DMAy Channelx CNDTR */ DMAy_Channelx->CNDTR = DataNumber; }
DMA_GetCurrDataCounter()
uint16_t DMA_GetCurrDataCounter(DMA_Channel_TypeDef* DMAy_Channelx) { /* Check the parameters */ assert_param(IS_DMA_ALL_PERIPH(DMAy_Channelx)); /* Return the number of remaining data units for DMAy Channelx */ return ((uint16_t)(DMAy_Channelx->CNDTR)); }
DMA_GetFlagStatus()
/***ISR寄存器对应bit读取,和后面的DMA_GetITStatus()函数完全一样;***/ #define IS_DMA_GET_FLAG(FLAG) (((FLAG) == DMA1_FLAG_GL1) || ((FLAG) == DMA1_FLAG_TC1) || ((FLAG) == DMA1_FLAG_HT1) || ((FLAG) == DMA1_FLAG_TE1) || \ ((FLAG) == DMA1_FLAG_GL2) || ((FLAG) == DMA1_FLAG_TC2) || ((FLAG) == DMA1_FLAG_HT2) || ((FLAG) == DMA1_FLAG_TE2) || \ ((FLAG) == DMA1_FLAG_GL3) || ((FLAG) == DMA1_FLAG_TC3) || ((FLAG) == DMA1_FLAG_HT3) || ((FLAG) == DMA1_FLAG_TE3) || \ ((FLAG) == DMA1_FLAG_GL4) || ((FLAG) == DMA1_FLAG_TC4) || ((FLAG) == DMA1_FLAG_HT4) || ((FLAG) == DMA1_FLAG_TE4) || \ ((FLAG) == DMA1_FLAG_GL5) || ((FLAG) == DMA1_FLAG_TC5) || ((FLAG) == DMA1_FLAG_HT5) || ((FLAG) == DMA1_FLAG_TE5) || \ ((FLAG) == DMA1_FLAG_GL6) || ((FLAG) == DMA1_FLAG_TC6) || ((FLAG) == DMA1_FLAG_HT6) || ((FLAG) == DMA1_FLAG_TE6) || \ ((FLAG) == DMA1_FLAG_GL7) || ((FLAG) == DMA1_FLAG_TC7) || ((FLAG) == DMA1_FLAG_HT7) || ((FLAG) == DMA1_FLAG_TE7) || \ ((FLAG) == DMA2_FLAG_GL1) || ((FLAG) == DMA2_FLAG_TC1) || ((FLAG) == DMA2_FLAG_HT1) || ((FLAG) == DMA2_FLAG_TE1) || \ ((FLAG) == DMA2_FLAG_GL2) || ((FLAG) == DMA2_FLAG_TC2) || ((FLAG) == DMA2_FLAG_HT2) || ((FLAG) == DMA2_FLAG_TE2) || \ ((FLAG) == DMA2_FLAG_GL3) || ((FLAG) == DMA2_FLAG_TC3) || ((FLAG) == DMA2_FLAG_HT3) || ((FLAG) == DMA2_FLAG_TE3) || \ ((FLAG) == DMA2_FLAG_GL4) || ((FLAG) == DMA2_FLAG_TC4) || ((FLAG) == DMA2_FLAG_HT4) || ((FLAG) == DMA2_FLAG_TE4) || \ ((FLAG) == DMA2_FLAG_GL5) || ((FLAG) == DMA2_FLAG_TC5) || ((FLAG) == DMA2_FLAG_HT5) || ((FLAG) == DMA2_FLAG_TE5)) FlagStatus DMA_GetFlagStatus(uint32_t DMAy_FLAG) { FlagStatus bitstatus = RESET; uint32_t tmpreg = 0; /* Check the parameters */ assert_param(IS_DMA_GET_FLAG(DMAy_FLAG)); /* Calculate the used DMAy */ if ((DMAy_FLAG & FLAG_Mask) != (uint32_t)RESET) { /* Get DMA2 ISR register value */ tmpreg = DMA2->ISR ; } else { /* Get DMA1 ISR register value */ tmpreg = DMA1->ISR ; } /* Check the status of the specified DMAy flag */ if ((tmpreg & DMAy_FLAG) != (uint32_t)RESET) { /* DMAy_FLAG is set */ bitstatus = SET; } else { /* DMAy_FLAG is reset */ bitstatus = RESET; } /* Return the DMAy_FLAG status */ return bitstatus; }
DMA_ClearFlag()
/***IFCR对应位配置,用来清除ISR中对应位; ***和后面的DMA_ClearITPendingBit()是逻辑相同的函数;***/ #define IS_DMA_CLEAR_FLAG(FLAG) (((((FLAG) & 0xF0000000) == 0x00) || (((FLAG) & 0xEFF00000) == 0x00)) && ((FLAG) != 0x00)) void DMA_ClearFlag(uint32_t DMAy_FLAG) { /* Check the parameters */ assert_param(IS_DMA_CLEAR_FLAG(DMAy_FLAG)); /* Calculate the used DMAy */ if ((DMAy_FLAG & FLAG_Mask) != (uint32_t)RESET) { /* Clear the selected DMAy flags */ DMA2->IFCR = DMAy_FLAG; } else { /* Clear the selected DMAy flags */ DMA1->IFCR = DMAy_FLAG; } }
DMA_GetITStatus()
/*这函数和前面的DMA_GetFlagStatus()完全一样,就是为了对齐凑数的;*/ ITStatus DMA_GetITStatus(uint32_t DMAy_IT) { ITStatus bitstatus = RESET; uint32_t tmpreg = 0; /* Check the parameters */ assert_param(IS_DMA_GET_IT(DMAy_IT)); /* Calculate the used DMA */ if ((DMAy_IT & FLAG_Mask) != (uint32_t)RESET) { /* Get DMA2 ISR register value */ tmpreg = DMA2->ISR; } else { /* Get DMA1 ISR register value */ tmpreg = DMA1->ISR; } /* Check the status of the specified DMAy interrupt */ if ((tmpreg & DMAy_IT) != (uint32_t)RESET) { /* DMAy_IT is set */ bitstatus = SET; } else { /* DMAy_IT is reset */ bitstatus = RESET; } /* Return the DMA_IT status */ return bitstatus; }
DMA_ClearITPendingBit()
/*清除IFCR中的中断flag位,和前面的DMA_ClearFlag()代码相同,这个函数也是凑数的;*/ #define IS_DMA_CLEAR_IT(IT) (((((IT) & 0xF0000000) == 0x00) || (((IT) & 0xEFF00000) == 0x00)) && ((IT) != 0x00)) void DMA_ClearITPendingBit(uint32_t DMAy_IT) { /* Check the parameters */ assert_param(IS_DMA_CLEAR_IT(DMAy_IT)); /* Calculate the used DMAy */ if ((DMAy_IT & FLAG_Mask) != (uint32_t)RESET) { /* Clear the selected DMAy interrupt pending bits */ DMA2->IFCR = DMAy_IT; } else { /* Clear the selected DMAy interrupt pending bits */ DMA1->IFCR = DMAy_IT; } }
4 使用函数
dma.c
#include "dma.h" #include "usart.h" u8 dma_to_usart1_buf[dma2usart_buf_size]; u8 usart1_to_dma_buf[buf_size]; u8 mem2mem_src[buf_size]={0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15}; u8 mem2mem_des[buf_size]={0}; void dma2usart_buf_init(void) { int i=0; u8 j=0; for(i=0;i<dma2usart_buf_size;i++){ dma_to_usart1_buf[i]=j; j++; } } void dma_to_usart1_init(void) { dma2usart_buf_init(); DMA_InitTypeDef DMA_InitStructure; RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE); DMA_InitStructure.DMA_PeripheralBaseAddr = (USART1_BASE+0x04); DMA_InitStructure.DMA_MemoryBaseAddr = (u32)dma_to_usart1_buf; DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST; DMA_InitStructure.DMA_BufferSize = dma2usart_buf_size; DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable; DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable; DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte; DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte; DMA_InitStructure.DMA_Mode = DMA_Mode_Normal; DMA_InitStructure.DMA_Priority = DMA_Priority_Medium; DMA_InitStructure.DMA_M2M = DMA_M2M_Disable; DMA_Init(DMA1_Channel4, &DMA_InitStructure); DMA_Cmd (DMA1_Channel4,ENABLE); USART_DMACmd(USART1, USART_DMAReq_Tx, ENABLE); } void usart1_to_dma_init(void) { DMA_InitTypeDef DMA_InitStructure; RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE); DMA_InitStructure.DMA_PeripheralBaseAddr = (USART1_BASE+0x04); DMA_InitStructure.DMA_MemoryBaseAddr = (u32)usart1_to_dma_buf; DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC; DMA_InitStructure.DMA_BufferSize = buf_size; DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable; DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable; DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte; DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte; DMA_InitStructure.DMA_Mode = DMA_Mode_Normal ; DMA_InitStructure.DMA_Priority = DMA_Priority_Medium; DMA_InitStructure.DMA_M2M = DMA_M2M_Disable; DMA_Init(DMA1_Channel5, &DMA_InitStructure); DMA_Cmd (DMA1_Channel5,ENABLE); USART_DMACmd(USART1, USART_DMAReq_Rx, ENABLE); while( !DMA_GetFlagStatus(DMA1_FLAG_TC5) ) ; DMA_ClearFlag(DMA1_FLAG_TC5); int i=0; for(i=0;i<buf_size;i++) printf("%x",usart1_to_dma_buf[i]); } void dma_to_dma_init(void) { DMA_InitTypeDef DMA_InitStructure; RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE); DMA_InitStructure.DMA_PeripheralBaseAddr = (u32)mem2mem_src; DMA_InitStructure.DMA_MemoryBaseAddr = (u32)mem2mem_des; DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC; DMA_InitStructure.DMA_BufferSize = buf_size; 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_InitStructure.DMA_Mode = DMA_Mode_Normal ; DMA_InitStructure.DMA_Priority = DMA_Priority_High; DMA_InitStructure.DMA_M2M = DMA_M2M_Enable; DMA_Init(DMA1_Channel1, &DMA_InitStructure); DMA_Cmd(DMA1_Channel1,ENABLE); while( !DMA_GetFlagStatus(DMA1_FLAG_TC1) ) ; DMA_ClearFlag(DMA1_FLAG_TC1); int i=0; for(i=0;i<buf_size;i++) printf("%x",mem2mem_des[i]); }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· AI 智能体引爆开源社区「GitHub 热点速览」
· 三行代码完成国际化适配,妙~啊~
· .NET Core 中如何实现缓存的预热?