野火电子论坛

 找回密码
 注册

QQ登录

只需一步,快速开始

查看: 19428|回复: 1

DMA+串口空闲中断得到数据都是0

[复制链接]
发表于 2020-8-14 09:26:52 | 显示全部楼层 |阅读模式
我使用dma双缓冲,配合串口的空闲中断,接收遥控器的DBUS信号,可以进入空闲中断,但是将内存接收数组打印出来都是0,在仿真中可以看到串口数据寄存器中是有数据的,使用普通的RXNE中断可以正常接收,但是使用dma空闲中断
不管DMA开不开双缓存接收的内存数组中都是0


//DMA_StreamxMA数据流,DMA1_Stream0~7/DMA2_Stream0~7
//chxMA通道选择,@Ref DMA_channel DMA_Channel_0~DMA_Channel_7
//par:外设地址
//mar:存储器地址
//direction:数据传输方向
//ndtr:数据传输量  
//dmamode:dma模式
void MYDMA_Config(DMA_Stream_TypeDef *DMA_Streamx,u32 chx,u32 par,u32 mar,u32 direction,u16 ndtr,u32 dmamode)
{

        DMA_InitTypeDef  DMA_InitStructure;
       
        if((u32)DMA_Streamx>(u32)DMA2)//得到当前stream是属于DMA2还是DMA1
        {
          RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA2,ENABLE);//DMA2时钟使能
               
        }else
        {
          RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA1,ENABLE);//DMA1时钟使能
        }
  DMA_DeInit(DMA_Streamx);
       
        while (DMA_GetCmdStatus(DMA_Streamx) != DISABLE){}//等待DMA可配置
       
  /* 配置 DMA Stream */
  DMA_InitStructure.DMA_Channel = chx;  //通道选择
  DMA_InitStructure.DMA_PeripheralBaseAddr = par;//DMA外设地址
  DMA_InitStructure.DMA_Memory0BaseAddr = mar;//DMA 存储器0地址
  DMA_InitStructure.DMA_DIR = direction;//存储器到外设模式
  DMA_InitStructure.DMA_BufferSize = ndtr;//数据传输量
  DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;//外设非增量模式
  DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;//存储器增量模式
  DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;//外设数据长度:8位
  DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;//存储器数据长度:8位
  DMA_InitStructure.DMA_Mode = dmamode;// 使用普通模式
  DMA_InitStructure.DMA_Priority = DMA_Priority_VeryHigh;//中等优先级
  DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Enable;         
  DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_1QuarterFull;
  DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single;//存储器突发单次传输
  DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;//外设突发单次传输       
  DMA_Init(DMA_Streamx, &DMA_InitStructure);//初始化DMA Stream

}

u8 USART4_DBUS_RX_BUF[18];
u8 USART4_DBUS_RX_BUF1[18];
void Uart4_DBUS_Init(u32 bound)              //串口3
{
  //GPIO端口设置
  GPIO_InitTypeDef GPIO_InitStructure;
        USART_InitTypeDef USART_InitStructure;
        NVIC_InitTypeDef NVIC_InitStructure;
       
  RCC_APB1PeriphClockCmd(RCC_APB1Periph_UART4,ENABLE);
        RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOC,ENABLE); //使能GPIOB时钟
        RCC_AHB1PeriphResetCmd(RCC_AHB1Periph_DMA1,ENABLE);
       
  //串口3对应引脚复用映射
        GPIO_PinAFConfig(GPIOC,GPIO_PinSource10,GPIO_AF_UART4);
        GPIO_PinAFConfig(GPIOC,GPIO_PinSource11,GPIO_AF_UART4);
       
        //UART4端口配置
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11;
        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;//复用功能
        GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;        //速度50MHz
        GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; //推挽复用输出
        GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP; //上拉
        GPIO_Init(GPIOC,&GPIO_InitStructure); //初始化

   //USART 初始化设置
        USART_InitStructure.USART_BaudRate = bound;//串口波特率
        USART_InitStructure.USART_WordLength = USART_WordLength_8b;//字长为8位数据格式
        USART_InitStructure.USART_StopBits = USART_StopBits_1;//一个停止位
        USART_InitStructure.USART_Parity = USART_Parity_No;//无奇偶校验位
        USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;//无硬件数据流控制
        USART_InitStructure.USART_Mode = USART_Mode_Rx |  USART_Mode_Tx;        //收发模式
  USART_Init(UART4, &USART_InitStructure);

  //Uart5 NVIC 配置
  NVIC_InitStructure.NVIC_IRQChannel = UART4_IRQn;
        NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=3 ;//抢占优先级2
        NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;                //子优先级1
        NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;                        //IRQ通道使能
        NVIC_Init(&NVIC_InitStructure);        //根据指定的参数初始化VIC寄存器
       
  MYDMA_Config(DMA1_Stream2,DMA_Channel_4,(u32)&UART4->DR,
                                                                        (u32)USART4_DBUS_RX_BUF,
                                                                        DMA_DIR_PeripheralToMemory,
                                                                        USART4_DBUS_LEN,
                                                                        DMA_Mode_Circular);  //最大一次接收256字节       

        DMA_DoubleBufferModeConfig(DMA1_Stream2,(uint32_t)USART4_DBUS_RX_BUF1,DMA_Memory_0);
        DMA_DoubleBufferModeCmd(DMA1_Stream2,ENABLE);       
       
  USART_DMACmd(UART4, USART_DMAReq_Rx, ENABLE);    //使能DMA接收       
        DMA_Cmd(DMA1_Stream2, ENABLE);               
       
        USART_ITConfig(UART4, USART_IT_IDLE,ENABLE); //使能串口4空闲中断       
        USART_Cmd(UART4, ENABLE);  //使能串口4                                                                                                                                                       
}
u16 Remote[12];
void RemoteData(u8 *pData)
{
         Remote[0] = (((int16_t)pData[1] << 8) | (int16_t)pData[0]) & 0x07FF;
         Remote[1] = (((int16_t)pData[2] << 5) | ((int16_t)pData[1] >> 3)) & 0x07FF;
}



u16 s[2]={0,0};
extern int Motor[2];
extern float K;
u8 UART4_RX_LEN=0;
int i;
void UART4_IRQHandler(void)                           //串口3 GPS中断服务程序
{               
          u8 res;  
          if(USART_GetITStatus(UART4,USART_IT_IDLE) != RESET)
                {
                 USART_ClearITPendingBit(UART4 ,USART_IT_IDLE);    //必须先清除总线空闲中断标识,然后读一下数据寄存器,DMA接收才会正确(先读SR,然后读DR才能清除空闲中断标识)注意:这句必须要,否则不能够清除中断标志位。       
                       
                 res = UART4->SR;
                 res = UART4->DR;  //清除中断标志位
//                 num = USART_ReceiveData(UART4);//读取DR寄存器,清除中断标志位
           DMA_Cmd(DMA1_Stream2, DISABLE);       
     DMA_ClearITPendingBit(DMA1_Stream2, DMA_IT_TCIF2 | DMA_IT_TEIF2);        // Clear Transfer Complete flag
   DMA_ClearFlag(DMA1_Stream2,DMA_FLAG_TCIF2 | DMA_FLAG_FEIF2 | DMA_FLAG_DMEIF2 | DMA_FLAG_TEIF2 | DMA_FLAG_HTIF2);//清除DMA1_Steam1传输完成标志       
                       
                        if(DMA_GetCurrentMemoryTarget(DMA1_Stream2) == 0)
                        {                     
                                 RemoteData(USART4_DBUS_RX_BUF);
                                 Motor[0]=(Remote[1]+Remote[0]-2048)*K;
                                 Motor[1]=(Remote[1]-Remote[0])*K;
                        }
                        else if(DMA_GetCurrentMemoryTarget(DMA1_Stream2) == 1)
                        {
                                 RemoteData(USART4_DBUS_RX_BUF1);
                                 Motor[0]=(Remote[1]+Remote[0]-2048)*K;
                                 Motor[1]=(Remote[1]-Remote[0])*K;
                        }

//                       
                        for(i=0;i<18;i++)
                        {
                                printf("%d,",USART4_DBUS_RX_BUF);                                       
                        }
                        printf("\r\n");
                        for(i=0;i<18;i++)
                        {
                                printf("%d,",USART4_DBUS_RX_BUF1);                                       
                        }               
                        printf("\r\n");

                       
                 DMA_SetCurrDataCounter(DMA1_Stream2, USART4_DBUS_LEN);  
                 DMA_Cmd(DMA1_Stream2, ENABLE);
                }       
       
     USART_ClearITPendingBit(UART4,USART_IT_IDLE); // 清除标志位

                        Motor_Control(Motor);
}

QQ截图20200814091426.png
QQ截图20200814091447.png
QQ截图20200814091239.png
回复

使用道具 举报

 楼主| 发表于 2020-8-14 16:57:42 | 显示全部楼层
求助啊.............................................................
回复

使用道具 举报

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

本版积分规则

联系站长|手机版|野火电子官网|野火淘宝店铺|野火电子论坛 ( 粤ICP备14069197号 ) 大学生ARM嵌入式2群

GMT+8, 2024-11-25 12:50 , Processed in 0.030605 second(s), 27 queries , Gzip On.

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

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