OpenEdv-开源电子网

 找回密码
 立即注册
正点原子全套STM32/Linux/FPGA开发资料,上千讲STM32视频教程免费下载...
查看: 1757|回复: 1

為什麼DMA 外設到內存+內存到外設陷入死循環

[复制链接]

52

主题

75

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
249
金钱
249
注册时间
2018-10-17
在线时间
40 小时
发表于 2023-10-27 21:45:41 | 显示全部楼层 |阅读模式
1金钱
我想要利用"串口助理",使用DMA把字串讀入
內存之後再立刻使用DMA輸出USART到外設
"利用串口助理ˋ"顯示~~~照理說應該我輸入
一個字串之後會立刻在"串口助理"顯示兩次
但是實際卻是陷入死循環不斷顯示???
ㄑㄧㄥ


void USARTx_DMA_Config(void)
{
                DMA_InitTypeDef DMA_InitStructure;
                // 开启DMA时钟
                RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);
            
                // 设置DMA源地址:串口数据寄存器地址*/
        DMA_InitStructure.DMA_PeripheralBaseAddr = USART_DR_ADDRESS;
                // 内存地址(要传输的变量的指针)
                DMA_InitStructure.DMA_MemoryBaseAddr =(u32)SendBuff;
                // 方向:从外设到内存        
                DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST;
                // 传输大小        
                DMA_InitStructure.DMA_BufferSize = SENDBUFF_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模式,一次或者循环模式
//                DMA_InitStructure.DMA_Mode = DMA_Mode_Normal ;
                DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;        
                // 优先级:中        
                DMA_InitStructure.DMA_Priority = DMA_Priority_Medium;
                // 禁止内存到内存的传输
                DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;
                // 配置DMA通道                  
                DMA_Init(DMA1_Channel4, &DMA_InitStructure);               
                // 使能DMA
                DMA_Cmd (DMA1_Channel4,ENABLE);
}
void USARRx_DMA_Config(void)
{
                DMA_InitTypeDef DMA_InitStructure;
                // 开启DMA时钟
          DMA_DeInit(USART_TX_DMA_CHANNEL);
                RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);
                // 设置DMA源地址:串口数据寄存器地址*/
        DMA_InitStructure.DMA_PeripheralBaseAddr = USART_DR_ADDRESS;
                // 内存地址(要传输的变量的指针)
                DMA_InitStructure.DMA_MemoryBaseAddr = (u32)ReceiveBuff;
                // 方向:从外设到内存        
                DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;
                // 传输大小        
                DMA_InitStructure.DMA_BufferSize = RECEIVEBUFF_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模式,一次或者循环模式
//                DMA_InitStructure.DMA_Mode = DMA_Mode_Normal ;
                DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;        
                // 优先级:中        
                DMA_InitStructure.DMA_Priority = DMA_Priority_Medium;
                // 禁止内存到内存的传输
                DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;
                // 配置DMA通道                  
                DMA_Init(USART_TX_DMA_CHANNEL, &DMA_InitStructure);               
                // 使能DMA
                DMA_Cmd (USART_TX_DMA_CHANNEL,ENABLE);
}
uint8_t t=0;
void USART1_IRQHandler(void) //(DEBUG_USARTx,USART_IT_RXNE)!
{
        uint16_t i;
        if(USART_GetITStatus(USART1,USART_IT_IDLE) != RESET)          //重要提醒:这句话是打开串口接受一帧数据中断。每收到一帧数据进入一次中断
        {        
                DMA_Cmd(DMA1_Channel5,DISABLE);                         //DMA DISABLE
                t = DMA_GetCurrDataCounter(DMA1_Channel5);              //DMA_GetCurrDataCounter();函数计算出本次的数据接受长度,从而进行数据处理。
                Usart_SendArray(USART1,ReceiveBuff,RECEIVEBUFF_SIZE-t); // 發送字串陣列 = SENDBUFF_SIZE - Ê£Óàδ´«ÊäµÄÊý¾ÝÊýÁ¿£©
          DMA_SetCurrDataCounter(DMA1_Channel5,RECEIVEBUFF_SIZE);    //設置數據長度
                DMA_Cmd(DMA1_Channel5,ENABLE);                          //啟動DMA Channel5
                USART_ReceiveData(USART1);                              //USART接收數據
                USART_ClearFlag(USART1,USART_FLAG_IDLE);                //清除標誌位
        
                 for(i=0;i<RECEIVEBUFF_SIZE-t;i++)
                    {
                                     SendBuff=ReceiveBuff;
                                      }
                                 USART_DMACmd(USART1,USART_DMAReq_Tx,ENABLE); //始能串口1 TX
         MYDMA_Enable(DMA1_Channel4);//開始串口1DMA發送 TX
               
        }

}
void MYDMA_Enable(DMA_Channel_TypeDef*DMA_CHx)
{
        DMA_Cmd(DMA_CHx, DISABLE );  //关闭USART1 TX DMA1 所指示的通道      
         DMA_SetCurrDataCounter(DMA_CHx,SENDBUFF_SIZE);//DMA通道的DMA缓存的大小
         DMA_Cmd(DMA_CHx, ENABLE);  //使能USART1 TX DMA1 所指示的通道
}     

正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

11

主题

2130

帖子

0

精华

论坛元老

Rank: 8Rank: 8

积分
4724
金钱
4724
注册时间
2015-1-10
在线时间
590 小时
发表于 2023-10-30 17:03:22 | 显示全部楼层
逻辑有点乱。。。按照你的目的应该是接收用DMA,发送也用DMA,接收是不需要使用中断的,DMA会在串口接收到数据后自动搬用至内存,只需要控制接收内存中更新数据后打开发送DMA就行
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则



关闭

原子哥极力推荐上一条 /2 下一条

正点原子公众号

QQ|手机版|OpenEdv-开源电子网 ( 粤ICP备12000418号-1 )

GMT+8, 2025-2-24 12:23

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

快速回复 返回顶部 返回列表