OpenEdv-开源电子网

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

STM32F103RCT6 一直在USART2中断里出不来

[复制链接]

5

主题

20

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
281
金钱
281
注册时间
2018-5-28
在线时间
32 小时
发表于 2018-7-21 16:24:18 | 显示全部楼层 |阅读模式
1金钱
使用STM32F103RCT6的USART2和DMA处理串口数据。我是这么想的,发送和接收均使用MDA。
代码如下:

USART2 初始化代码
[mw_shl_code=applescript,true]void Uart2_Init(u32 BaudRate)
{
         GPIO_InitTypeDef GPIO_InitStructure;
         USART_InitTypeDef USART_InitStructure;
        NVIC_InitTypeDef NVIC_InitStructure;
         DMA_InitTypeDef DMA_InitStruct;
       
    //串口配置
         RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOA, ENABLE); // 使能PB端口时钟  
    RCC_APB1PeriphClockCmd( RCC_APB1Periph_USART2, ENABLE); // 使能PB端口时钟  

    //PA.2,Tx Pin
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
    GPIO_Init(GPIOA, &GPIO_InitStructure);
    //PA.3,Rx Pin
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
    GPIO_Init(GPIOA, &GPIO_InitStructure);

    //串口参数配置
    USART_InitStructure.USART_BaudRate = BaudRate;
    USART_InitStructure.USART_WordLength = USART_WordLength_8b;
    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_ITConfig(USART2, USART_IT_IDLE, ENABLE);
    /* Configure USART1 */
    USART_Init(USART2, &USART_InitStructure);

    /* Enable the USART1 */
    USART_Cmd(USART2, ENABLE);



    //DMA 配置
    USART_DMACmd(USART2, USART_DMAReq_Tx, ENABLE);
    /* Enable USART2 DMA TX request */
    RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);

    DMA_DeInit(DMA1_Channel7);
    DMA_InitStruct.DMA_PeripheralBaseAddr = (uint32_t)(&USART2->DR);
    DMA_InitStruct.DMA_MemoryBaseAddr     = (uint32_t)USART2_DMA_TX_Buf;
    DMA_InitStruct.DMA_DIR                = DMA_DIR_PeripheralDST;
    DMA_InitStruct.DMA_BufferSize         = 0;
    DMA_InitStruct.DMA_PeripheralInc      = DMA_PeripheralInc_Disable;
    DMA_InitStruct.DMA_MemoryInc          = DMA_MemoryInc_Enable;
    DMA_InitStruct.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;
    DMA_InitStruct.DMA_MemoryDataSize     = DMA_MemoryDataSize_Byte;
    DMA_InitStruct.DMA_Mode               = DMA_Mode_Normal;
    DMA_InitStruct.DMA_Priority           = DMA_Priority_VeryHigh;
    DMA_InitStruct.DMA_M2M                = DMA_M2M_Disable;
    DMA_Init(DMA1_Channel7, &DMA_InitStruct);
    DMA_ITConfig(DMA1_Channel7, DMA_IT_TC, ENABLE);
   

    //DMA接收
   
      DMA_ITConfig(DMA1_Channel6,DMA_IT_TC,ENABLE);
  
      DMA_Cmd(DMA1_Channel6,DISABLE);
  
     DMA_InitStruct.DMA_PeripheralBaseAddr = (Uint32)(&USART2->DR);
     DMA_InitStruct.DMA_MemoryBaseAddr = (Uint32)&USART2_DMA_RX_Buf[0];
     DMA_InitStruct.DMA_DIR = DMA_DIR_PeripheralSRC;
     DMA_InitStruct.DMA_BufferSize = USART2_DMARx_LEN;
     DMA_InitStruct.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
     DMA_InitStruct.DMA_MemoryInc = DMA_MemoryInc_Enable;
     DMA_InitStruct.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;
     DMA_InitStruct.DMA_MemoryDataSize = DMA_PeripheralDataSize_Byte;
     DMA_InitStruct.DMA_Mode = DMA_Mode_Normal;
     DMA_InitStruct.DMA_Priority = DMA_Priority_VeryHigh;
     DMA_InitStruct.DMA_M2M = DMA_M2M_Disable;
     DMA_Init(DMA1_Channel6,&DMA_InitStruct);
  
    //启动DMA接收通道
     DMA_Cmd(DMA1_Channel6,ENABLE);
     USART_DMACmd(USART2, USART_DMAReq_Rx,ENABLE);
        
        //    //串口中断配置
    NVIC_InitStructure.NVIC_IRQChannel = USART2_IRQn;
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority =8;
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
    NVIC_Init(&NVIC_InitStructure);


    // Enable USART2 DMA TX Finish Interrupt
    NVIC_InitStructure.NVIC_IRQChannel = DMA1_Channel7_IRQn;
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 7;
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
    NVIC_Init(&NVIC_InitStructure);




}[/mw_shl_code]

发送数据部分代码
[mw_shl_code=applescript,true]void USART2_Data_Send(uint16_t len)
{
    DMA1_Channel7->CMAR  = (uint32_t)&USART2_DMA_TX_Buf[0];
    DMA1_Channel7->CNDTR = len;
    DMA_Cmd(DMA1_Channel7, ENABLE);

}[/mw_shl_code]
DMA发送完成中断
[mw_shl_code=applescript,true]void DMA1_Channel7_IRQHandler(void)
{
  if(DMA_GetITStatus(DMA1_IT_TC7))
  {
    // USART2 DMA 传输完成
    DMA_ClearITPendingBit(DMA1_IT_TC7);
    DMA_Cmd(DMA1_Channel7, DISABLE);
    // Enable USART2 Transmit complete interrupt
    USART_ITConfig(USART2, USART_IT_TC, ENABLE);
  }
}[/mw_shl_code]

USART2 接收完成中断
[mw_shl_code=applescript,true]void USART2_IRQHandler(void)
{
    Uint8 Temp;
      
    /****************DMA串口空闲中断后读取数据*************************/
    if(USART_GetITStatus(USART2, USART_IT_IDLE) != RESET)
    {
        USART_ClearFlag(USART2, USART_IT_IDLE);   
        
        Temp  = USART2->SR;
        Temp  = USART2->DR;
        DMA_Cmd(DMA1_Channel6,DISABLE);        //关闭DMA
        Temp = 64 - DMA_GetCurrDataCounter(DMA1_Channel6);    //获取数据长度
        //读取数据
        DMA1_Channel6->CNDTR = 64;//重装填,并让接收地址偏址从0开始
        DMA_Cmd(DMA1_Channel6,ENABLE);        //重新打开DMA
      
       // WriteBufferFIFO((struct UART_Struct *)&UART3Buffer.RxInterval,UART3DMABuffer,Temp);   
      //  UART3Buffer.RevFlag = 1;
    }

}

[/mw_shl_code]

我的思路是发送和接收都是用DMA。其中接收部分使用USART的接收中断,当接收完一帧数据后触发中断,把数据读出来。
现在的问题是接收部分和发送部分的中断只使能一个的时候可以正常,可以正常发送或者正常接收。但是两个中断同时使能时就无法发送了,测试的时候用的是延时发送,每0.5s发送一次
经过仿真发现使能串口接收中断后重新一直在中断里面执行,根本执行不到发送部分的函数,因为不能正常发送。关于串口的中断我也用过很多次了,感觉中断配置上没有啥问题,可是问题应该就是在中断配置上,希望大神给看一下哪儿出了问题。

最佳答案

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

1,dma发送,参考我们标准例程。 2, DMA接收,参考:http://www.openedv.com/forum.php?mod=viewthread&tid=63849&highlight=DMA%2B%B4%AE%BF%DA%2B%BD%D3%CA%D5 论坛好多帖子,学会自己搜索。
正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

530

主题

11万

帖子

34

精华

管理员

Rank: 12Rank: 12Rank: 12

积分
165540
金钱
165540
注册时间
2010-12-1
在线时间
2117 小时
发表于 2018-7-21 16:24:19 | 显示全部楼层
1,dma发送,参考我们标准例程。
2, DMA接收,参考:http://www.openedv.com/forum.php ... F%DA%2B%BD%D3%CA%D5
论坛好多帖子,学会自己搜索。
我是开源电子网www.openedv.com站长,有关站务问题请与我联系。
正点原子STM32开发板购买店铺http://openedv.taobao.com
正点原子官方微信公众平台,点击这里关注“正点原子”
回复

使用道具 举报

5

主题

20

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
281
金钱
281
注册时间
2018-5-28
在线时间
32 小时
 楼主| 发表于 2018-7-21 21:51:38 | 显示全部楼层
正点原子 发表于 2018-7-21 16:24
1,dma发送,参考我们标准例程。
2, DMA接收,参考:http://www.openedv.com/forum.php?mod=viewthread&t ...

谢谢原子哥
回复

使用道具 举报

5

主题

20

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
281
金钱
281
注册时间
2018-5-28
在线时间
32 小时
 楼主| 发表于 2018-7-21 22:14:03 | 显示全部楼层

看了原子哥推荐的帖子,说实话,没有找到原因哦。
不过通过对比分析出了自己代码里的问题。问题是下面这个函数
[mw_shl_code=applescript,true]void USART2_Data_Send(uint16_t len)
{
    DMA1_Channel7->CMAR  = (uint32_t)&USART2_DMA_TX_Buf[0];
    DMA1_Channel7->CNDTR = len;
    DMA_Cmd(DMA1_Channel7, ENABLE);

}[/mw_shl_code]

其中 DMA_Cmd(DMA1_Channel7, ENABLE);是不需要的。这一句是在移植别人的代码的时候没有注意而留下来的。把这一句去掉就正常了。
回复

使用道具 举报

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

本版积分规则



关闭

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

正点原子公众号

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

GMT+8, 2025-6-20 01:03

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

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