初级会员

- 积分
- 158
- 金钱
- 158
- 注册时间
- 2019-5-29
- 在线时间
- 48 小时
|
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);
}
|
|