OpenEdv-开源电子网

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

STM32F103VET6 使用DMA发送 会接收到自己发送的数据 求解

[复制链接]

4

主题

13

帖子

0

精华

初级会员

Rank: 2

积分
158
金钱
158
注册时间
2019-5-29
在线时间
48 小时
发表于 2019-11-7 10:32:59 | 显示全部楼层 |阅读模式
10金钱
STM32 使用DMA 用于2G模块得发送和接收  遇到得问题是发送AT指令后 会同时接收到相同得AT指令 实在找不到问题所在 现象:

串口打印出来得数据

串口打印出来得数据


下面是代码

/**
  ****************************************************************************
  *                                   Copyright 2019 by LZZ, All rights reserved.
  ****************************************************************************
  *@Filename :  usart3.c
  *@Author   :  LZZ
  *@Date     :  2019-10-30
  *@Version  :  V1.0
  *@Brief    :  利用Usart3 DMA空闲中断模式,接收来自终端的不定长数据并回显。
  *                            ------------------------
  *            |   PB10  - USART3(Tx)    |
  *            |   PB11  - USART3(Rx)    |
  *             ------------------------
  ****************************************************************************
  *
  */
#include "Usart3.h"
#include "math.h"
#include "string.h"
#include "2G_module.h"
Status USART3_Status;                  //串口状态
uint8_t gbUsart3TxBuf[USART3_TX_BUF_SIZE];
uint8_t gbUsart3RxBuf[USART3_RX_BUF_SIZE];
static void USART3_Config(uint32_t BaudRate);
static void USART3_DMA_Config(void);
static void USART3_NVIC_Config(void);
/**
   * @brief  串口3的初始化
   * @param  [IN] BaudRate:指明串口3的波特率
   * @retval 无
   */
void USART3_Init(uint32_t BaudRate)
{
        USART3_Config(BaudRate);
        USART3_DMA_Config();
        USART3_NVIC_Config();
}
/**
  * @brief  串口3工作模式配置:BaudRate 8-N-1
  * @param  [IN] BaudRate:指明串口3的波特率
  * @retval 无
  */
static void USART3_Config(uint32_t BaudRate)   //BaudRate 9600
{
        GPIO_InitTypeDef GPIO_InitStructure;
        USART_InitTypeDef USART_InitStructure;
       
        RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART3, ENABLE);
        RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);
       
        //USART3 Tx(PB10)复用推挽输出
        GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
        GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
        GPIO_Init(GPIOB, &GPIO_InitStructure);
            
        // USART3 Rx(PB11) 浮空输入
        GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11;
        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
        GPIO_Init(GPIOB, &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_Init(USART3, &USART_InitStructure);
       
        // 仅打开空闲接收中断
        USART_ITConfig(USART3,USART_IT_TC,DISABLE);
        USART_ITConfig(USART3,USART_IT_RXNE,DISABLE);                               
        USART_ITConfig(USART3,USART_IT_IDLE,ENABLE);         
        // 串口模块使能          
        USART_Cmd(USART3, ENABLE);                                              
}
/**
  * @brief  串口3 DMA模式配置
  * @param  无
  * @retval 无
  */
static void USART3_DMA_Config(void)
{
        DMA_InitTypeDef DMA_InitStructure;
       
        RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);
                               
        // 配置DMA1通道12:由串口3发送事件触发
        DMA_DeInit(DMA1_Channel2);  
        DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)(&USART3->DR);           //定义 DMA 外设基地址
        DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)gbUsart3TxBuf;                    //定义 DMA 内存基地址
        DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST;                                 //外设作为数据传输的内部
        DMA_InitStructure.DMA_BufferSize = USART3_TX_BUF_SIZE;                        //定义指定 DMA 通道的 DMA 缓存的大小
        DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;             //外设地址寄存器不变
        DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;                                    //
        DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;
        DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;
        DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;                                             //工作正常模式
        DMA_InitStructure.DMA_Priority = DMA_Priority_VeryHigh;
        DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;
       
        DMA_Init(DMA1_Channel2, &DMA_InitStructure);
        // 传输完成中断       
        DMA_ITConfig(DMA1_Channel2, DMA_IT_TC, DISABLE);   
        // 传输错误中断
        DMA_ITConfig(DMA1_Channel2, DMA_IT_TE, DISABLE);          
        // 发送DMA请求
        USART_DMACmd(USART3, USART_DMAReq_Tx, ENABLE);         
        /*关闭DMA1通道2*/
        DMA_Cmd(DMA1_Channel2, DISABLE);
        /*设置通道的缓冲区大小*/
        DMA_SetCurrDataCounter(DMA1_Channel2,USART3_TX_BUF_SIZE);       
        /*使能DMA*/
        DMA_Cmd(DMA1_Channel2, ENABLE);

        // 配置DMA1通道13:由串口3接收事件触发
        DMA_DeInit(DMA1_Channel3);       
        DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)&USART3->DR;
        DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)gbUsart3RxBuf;
        DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;                                            /*从内存到外设*/
        DMA_InitStructure.DMA_BufferSize = USART3_RX_BUF_SIZE;
        DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;        //外设地址寄存器不变
        DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;                                       
        DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;
        DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;
        DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;
        DMA_InitStructure.DMA_Priority = DMA_Priority_VeryHigh;
        DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;
        DMA_Init(DMA1_Channel3, &DMA_InitStructure);
        // 传输完成中断
        DMA_ITConfig(DMA1_Channel3, DMA_IT_TC, DISABLE);          
        // 传输错误中断         
        DMA_ITConfig(DMA1_Channel3, DMA_IT_TE, DISABLE);       
        // 接收DMA请求
        USART_DMACmd(USART3,USART_DMAReq_Rx,ENABLE);
        /*关闭DMA1通道3*/
        DMA_Cmd(DMA1_Channel3, DISABLE);
        /*设置通道的缓冲区大小*/
        DMA_SetCurrDataCounter(DMA1_Channel3,USART3_RX_BUF_SIZE);
        // 使能DMA1通道13
        DMA_Cmd(DMA1_Channel3, ENABLE);
}
/**
  * @brief  配置串口中断优先级
  * @param  无
  * @retval 无
  */
static void USART3_NVIC_Config(void)
{
        NVIC_InitTypeDef NVIC_InitStructure;
        NVIC_InitStructure.NVIC_IRQChannel = USART3_IRQn;               
        NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;   
        NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;               
        /*必须打开中断通道使能*/
        NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
        NVIC_Init(&NVIC_InitStructure);     
}
void USART3_IRQHandler(void)
{
        u8 Size;
        u8 re_buff[256];
        u8 i;
    if (USART_GetITStatus( USART3, USART_IT_IDLE ) != RESET )           //串口空闲中断 用于DMA        
    {
                USART_ClearITPendingBit(USART3, USART_IT_IDLE );  //清除空闲中断
                Size=USART_ReceiveData(USART3);    //读DR,只有读过一次,才能真正清除标志
                USART_ClearFlag( USART3, USART_FLAG_IDLE );             //读SR其实就是清除标志
                DMA_Cmd(DMA1_Channel3, DISABLE);                                        //先停止DMA才行设置缓冲区大小
                Size=USART3_RX_BUF_SIZE-DMA_GetCurrDataCounter(DMA1_Channel3);  //size=设置的大小-剩余待传输的数据大小
                printf("%s\r\n",gbUsart3RxBuf);
                /*若发送数据需要检测*/
                if(USART3_Status.DMA_IsSending==1)
                {
                        /*判断是否是MQTT服务器接收数据包数据*/
                        if(strstr((char*)gbUsart3RxBuf,"QMTRECV"))
                        {
                                        USART3_Status.DMA_ReceiveOK=1;
                                        //数据处理
                        }
                        else
                        {
                                        /*接收到数据并且检测数据是否与期待接收的数据一样*/
                                        if(Module_2G_check_cmd(gbUsart3RxBuf,Expected_response))
                                        {
                                                /*接收到期待的数据 释放*/
                                                USART3_Status.DMA_IsSending=0;
                                                USART3_Status.DMA_SendOK=1;
                                        }
                        }
                }
                /*若数据不需要检测*/
                else
                {
                        //把数据填进FIFO数据缓冲区
                        USART3_Status.DMA_ReceiveOK=1;
                        if(strstr((char*)gbUsart3RxBuf,"QMTRECV"))
                        {
                                re_buff[0]=*(strstr((char*)gbUsart3RxBuf,"+QMTRECV:")+9);
                                re_buff[1]=*(strstr((char*)gbUsart3RxBuf,"+QMTRECV:")+65);
                                for(i=0;i<re_buff[1];i++)
                                {
                                        re_buff=*(strstr((char*)gbUsart3RxBuf,"+QMTRECV:")+64+i);
                                        printf("re_buff[1]=%x",re_buff[1]);
                                }
                                        printf("\r\n");
                                /*校验*/
                                if(module_2G_instruction_verification(re_buff,re_buff[1])==re_buff[re_buff[1]-1])
                                {
                                                //若校验正确则进入
                                                printf("check OK\r\n");
                                       
                                }else
                                {
                                                printf("check CMD error\r\n");
                                }
                        }
                }
                //清空DMA数据缓冲区
                memset(gbUsart3RxBuf,0,USART3_RX_BUF_SIZE);
                DMA_SetCurrDataCounter(DMA1_Channel3, USART3_RX_BUF_SIZE);   //重新设置DMA的读取缓冲区长度   DMA_USART3_Recieve_Buff[USART3_TX_BUF_SIZE]
                DMA_Cmd(DMA1_Channel3, ENABLE);  //开启DMA   
        }
}

/**
  * @brief  发送若干字节数据
  * @param  [IN] pDataBuf:  指向待发送数据区
  *         [IN] LenOfData: 指明待发送字节数据长度
  * @retval 无
  */
void USART3_SendBuffer(uint8_t *pDataBuf, uint16_t LenOfData)
{
        uint16_t Count;
       
        for (Count=0; Count<LenOfData; Count++)
        {
                USART_SendData(USART3, pDataBuf[Count]);
                while(!USART_GetFlagStatus(USART3, USART_FLAG_TXE));
        }
}


/*=========发送端数据处理===============*/
/**
* @ Function Name : dma_usart_tx_restart
* @ Author        : hlb
* @ Brief         : 重启串口的dma
* @ Date          : 2019.10.30
* @ Input         : u8 *res                 发送的数据  字符串
                    u32 size            传输数据的长度
* @ Modify        : ...
**/
void dma_usart_tx_restart(u8 *res,u32 size)
{
    // 禁用DMA
    DMA_Cmd(DMA1_Channel2, DISABLE);

    // 设置DMA的传输值
    DMA1_Channel2 -> CNDTR = size;

    // 设置传输数据
    DMA1_Channel2 -> CMAR  = (u32)res;
       
    // 启动DMA
    DMA_Cmd(DMA1_Channel2, ENABLE);
}
/**
* @ Function Name : dma_usart_tx
* @ Author        : hlb
* @ Brief         : 串口DMA发送函数
* @ Date          : 2019.10.30
* @ Input         : u8* buff       待发送数组头指针 字符串
*                   u32 size       待发送数组大小
* @ Modify        : ...
**/
void dma_usart_tx(u8 *buff, u32 size)
{
    // 清除TC标志
    USART_ClearFlag(USART3, USART_FLAG_TC);

    //重启DMA发送
    dma_usart_tx_restart(buff, size);
}






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

使用道具 举报

12

主题

146

帖子

0

精华

高级会员

Rank: 4

积分
922
金钱
922
注册时间
2018-7-18
在线时间
385 小时
发表于 2019-11-7 10:50:43 | 显示全部楼层
这个应该是模块的指令回显   可以关掉的!
回复

使用道具 举报

4

主题

13

帖子

0

精华

初级会员

Rank: 2

积分
158
金钱
158
注册时间
2019-5-29
在线时间
48 小时
 楼主| 发表于 2019-11-7 11:23:00 | 显示全部楼层
wwhh 发表于 2019-11-7 10:50
这个应该是模块的指令回显   可以关掉的!

我接串口助手不会得 ,就是接了板子之后才会出现
回复

使用道具 举报

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

本版积分规则



关闭

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

正点原子公众号

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

GMT+8, 2025-5-28 01:38

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

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