OpenEdv-开源电子网

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

STM32F103串口+DMA第一次空闲中断无法进入

[复制链接]

8

主题

33

帖子

0

精华

高级会员

Rank: 4

积分
872
金钱
872
注册时间
2017-8-1
在线时间
85 小时
发表于 2018-7-17 10:03:55 | 显示全部楼层 |阅读模式
20金钱
void usart2DmaInit(u32 baudRate)
{
        //GPIO端口设置
        GPIO_InitTypeDef GPIO_InitStructure;
        NVIC_InitTypeDef NVIC_InitStructure;
        USART_InitTypeDef USART_InitStructure;
       
        DMA_InitTypeDef DMA_InitStructure;
         
        //使能USART2,GPIOA时钟
        RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2, ENABLE);
        RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
        RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);
       
        //USART2_TX   GPIOA.2
        GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2; //PA.2
        GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;        //复用推挽输出
        GPIO_Init(GPIOA, &GPIO_InitStructure);//初始化GPIOA.2

        //USART2_RX          GPIOA.3
        GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3;//PA.3
        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;//浮空输入
        GPIO_Init(GPIOA, &GPIO_InitStructure);//初始化GPIOA.3

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

        //USART2 初始化设置
        USART_InitStructure.USART_BaudRate = baudRate;//串口波特率
        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(USART2, &USART_InitStructure); //初始化串口2
       
        //USART_ITConfig(USART2, USART_IT_RXNE, ENABLE);//开启串口接受中断
        USART_ITConfig(USART2, USART_IT_IDLE, ENABLE);//开启空闲中断
       
        //DMA1通道6配置
        DMA_DeInit(DMA1_Channel6);   //将DMA的通道6寄存器重设为缺省值  USART2 RX对应的是DMA1通道6
        DMA_InitStructure.DMA_PeripheralBaseAddr = (u32)&USART2->DR;  //DMA外设ADC基地址
        DMA_InitStructure.DMA_MemoryBaseAddr = (u32)usart2DmaRecFifoBuf;  //DMA内存基地址
        DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;  //数据传输方向,从外设读取发送到内存
        DMA_InitStructure.DMA_BufferSize = USART2_DMA_REC_FIFO_MAX_LEN;  //DMA通道的DMA缓存的大小
        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 = DMA_Mode_Circular;  //工作在循环模式
        DMA_InitStructure.DMA_Priority = DMA_Priority_Medium; //DMA通道 x拥有中优先级
        DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;  //DMA通道x没有设置为内存到内存传输
        DMA_Init(DMA1_Channel6, &DMA_InitStructure);  //根据DMA_InitStruct中指定的参数初始化DMA的通道
        DMA_Cmd(DMA1_Channel6, ENABLE);
       
        //使能USART2 DMA接收
        USART_DMACmd(USART2,USART_DMAReq_Rx,ENABLE);
       
        //使能USART2
        USART_Cmd(USART2, ENABLE);
       
        //清除发送完成标志
        USART_ClearFlag(USART2, USART_FLAG_TC);
}

void USART2_IRQHandler(void)
{       
        if(USART_GetITStatus(USART2, USART_IT_IDLE) != RESET)  //空闲中断
        {
                printf("USART2_IRQHandler\r\n");
                USART_ClearITPendingBit( USART2, USART_IT_IDLE );  //清除空闲中断
                USART_ReceiveData( USART2);  //读DR,只有读过一次,才能真正清除标志
                USART_ClearFlag( USART2, USART_FLAG_IDLE );  //读SR其实就是清除标志
        }
}
串口2DMA相关代码如图
只有发送第二次才跳到中断里面。


最佳答案

查看完整内容[请看2#楼]

[mw_shl_code=c,true]void usart2SendU8Array(u8 *buf, u16 buflen) { while(buflen)//检测字符串结束符 { while(USART_GetFlagStatus(USART2, USART_FLAG_TC)==RESET); USART_SendData(USART2 ,*buf++);//发送当前字符 buflen--; } while(USART_GetFlagStatus(USART2, USART_FLAG_TC)==RESET); }[/mw_shl_code] 这样解决了,不过还是不清楚原因。
正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

8

主题

33

帖子

0

精华

高级会员

Rank: 4

积分
872
金钱
872
注册时间
2017-8-1
在线时间
85 小时
 楼主| 发表于 2018-7-17 10:03:56 | 显示全部楼层
[mw_shl_code=c,true]void usart2SendU8Array(u8 *buf, u16 buflen)
{
        while(buflen)//检测字符串结束符
        {
                while(USART_GetFlagStatus(USART2, USART_FLAG_TC)==RESET);
                USART_SendData(USART2 ,*buf++);//发送当前字符
                buflen--;
        }
        while(USART_GetFlagStatus(USART2, USART_FLAG_TC)==RESET);
}[/mw_shl_code]
这样解决了,不过还是不清楚原因。
回复

使用道具 举报

8

主题

33

帖子

0

精华

高级会员

Rank: 4

积分
872
金钱
872
注册时间
2017-8-1
在线时间
85 小时
 楼主| 发表于 2018-7-17 11:09:39 | 显示全部楼层
[mw_shl_code=c,true]        while(1)
        {
                if(usart1RecFlag != RESET)  //串口1接收到一次数据了
                {
                        usart1RecFlag = RESET;
                        usart1RecLen = usart1RecRead();
                        printf("usart1RecLen:%d",usart1RecLen);
                        usart1SendU8Array(usart1RecBuf,usart1RecLen);
                        usart2SendU8Array(usart1RecBuf,usart1RecLen);  //把串口1接到到数据发送到串口2
                       
                }
                if(usart2RecFlag != RESET)  //串口3接收到一次数据了
                {
                        usart2RecFlag = RESET;
                        usart2RecLen = usart2RecRead();

                        usart1SendU8Array(usart2RecBuf,usart2RecLen);  //把串口3接到到数据发送到串口1
                }
        }[/mw_shl_code]
主函数是接收到串口1里面数据发送到串口2上去,要等串口1发送第二次数据才进空闲中断。
回复

使用道具 举报

8

主题

33

帖子

0

精华

高级会员

Rank: 4

积分
872
金钱
872
注册时间
2017-8-1
在线时间
85 小时
 楼主| 发表于 2018-7-17 11:11:53 | 显示全部楼层
串口1输出结果如下:usart1RecLen:3+++usart1RecLen:3+++USART2_IRQHandler
有大神知道是什么问题吗?
回复

使用道具 举报

8

主题

33

帖子

0

精华

高级会员

Rank: 4

积分
872
金钱
872
注册时间
2017-8-1
在线时间
85 小时
 楼主| 发表于 2018-7-17 11:35:58 | 显示全部楼层
[mw_shl_code=c,true]void usart2SendU8Array(u8 *buf, u16 buflen)
{
        //printf("usart2SendU8Array\r\n");
        while(buflen)//检测字符串结束符
        {
                printf("usart2SendU8Array\r\n");
                USART_SendData(USART2 ,*buf++);//发送当前字符
                while(USART_GetFlagStatus(USART2, USART_FLAG_TC)==RESET);
                buflen--;
        }
}[/mw_shl_code]
在while里面加个printf("usart2SendU8Array\r\n");就OK了,去掉又不行,请问下我这个发送代码有什么问题吗?
回复

使用道具 举报

530

主题

11万

帖子

34

精华

管理员

Rank: 12Rank: 12Rank: 12

积分
165540
金钱
165540
注册时间
2010-12-1
在线时间
2117 小时
发表于 2018-7-18 01:32:52 | 显示全部楼层
帮顶
回复

使用道具 举报

27

主题

132

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
328
金钱
328
注册时间
2018-7-20
在线时间
117 小时
发表于 2018-8-13 18:03:36 | 显示全部楼层
get√√
回复

使用道具 举报

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

本版积分规则



关闭

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

正点原子公众号

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

GMT+8, 2025-6-18 09:11

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

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