相关的配置函数
//串口1接收DMA初始化配置
//DMA2 数据流5 通道2或5
void UART1RxDMA_Config(u8* buf0,u8 *buf1,u16 num,u8 width)
{
u32 memwidth=0,perwidth=0;
switch(width)
{
case 0:
memwidth=DMA_MDATAALIGN_BYTE;
perwidth=DMA_PDATAALIGN_BYTE;
break;
case 1:
memwidth=DMA_MDATAALIGN_HALFWORD;
perwidth=DMA_PDATAALIGN_HALFWORD;
break;
case 2:
memwidth=DMA_MDATAALIGN_WORD;
perwidth=DMA_PDATAALIGN_WORD;
break;
}
//impinjbuf1=mymalloc(SRAMEX,IMPINJ_BUF_SIZE);
//impinjbuf2=mymalloc(SRAMEX,IMPINJ_BUF_SIZE);
__HAL_RCC_DMA2_CLK_ENABLE();
__HAL_LINKDMA(&UART1_Handler,hdmarx,UART1RxDMA_Handler);
UART1RxDMA_Handler.Instance=DMA2_Stream5;
UART1RxDMA_Handler.Init.Channel=DMA_CHANNEL_4;
UART1RxDMA_Handler.Init.Direction=DMA_PERIPH_TO_MEMORY;
UART1RxDMA_Handler.Init.PeriphInc=DMA_PINC_DISABLE;
UART1RxDMA_Handler.Init.MemInc=DMA_MINC_ENABLE;
UART1RxDMA_Handler.Init.PeriphDataAlignment=perwidth;
UART1RxDMA_Handler.Init.MemDataAlignment=memwidth;
UART1RxDMA_Handler.Init.Mode=DMA_CIRCULAR;
UART1RxDMA_Handler.Init.Priority=DMA_PRIORITY_MEDIUM;
UART1RxDMA_Handler.Init.FIFOMode=DMA_FIFOMODE_DISABLE;
UART1RxDMA_Handler.Init.MemBurst=DMA_MBURST_SINGLE;
UART1RxDMA_Handler.Init.PeriphBurst=DMA_PBURST_SINGLE;
HAL_DMA_DeInit(&UART1RxDMA_Handler);
HAL_DMA_Init(&UART1RxDMA_Handler);
HAL_DMAEx_MultiBufferStart(&UART1RxDMA_Handler,(u32)&USART1->DR,(u32)buf0,(u32)buf1,num);
__HAL_DMA_DISABLE(&UART1RxDMA_Handler);
delay_us(10);
__HAL_DMA_CLEAR_FLAG(&UART1RxDMA_Handler,DMA_FLAG_TCIF1_5);//清除传输完成中断标志位
__HAL_DMA_ENABLE_IT(&UART1RxDMA_Handler,DMA_IT_TC); //开启传输完成中断
HAL_NVIC_SetPriority(DMA2_Stream5_IRQn,0,1);
HAL_NVIC_EnableIRQ(DMA2_Stream5_IRQn);
}
void ImpinjRxDMA_Start(void)
{
__HAL_DMA_ENABLE(&UART1RxDMA_Handler);
}
void ImpinjRxDMA_Stop(void)
{
__HAL_DMA_DISABLE(&UART1RxDMA_Handler);
}
void DMA2_Stream5_IRQHandler(void)
{
if(__HAL_DMA_GET_FLAG(&UART1RxDMA_Handler,DMA_FLAG_TCIF1_5)!=RESET) //DMA传输完成
{
__HAL_DMA_CLEAR_FLAG(&UART1RxDMA_Handler,DMA_FLAG_TCIF1_5); //清除DMA传输完成中断标志位
UART1RxDMA_callback(); //执行回调函数,读取数据等操作在这里面处理
}
}
//这个回调函数里是切换传输完成内存块的地址
//我所用的双缓冲是在一个大缓存里取相邻的两个小缓存
void UART1RxDMA_callback(void)
{
sw_cnt=sw_cnt+1;
if(sw_cnt/2==1)
{
sw_0=sw_0+1;
}
else
{
sw_1=sw_1+1;
}
if(DMA2_Stream5->CR&(1<<19))
{
DMA2_Stream1->M0AR = (u32)&IPJ_BUF[sw_0*2*IPJ_miniBUF_SIZE];
LED0=!LED0;
}
else
{
DMA2_Stream1->M1AR = (u32)&IPJ_BUF[IPJ_miniBUF_SIZE+sw_1*2*IPJ_miniBUF_SIZE];
LED1=!LED1;
}
}
//初始化
IPJ_BUF_MALLOC(); //大缓存内存申请
UART1RxDMA_Config(IPJ_BUF,&IPJ_BUF[IPJ_miniBUF_SIZE],IPJ_miniBUF_SIZE,0);//开始采用大缓存的首地址和一个偏移地址,传输项目量为偏移地址大小即小缓存大小
ImpinjRxDMA_Start();//开启传输
问题:无法进入传输完成中断
友情提示: 此问题已得到解决,问题已经关闭,关闭后问题禁止继续编辑,回答。
//UART3RxDMA的通道配置
//从外设->存储器模式/8位数据宽度/外设增量模式
//DMA数据流MA1_Stream1
//DMA通道: DMA_CHANNEL_4
void UART3RxDMA_init()
{
__HAL_RCC_DMA1_CLK_ENABLE(); //DMA1时钟使能
__HAL_LINKDMA(&UART3_Handler,hdmarx,UART3RxDMA_Handler); //将DMA与USART3联系起来(接收DMA)
//Rx DMA配置
UART3RxDMA_Handler.Instance=DMA1_Stream1; //数据流选择DMA1_Stream1
UART3RxDMA_Handler.Init.Channel=DMA_CHANNEL_4; //通道选择 DMA_CHANNEL_4
UART3RxDMA_Handler.Init.Direction=DMA_PERIPH_TO_MEMORY; //外设到存储器
UART3RxDMA_Handler.Init.PeriphInc=DMA_PINC_DISABLE; //外设非增量模式
UART3RxDMA_Handler.Init.MemInc=DMA_MINC_ENABLE; //存储器增量模式
UART3RxDMA_Handler.Init.PeriphDataAlignment=DMA_PDATAALIGN_BYTE; //外设数据长度:8位
UART3RxDMA_Handler.Init.MemDataAlignment=DMA_MDATAALIGN_BYTE; //存储器数据长度:8位
//UART3RxDMA_Handler.Init.Mode=DMA_NORMAL; //外设普通模式
UART3RxDMA_Handler.Init.Mode=DMA_CIRCULAR; //外设普通模式
UART3RxDMA_Handler.Init.Priority=DMA_PRIORITY_HIGH; //高等优先级
UART3RxDMA_Handler.Init.FIFOMode=DMA_FIFOMODE_DISABLE;
UART3RxDMA_Handler.Init.FIFOThreshold=DMA_FIFO_THRESHOLD_FULL;
UART3RxDMA_Handler.Init.MemBurst=DMA_MBURST_SINGLE; //存储器突发单次传输
UART3RxDMA_Handler.Init.PeriphBurst=DMA_PBURST_SINGLE; //外设突发单次传输
HAL_DMA_DeInit(&UART3RxDMA_Handler);
HAL_DMA_Init(&UART3RxDMA_Handler);
HAL_DMAEx_MultiBufferStart(&UART3RxDMA_Handler,(u32)&USART3->DR,(u32)UART3_RX_BUF0,(u32)UART3_RX_BUF1,UART3_REC_LEN);
__HAL_DMA_DISABLE(&UART3RxDMA_Handler);
delay_us(10);
__HAL_DMA_CLEAR_FLAG(&UART3RxDMA_Handler,DMA_FLAG_TCIF1_5); //清除传输完成中断标志位
__HAL_DMA_ENABLE_IT(&UART3RxDMA_Handler,DMA_IT_TC); //开启传输完成中断
HAL_NVIC_SetPriority(DMA1_Stream1_IRQn,0,4);
HAL_NVIC_EnableIRQ(DMA1_Stream1_IRQn);
__HAL_DMA_ENABLE(&UART3RxDMA_Handler);
HAL_UART_Receive_DMA(&UART3_Handler, UART3_RX_BUF0, UART3_REC_LEN); //先开启DMA接收
USART3->CR3 |= USART_CR3_DMAR;
}
//UART3RxDMA接收中断服务程序
void DMA1_Stream1_IRQHandler(void)
{
printf("DMA1_Stream1_IRQHandler in! ");
if(__HAL_DMA_GET_FLAG(&UART3RxDMA_Handler,DMA_FLAG_TCIF1_5)!=RESET) //DMA传输完成
{
printf("DMA_FLAG_TCIF1_5 != RESET! ");
__HAL_DMA_CLEAR_FLAG(&UART3RxDMA_Handler,DMA_FLAG_TCIF1_5); //清除DMA传输完成中断标志位
UART3RxDMA_callback(); //执行回调函数,读取数据等操作在这里面处理
}
}
//切换传输完成原始数据接收内存块的地址
void UART3RxDMA_callback(void)
{
//if(DMA1_Stream1->CR&(1<<19))
if((DMA1_Stream1->CR & DMA_SxCR_CT) == RESET)
{
//DMA1_Stream1->M0AR = (u32)&UART3_RX_BUF0[UART3_REC_LEN];
printf("DMA1_Stream1->M0AR ");
}
else
{
//DMA1_Stream1->M1AR = (u32)&UART3_RX_BUF1[UART3_REC_LEN];
printf("DMA1_Stream1->M1AR ");
}
}
#define DMA_SxCR_CT 0x00080000U
(DMA1_Stream1->CR & DMA_SxCR_CT)的判断值永远不变化,缓冲不能替换,一直打印 printf("DMA1_Stream1->M0AR ");
你跟踪下寄存器的值,peripherals控件选DMA1找对应数据流的CT
现在能分别进入M0AR和M1AR切换了,但是第一包数据(很大的话)能两个MxAR多次切换成功,而第二包数据就不能再切换了, 今后再进入完成中断之后,CR的值好像就不变了,不知为何?
我采用的是串口空闲中断+DMA双缓冲
说错了 不是CR寄存器的问题 我跟踪到应该是 DMA_SxCR_DBM这个寄存器的值没有被置位
导致
if(((hdma->Instance->CR) & (uint32_t)(DMA_SxCR_DBM)) != RESET)
{
/* Current memory buffer used is Memory 0 */
if((hdma->Instance->CR & DMA_SxCR_CT) == RESET)
{
//自定义1号缓存函数
Memory1CpltCallback(hdma);
}
/* Current memory buffer used is Memory 1 */
else
{
//自定义0号缓存函数
Memory0CpltCallback(hdma);
}
}
/* Disable the transfer complete interrupt if the DMA mode is not CIRCULAR */
else if((hdma->Instance->CR) != RESET)
{
if((hdma->Instance->CR & DMA_SxCR_CIRC) == RESET)
{
/* Disable the transfer complete interrupt */
hdma->Instance->CR &= ~(DMA_IT_TC);
/* Process Unlocked */
__HAL_UNLOCK(hdma);
/* Change the DMA state */
hdma->State = HAL_DMA_STATE_READY;
}
RxDMA_callback(hdma); //自定义DMA接收完成处理函数
}
一周热门 更多>