OpenEdv-开源电子网

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

写的F0的串口通过DMA中断接收发送,发送不能循环发送,接收不能接收,大家帮帮忙

[复制链接]

2

主题

5

帖子

0

精华

新手上路

积分
24
金钱
24
注册时间
2017-9-20
在线时间
4 小时
发表于 2017-9-20 11:05:45 | 显示全部楼层 |阅读模式
3金钱
具体的程序如下:#include "stm32f0xx.h"#include "bsp_usart1.h"


#define USART_TDR_Address (USART1_BASE + 0x28)
#define USART_RDR_Address (USART1_BASE + 0x24)
#define TXBUFF_SIZE   255
#define RXBUFF_SIZE   255

uint8_t Tx_Buff[TXBUFF_SIZE];
uint8_t Rx_Buff[RXBUFF_SIZE];
uint8_t Flag_Uart_Send = 0;
uint8_t Rx_Size = 0;
uint8_t rx_buff[255];

        /// 配置USART2接收中断
static void NVIC_Configuration(void)
{
                NVIC_InitTypeDef NVIC_InitStructure;

    /* Enable the DMA Interrupt */
    NVIC_InitStructure.NVIC_IRQChannel = DMA1_Channel2_3_IRQn;   // 发送DMA通道的中断配置
    NVIC_InitStructure.NVIC_IRQChannelPriority = 0x03;     // 优先级设置
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
    NVIC_Init(&NVIC_InitStructure);

    /* Enable the USART Interrupt */
    NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;     // 串口中断配置
    NVIC_InitStructure.NVIC_IRQChannelPriority =0x02;
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
    NVIC_Init(&NVIC_InitStructure);  
}

/**
  * @brief  USART3 TX DMA 配置,内存到外设(USART1->DR)
  * @param  无
  * @retval 无
  */
void USART1_DMA_Config(void)
{
                DMA_InitTypeDef DMA_InitStructure;
       
                /*开启DMA时钟*/
                RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);

///*--- LUMMOD_UART_Tx_DMA_Channel DMA Config ---*/
       
          /*关DMA通道*/
          DMA_Cmd(DMA1_Channel2, DISABLE);
       
          /*恢复缺省值*/
          DMA_DeInit(DMA1_Channel2);
       
                /*设置DMA源:串口数据寄存器地址*/
                DMA_InitStructure.DMA_PeripheralBaseAddr = USART_TDR_Address;

                /*内存地址(要传输的变量的指针)*/
                DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)Tx_Buff;

                /*方向:从内存到外设*/               
                DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST;       

                /*传输大小DMA_BufferSize=TXBUFF_SIZE*/       
                DMA_InitStructure.DMA_BufferSize = TXBUFF_SIZE;

                /*外设地址不增*/            
                DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;

                /*内存地址自增*/
                DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;       

                /*外设数据单位*/       
                DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;

                /*内存数据单位 8bit*/
                DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;         

                /*DMA模式:单次传输模式*/
                DMA_InitStructure.DMA_Mode = DMA_Mode_Normal ;         

                /*优先级:高*/       
                DMA_InitStructure.DMA_Priority = DMA_Priority_VeryHigh;  

                /*禁止内存到内存的传输        */
                DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;

                /*配置DMA1的2通道*/                  
                DMA_Init(DMA1_Channel2, &DMA_InitStructure);           
               
                /*清除DMA所有标志*/
                DMA_ClearFlag(DMA1_FLAG_GL2);      
               
                /*关闭DMA*/
                DMA_Cmd (DMA1_Channel2,DISABLE);                        
               
                /*配置DMA发送完成后产生中断*/
    DMA_ITConfig(DMA1_Channel2, DMA_IT_TC, ENABLE);   
               
/*--- LUMMOD_UART_Rx_DMA_Channel DMA Config ---*/
               
                /*关DMA通道*/
          DMA_Cmd(DMA1_Channel3, DISABLE);
          
          /*恢复缺省值*/
          DMA_DeInit(DMA1_Channel3);
       
                /*设置DMA源:串口数据寄存器地址*/
                DMA_InitStructure.DMA_PeripheralBaseAddr = USART_RDR_Address;

                /*内存地址(要传输的变量的指针)*/
                DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)Rx_Buff;

                /*方向:从外设到内存*/               
                DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;       

                /*传输大小DMA_BufferSize=RXBUFF_SIZE*/       
                DMA_InitStructure.DMA_BufferSize = RXBUFF_SIZE;

                /*外设地址不增*/            
                DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;

                /*内存地址自增*/
                DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;       

                /*外设数据单位*/       
                DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;

                /*内存数据单位 8bit*/
                DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;         

                /*DMA模式:单次传输模式*/
                DMA_InitStructure.DMA_Mode = DMA_Mode_Normal ;         

                /*优先级:高*/       
                DMA_InitStructure.DMA_Priority = DMA_Priority_VeryHigh;  

                /*禁止内存到内存的传输        */
                DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;

                /*配置DMA1的2通道*/                  
                DMA_Init(DMA1_Channel3, &DMA_InitStructure);           
               
                /*清除DMA所有标志*/
                DMA_ClearFlag(DMA1_FLAG_GL3);
               
                /*关闭DMA*/
                DMA_Cmd (DMA1_Channel3,ENABLE);                                       
}

/**
  * @brief  USART3 GPIO 配置,工作模式配置。115200 8-N-1
  * @param  无
  * @retval 无
  */
void USART1_Config(void)
{
                GPIO_InitTypeDef GPIO_InitStructure;       
    USART_InitTypeDef USART_InitStructure;  //定义串口初始化结构体
       
    RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOA, ENABLE);  //使能GPIOA的时钟
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);//使能USART的时钟

    GPIO_PinAFConfig(GPIOA, GPIO_PinSource9, GPIO_AF_1);//配置PA9成第二功能引脚        TX
    GPIO_PinAFConfig(GPIOA, GPIO_PinSource10, GPIO_AF_1);//配置PA10成第二功能引脚  RX       

    /*USART1_TX ->PA9  USART1_RX ->PA10*/               
      GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9|GPIO_Pin_10;               //选中串口默认输出管脚         
      GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;  //定义输出最大速率
      GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
      GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
      GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;//定义管脚9的模式  
      GPIO_Init(GPIOA, &GPIO_InitStructure);           //调用函数,把结构体参数输入进行初始化                  

    /*串口通讯参数设置*/
    USART_InitStructure.USART_BaudRate = 9600; //波特率
    USART_InitStructure.USART_WordLength = USART_WordLength_8b; //数据位8位
    USART_InitStructure.USART_StopBits = USART_StopBits_1;        //停止位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(USART1, &USART_InitStructure);
               
                USART1_DMA_Config();   // 串口 DMA 配置
                NVIC_Configuration();
               
                USART_ITConfig(USART1, USART_IT_IDLE, ENABLE);  // 开启 串口空闲IDEL 中断
               
                USART_DMACmd(USART1, USART_DMAReq_Tx, ENABLE);  // 开启串口DMA发送
    USART_DMACmd(USART1, USART_DMAReq_Rx, ENABLE); // 开启串口DMA接收
               
//                queueCreate(&g_SendQueue,g_SendBuffer,UART_BUF_SIZE);
//                queueCreate(&g_RecvQueue,g_RecvBuffer,UART_BUF_SIZE);
                USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);
                USART_Cmd(USART1, ENABLE);
}

void USART1_DAM_Tx_Over(void)
{
    DMA_ClearFlag(DMA1_FLAG_GL2);         // 清除标志
    DMA_Cmd(DMA1_Channel2, DISABLE);   // 关闭DMA通道
          Flag_Uart_Send = 0;
}

void Uart1Send(uint8_t *buf,uint8_t Size)
{
                uint8_t i;
          
                for(i=0;i<Size;i++)
                                {
                                        Tx_Buff[i] = buf[i];
                                }
                DMA1_Channel2->CNDTR = (uint16_t)Size; // 设置要发送的字节数目
                                USART_DMACmd(USART1, USART_DMAReq_Tx, ENABLE);
    DMA_Cmd(DMA1_Channel2, ENABLE);        //开始DMA发送       
    Flag_Uart_Send = 1;       
                                   
}

void USART1_DMA_Rx_Data(void)
{
          
          uint16_t i = 0;
         
          Rx_Size = USART1->ISR;
          Rx_Size = USART1->RDR;                    
    DMA_Cmd(DMA1_Channel3, DISABLE);         // 关闭DMA ,防止干扰
    DMA_ClearFlag(DMA1_FLAG_GL3 );           // 清DMA标志位
          
    Rx_Size = RXBUFF_SIZE - DMA_GetCurrDataCounter(DMA1_Channel3); //获得接收到的字节数
    for(i = 0;i < Rx_Size;i++)
          {
                                rx_buff[i]=Rx_Buff[i];
//        enqueue(&g_RecvQueue,Rx_Buff[i]);
                }
          DMA1_Channel3->CNDTR = RXBUFF_SIZE;    //  重新赋值计数值,必须大于等于最大可能接收到的数据帧数目
    DMA_Cmd(DMA1_Channel3, ENABLE);       //处理完在开启缓冲   
                /* DMA 开启,等待数据。注意,如果中断发送数据帧的速率很快,MCU来不及处理此次接收到的数据,中断又发来数据的话,这里不能开启,否则数据会被覆盖。有2种方式解决。
    1. 在重新开启接收DMA通道之前,将LumMod_Rx_Buf缓冲区里面的数据复制到另外一个数组中,然后再开启DMA,然后马上处理复制出来的数据。
    2. 建立双缓冲,在LumMod_Uart_DMA_Rx_Data函数中,重新配置DMA_MemoryBaseAddr 的缓冲区地址,那么下次接收到的数据就会保存到新的缓冲区中,不至于被覆盖。*/
    }
中断函数如下
void USART1_IRQHandler(void)
{
    if(USART_GetITStatus(USART1, USART_IT_IDLE) != RESET)  // 空闲中断
    {
        USART1_DMA_Rx_Data();
        USART_ReceiveData( USART1 ); // Clear IDLE interrupt flag bit
    }
}

void DMA1_Channel2_3_IRQHandler(void)
{
        /*判断是否发送完毕*/
        if(DMA_GetITStatus(DMA1_FLAG_TC2))
    {
        USART1_DAM_Tx_Over();
    }
}

现在问题是只能发送一次,就停了,接收不能接收,麻烦大家帮帮忙

最佳答案

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

使用道具 举报

530

主题

11万

帖子

34

精华

管理员

Rank: 12Rank: 12Rank: 12

积分
165540
金钱
165540
注册时间
2010-12-1
在线时间
2117 小时
发表于 2017-9-20 11:05:46 | 显示全部楼层
回复

使用道具 举报

2

主题

5

帖子

0

精华

新手上路

积分
24
金钱
24
注册时间
2017-9-20
在线时间
4 小时
 楼主| 发表于 2017-9-21 08:48:36 | 显示全部楼层

已经解决了,谢谢
回复

使用道具 举报

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

本版积分规则



关闭

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

正点原子公众号

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

GMT+8, 2025-6-18 02:23

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

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