根据香水城老师的建议把DMA传输模式由内存-内存改为外设-内存,DMA中断寄存器DMA1->LISR相应标志位正常。但是有新的问题。需要两次启动DMA传输后,才能出现一次DMA中断。相关程序如下。
//DMA配置函数
void MYDMA_Config(DMA_Stream_TypeDef *DMA_Streamx,uint8_t chx,uint32_t par,uint32_t mar,uint16_t ndtr)
{
DMA_TypeDef *DMAx;
DMAMUX_Channel_TypeDef *DMAMUXx;
uint8_t streamx;
if((uint32_t)DMA_Streamx>(uint32_t)DMA2)//得到当前stream是属于DMA2还是DMA1
{
DMAx=DMA2;
RCC->AHB1ENR|=1<<1; //DMA2时钟使能
}else
{
DMAx=DMA1;
RCC->AHB1ENR|=1<<0; //DMA1时钟使能
}
while(DMA_Streamx->CR&0X01);//等待DMA可配置
streamx=(((uint32_t)DMA_Streamx-(uint32_t)DMAx)-0X10)/0X18; //得到stream通道号
if(streamx>=6)DMAx->HIFCR|=0X3D<<(6*(streamx-6)+16); //清空之前该stream上的所有中断标志
else if(streamx>=4)DMAx->HIFCR|=0X3D<<6*(streamx-4); //清空之前该stream上的所有中断标志
else if(streamx>=2)DMAx->LIFCR|=0X3D<<(6*(streamx-2)+16); //清空之前该stream上的所有中断标志
else DMAx->LIFCR|=0X3D<<6*streamx; //清空之前该stream上的所有中断标志
if((uint32_t)DMA_Streamx>(uint32_t)DMA2)streamx+=8; //如果是DMA2,通道编号+8
DMAMUXx=(DMAMUX_Channel_TypeDef *)(DMAMUX1_BASE+streamx*4); //得到对应的DMAMUX通道控制地址
DMAMUXx->CCR=chx&0XFF; //通道选择
DMA_Streamx->PAR=par; //DMA外设地址
DMA_Streamx->M0AR=mar; //DMA 存储器0地址
DMA_Streamx->NDTR=ndtr; //DMA 存储器0地址
DMA_Streamx->CR=0; //先全部复位CR寄存器值
DMA_Streamx->CR|=0<<6;
DMA_Streamx->CR|=0<<7; //外设到存储器模式
DMA_Streamx->CR|=0<<8; //非循环模式(即使用普通模式)
DMA_Streamx->CR|=0<<9; //外设非增量模式
DMA_Streamx->CR|=1<<10; //存储器增量模式
DMA_Streamx->CR|=1<<11; //外设数据长度:16位
DMA_Streamx->CR|=1<<13; //存储器数据长度:16位
DMA_Streamx->CR|=1<<16; //中等优先级
DMA_Streamx->CR|=0<<21; //外设突发单次传输
DMA_Streamx->CR|=0<<23; //存储器突发单次传输
DMA_Streamx->CR|=1<<4; //传输完成产生中断
DMA_Streamx->CR|=1<<3; //传输完成一半产生中断
DMA_Streamx->CR|=1<<2; //传输错误产生中断
DMA_Streamx->CR|=1<<1; //直接模式错误产生中断
//DMA_Streamx->FCR=0X21; //FIFO控制寄存器
// DMA interrupt init
// DMA1_Stream0_IRQn interrupt configuration
HAL_NVIC_SetPriority(DMA1_Stream0_IRQn, 3, 0);
HAL_NVIC_EnableIRQ(DMA1_Stream0_IRQn);
}
//开启一次DMA传输
//DMA_Streamx:DMA数据流,DMA1_Stream0~7/DMA2_Stream0~7
//ndtr:数据传输量
void MYDMA_Enable(DMA_Stream_TypeDef *DMA_Streamx,uint16_t ndtr)
{
DMA_Streamx->CR&=~(1<<0); //关闭DMA传输
while(DMA_Streamx->CR&0X1); //确保DMA可以被设置
DMA_Streamx->NDTR=ndtr; //DMA 存储器0地址
DMA_Streamx->CR|=1<<0; //开启DMA传输
}
// dma传输完成中断处理
void DMA1_Stream0_IRQHandler(void)
{
HAL_DMA_IRQHandler(&hdma_memtomem_dma1_stream0);
/* USER CODE BEGIN DMA1_Stream0_IRQn 1 */
if(__HAL_DMA_GET_FLAG(&hdma_memtomem_dma1_stream0,DMA_FLAG_TCIF0_4))//判断是否为DMA传输完成中断
{
__HAL_DMA_CLEAR_FLAG(&hdma_memtomem_dma1_stream0,DMA_FLAG_TCIF0_4);//清除中断标志位
HAL_DMA_Abort_IT(&hdma_memtomem_dma1_stream0); //传输完成以后关闭DMA
//在此添加dma传输完成后的函数
}
}
//FIFO中断 外部中断1 PB1
void EXTI1_IRQHandler(void)
{
/* USER CODE BEGIN EXTI1_IRQn 0 */
/* USER CODE END EXTI1_IRQn 0 */
DisADsample();
HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_1);
/* USER CODE BEGIN EXTI1_IRQn 1 */
MYDMA_Enable(DMA1_Stream0,16000);//开始一次DMA传输!
/* USER CODE END EXTI1_IRQn 1 */
}
//DMA初始化
MYDMA_Config(DMA1_Stream0,0,(uint32_t)0x64000000,(uint32_t) 0x24001000,16000);//DMA1,STEAM0,CH0,外设为FIFO,存储器为SendBuff,长度为:16000.
为什么两次启动DMA传输才能有一次DMA中断?
|