|
本帖最后由 zztq 于 2024-3-4 17:04 编辑
使用例程DMAMUX的定时器触+DMA双缓冲控制任意IO做PWM和脉冲数控制,可以正常运行,发脉冲也正确。现在我想把DMA1_Stream1更改为DMA1_Stream2,然后我发脉冲的的时候,就程序就卡在DMA1_Stream2_IRQHandler的中断服务函数里面了。
我把程序里面用到的DMA1_Stream1都更改为DMA1_Stream2了,是不是还有哪些地方要修改的,但我我没有注意到的?
代码修改的地方:
__HAL_RCC_DMA1_CLK_ENABLE();
DMA_Handle.Instance = DMA1_Stream2; /* 使用的DMA1 Stream1 此处改为DMA1_Stream2*/
DMA_Handle.Init.Request = DMA_REQUEST_GENERATOR0; /* 请求类型采用的DMAMUX请求发生器通道0 */
DMA_Handle.Init.Direction = DMA_MEMORY_TO_PERIPH; /* 传输方向是从存储器到外设 */
DMA_Handle.Init.PeriphInc = DMA_PINC_DISABLE; /* 外设地址自增禁止 */
DMA_Handle.Init.MemInc = DMA_MINC_ENABLE; /* 存储器地址自增使能 */
DMA_Handle.Init.PeriphDataAlignment = DMA_PDATAALIGN_WORD; /* 外设数据传输位宽选择字,即32bit */
DMA_Handle.Init.MemDataAlignment = DMA_MDATAALIGN_WORD; /* 存储器数据传输位宽选择字,即32bit */
DMA_Handle.Init.Mode = DMA_CIRCULAR; /* 循环模式 */
DMA_Handle.Init.Priority = DMA_PRIORITY_LOW; /* 优先级低 */
DMA_Handle.Init.FIFOMode = DMA_FIFOMODE_DISABLE; /* 禁止FIFO*/
DMA_Handle.Init.FIFOThreshold = DMA_FIFO_THRESHOLD_FULL; /* 禁止FIFO此位不起作用,用于设置阀值 */
DMA_Handle.Init.MemBurst = DMA_MBURST_SINGLE; /* 禁止FIFO此位不起作用,用于存储器突发 */
DMA_Handle.Init.PeriphBurst = DMA_PBURST_SINGLE; /* 禁止FIFO此位不起作用,用于外设突发 */
/* 初始化DMA */
if(HAL_DMA_DeInit(&DMA_Handle) != HAL_OK)
{
/* DMA处于忙状态,直接终止DMA */
if(HAL_DMA_Abort_IT(&DMA_Handle) != HAL_OK)
{
Error_Handler(__FILE__, __LINE__);
}
}
/* 初始化DMA */
if(HAL_DMA_Init(&DMA_Handle) != HAL_OK)
{
Error_Handler(__FILE__, __LINE__);
}
/* 开启DMA1 Stream1的中断 */
HAL_NVIC_SetPriority(DMA1_Stream2_IRQn, 1, 0); //此处改为DMA1_Stream2_IRQn
HAL_NVIC_EnableIRQ(DMA1_Stream2_IRQn);
void DMA1_Stream2_IRQHandler(void) //此处改为DMA1_Stream2_IRQn
{
u8 i;
/* 传输完成中断 */
if((DMA1->LISR & DMA_FLAG_TCIF1_5) != RESET)
{
/* 清除标志 */
DMA1->LIFCR = DMA_FLAG_TCIF1_5;
HAL_GPIO_TogglePin(GPIOG, GPIO_PIN_7); //LED0输出电平翻转
/* 当前使用的缓冲0 */
if((DMA1_Stream2->CR & DMA_SxCR_CT) == RESET) //此处改为DMA1_Stream2
{
/*
1、当前正在使用缓冲0,此时可以动态修改缓冲1的数据。
比如缓冲区0是IO_Toggle,缓冲区1是IO_Toggle1,那么此时就可以修改IO_Toggle1。
2、变量所在的SRAM区已经通过MPU配置为WT模式,更新变量IO_Toggle会立即写入。
3、不配置MPU的话,也可以通过Cahce的函数SCB_CleanDCache_by_Addr做Clean操作。
*/
#ifdef UsedGPIOFMC
if(PulseOutF1)
{
for(i=0;i<Buff_MAX;i++)
{
IO_Toggle1=0x00800000U;
}
DMA_pos_cnt1 = 0;
PulseOutF1 = 0;
}
// if(PulseOutF1)
// {
//
// DMA_pos_cnt1++;
// }
//
#else
#endif
}
/* 当前使用的缓冲1 */
else
{
/*
1、当前正在使用缓冲1,此时可以动态修改缓冲0的数据。
比如缓冲区0是IO_Toggle,缓冲区1是IO_Toggle1,那么此时就可以修改IO_Toggle。
2、变量所在的SRAM区已经通过MPU配置为WT模式,更新变量IO_Toggle会立即写入。
3、不配置MPU的话,也可以通过Cahce的函数SCB_CleanDCache_by_Addr做Clean操作。
*/
#ifdef UsedGPIOFMC
//
if(DMA_pos_cnt >=DMA_pos_MAX)
{
PulseOutF = 0;
for(i=0;i<Buff_MAX;i++)
{
IO_Toggle=0x00800000U;
}
//
DMA_pos_cnt = 0;
// HAL_DMAEx_DisableMuxRequestGenerator(&DMA_Handle);
}
#else
#endif
if(PulseOutF)
{
DMA_pos_cnt++;
}
}
}
/* 半传输完成中断 */
if((DMA1->LISR & DMA_FLAG_HTIF1_5) != RESET)
{
/* 清除标志 */
DMA1->LISR = DMA_FLAG_HTIF1_5;
}
/* 传输错误中断 */
if((DMA1->LISR & DMA_FLAG_TEIF1_5) != RESET)
{
/* 清除标志 */
DMA1->LISR = DMA_FLAG_TEIF1_5;
}
/* 直接模式错误中断 */
if((DMA1->LISR & DMA_FLAG_DMEIF1_5) != RESET)
{
/* 清除标志 */
DMA1->LISR = DMA_FLAG_DMEIF1_5;
}
// HAL_DMA_IRQHandler(&DMA_Handle);
}
|
|