为什么只有在串口空闲中断DMA中断里面打印接收数组才完整?

2019-07-21 04:03发布

使用的串口4空闲接收中断 + DMA,为什么只有在串口4的接收中断中打印输出才是完整,同时在调试watch1内也能看到USART4_RX_BUF数据和Usart4_Rec_Cnt 的接收动态,在外部main函数中调用Get_Picture()函数,用串口3却打印不出来,而且接收计数器Usart4_Rec_Cnt 也都为0(同样使用中断输出加黑标粗的代码)
void Get_Picture(void)
{
        u8 tx = 0, rx = 0;
        u8 senddata[7] = { 0x55, 0x48, 0x01, 0x33, 0x00, 0x02, 0x23};          //发送读数据协议55 48 01 32 00 02 23
        usart4_send(senddata, 7);       //发送7位读数据协议
        u3_printf("CAM_TX: ");
        for(tx = 0; tx < 7; tx ++)
       {
             u3_printf("%02X ",senddata[tx]);       
       }
       u3_printf(" ");
       u3_printf("CAM_RX: ");
      for(rx = 0; rx < Usart4_Rec_Cnt; rx ++)
      {
          u3_printf("%02X ",USART4_RX_BUF[rx]);       
      }
       u3_printf(" ");       
}

void uart4_init(u32 bound)
{
        GPIO_InitTypeDef GPIO_InitStructure;
        NVIC_InitTypeDef NVIC_InitStructure;
        USART_InitTypeDef USART_InitStructure;
        DMA_InitTypeDef DMA_UART4_RX;

        RCC_APB1PeriphClockCmd(RCC_APB1Periph_UART4, ENABLE);       
        RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA2, ENABLE);        //使能DMA传输
        RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC | RCC_APB2Periph_GPIOB |RCC_APB2Periph_AFIO, ENABLE);

        USART_DeInit(UART4);  //复位串口4
        //UART4_TX   PC10
        GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10; //PC.10
        GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;        //复用推挽输出
        GPIO_Init(GPIOC, &GPIO_InitStructure); //初始化PC10

        //UART4_RX          PC.11
        GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11;
        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;//浮空输入
        GPIO_Init(GPIOC, &GPIO_InitStructure);  //初始化PB11

        //485EN       PB.4
        GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4;
        GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;        //内部上拉输出
        GPIO_Init(GPIOB, &GPIO_InitStructure);
        USART4_SEND = U4SEND_DISABLE;

        //Uart4 NVIC 配置
        NVIC_InitStructure.NVIC_IRQChannel = UART4_IRQn;
        NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 3;//抢占优先级3
        NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3;                //子优先级3
        NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;                        //IRQ通道使能
        NVIC_Init(&NVIC_InitStructure);        //根据指定的参数初始化VIC寄存器

        //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); //初始化串口4
               
        USART_ITConfig(UART4, USART_IT_IDLE, ENABLE); //开启空闲中断
        USART_DMACmd(UART4, USART_DMAReq_Rx, ENABLE); //使能串口4的DMA接收
        USART_Cmd(UART4, ENABLE); //使能串口

        //DMA_RX相应的DMA配置
        DMA_DeInit(DMA2_Channel3);   //将DMA的通道5寄存器重设为缺省值  串口1对应的是DMA通道5
        DMA_UART4_RX.DMA_PeripheralBaseAddr = (u32)&UART4->DR;  //DMA外设ADC基地址
        DMA_UART4_RX.DMA_MemoryBaseAddr = (u32)USART4_RX_BUF;  //DMA内存基地址
        DMA_UART4_RX.DMA_DIR = DMA_DIR_PeripheralSRC;  //数据传输方向,从外设读取发送到内存
        DMA_UART4_RX.DMA_BufferSize = USART4_REC_LEN;  //DMA通道的DMA缓存的大小
        DMA_UART4_RX.DMA_PeripheralInc = DMA_PeripheralInc_Disable;  //外设地址寄存器不变
        DMA_UART4_RX.DMA_MemoryInc = DMA_MemoryInc_Enable;  //内存地址寄存器递增
        DMA_UART4_RX.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;  //数据宽度为8位
        DMA_UART4_RX.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte; //数据宽度为8位
        DMA_UART4_RX.DMA_Mode = DMA_Mode_Normal;  //工作在正常缓存模式
        DMA_UART4_RX.DMA_Priority = DMA_Priority_Medium; //DMA通道 x拥有中优先级
        DMA_UART4_RX.DMA_M2M = DMA_M2M_Disable;  //DMA通道x没有设置为内存到内存传输
        DMA_Init(DMA2_Channel3, &DMA_UART4_RX);  //根据DMA_InitStruct中指定的参数初始化DMA的通道USART4_Tx_DMA_Channel所标识的寄存器
               
        DMA_Cmd(DMA2_Channel3, ENABLE);  //正式驱动DMA传输
}

void UART4_RX_DMA_Enable(void)       
{
        DMA_Cmd(DMA2_Channel3, DISABLE ); //先停止DMA
        DMA_SetCurrDataCounter(DMA2_Channel3, USART4_REC_LEN); //DMA通道的DMA缓存的大小
        DMA_Cmd(DMA2_Channel3, ENABLE); //使能USART4 TX DMA2 所指示的通道
}
void UART4_IRQHandler(void)                        //串口4中断服务程序
{
#ifdef OS_TICKS_PER_SEC                 //如果时钟节拍数定义了,说明要使用ucosII了.
        OSIntEnter();   
#endif       
        //串口4空闲中断
        if(USART_GetITStatus(UART4, USART_IT_IDLE) != RESET)  
        {         
                /* 1.清除标志 */
                USART_ClearITPendingBit(UART4, USART_IT_IDLE); //清除中断标志
               
                /* 2.读取DMA */
                USART_ReceiveData(UART4); //读取数据
                Usart4_Rec_Cnt = USART4_REC_LEN - DMA_GetCurrDataCounter(DMA2_Channel3); //接收个数等于接收缓冲区总大小减已经接收的个数
       
                /* 3.开启新的一次DMA接收 */
                UART4_RX_DMA_Enable(); //重新使能DMA,等待下一次的接收

                u3_printf("CAM_RX: ");
                for(rx = 0; rx < Usart4_Rec_Cnt; rx ++)
                {
                        u3_printf("%02X ",USART4_RX_BUF[rx]);               
                }
                u3_printf(" ");
}

友情提示: 此问题已得到解决,问题已经关闭,关闭后问题禁止继续编辑,回答。
该问题目前已经被作者或者管理员关闭, 无法添加新回复
13条回答
edmund1234
1楼-- · 2019-07-21 06:06
 精彩回答 2  元偷偷看……
leozzd
2楼-- · 2019-07-21 08:54
[quote][url=forum.php?mod=redirect

最开始是有加Usart4_Rec_Cnt这个判断条件的,但打印前串口3获取Usart4_Rec_Cnt这个变量为0,而调试watch窗口为非0,有记录到接收数据个数,其他地方没有做Usart4_Rec_Cnt清0处理,Usart4_Rec_Cnt为0判断条件不成立,我才把判断条件先给去掉的。
u3_printf("接收数据长度:%d",Usart4_Rec_Cnt)
if(Usart4_Rec_Cnt)

      u3_printf("CAM_RX: ");
leozzd
3楼-- · 2019-07-21 09:02
edmund1234 发表于 2019-3-13 22:21
Get_Picture里, 发完就马上打印, 不用判断收到了没有? 能打印出来才怪呢

一开始是有加Usart4_Rec_Cnt这个判断条件,但是发送请求帧回复都是 0,
      
u3_printf("CAM_RX: ");
      for(rx = 0; rx < Usart4_Rec_Cnt; rx ++)
      {
          u3_printf("%02X ",USART4_RX_BUF[rx]);        
      }
       u3_printf(" ");
leozzd
4楼-- · 2019-07-21 10:13
edmund1234 发表于 2019-3-13 22:21
Get_Picture里, 发完就马上打印, 不用判断收到了没有? 能打印出来才怪呢

一开始是有加Usart4_Rec_Cnt这个判断条件,但是发送请求帧回复都是 0,以至于判断条件不成立不打印,我才释放掉判断条件。但是这个过程在watch串口都是能看到Usart4_Rec_Cnt和USART4_RX_BUF在变化。
if(Usart4_Rec_Cnt)
{
      u3_printf("CAM_RX: ");
      for(rx = 0; rx < Usart4_Rec_Cnt; rx ++)
      {
          u3_printf("%02X ",USART4_RX_BUF[rx]);        
      }
       u3_printf(" ");
}   
edmund1234
5楼-- · 2019-07-21 14:14
leozzd 发表于 2019-3-14 10:06
一开始是有加Usart4_Rec_Cnt这个判断条件,但是发送请求帧回复都是 0,以至于判断条件不成立不打印,我才 ...

你这个判断怎么可能有用呢

这一条判断只是在发送完之后, 检查了是否有接收到, 没有就退出

应该是类似这样的一条判断

while(!Usart4_Rec_Cnt);
leozzd
6楼-- · 2019-07-21 17:21
 精彩回答 2  元偷偷看……

一周热门 更多>