张三-2046160 发表于 2019-5-27 18:22:16

USART3 用DMA发送只能发送一次,是什么问题呢?

单片机STM32F103R8T6,环境IAR8.22
请各位大神帮忙看下:

/*******************************************************************************
* Function Name: void USART3_Init(u32 baud)
* Description    : 初始化USART2    TX:PA2RX:PA3
* Input          : 无
* Output         : 无
* Return         : 无
*******************************************************************************/
void USART3_Init(u32 baud)
{
GPIO_InitTypeDef GPIO_InitStructure;   //定义结构体
USART_InitTypeDef USART_InitStructure; //定义结构体
//NVIC_InitTypeDef NVIC_InitStruct;

// 第1步:打开GPIO和USART部件的时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB | RCC_APB2Periph_AFIO, ENABLE);//打开PIOA口的时钟
RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART3, ENABLE); //打开UART_3的时钟

// 第2步:将USART Tx的GPIO(PB10)配置为推挽复用模式
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //配置PB口时钟
GPIO_Init(GPIOB, &GPIO_InitStructure);

//第3步:将USART Rx的GPIO配置为浮空输入模式
//将USART Rx的GPIO(PB11)配置为浮空输入模式
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
GPIO_Init(GPIOB, &GPIO_InitStructure);

GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //配置PB口时钟
GPIO_Init(GPIOB, &GPIO_InitStructure);


//第4步:配置USART参数

USART_InitStructure.USART_BaudRate =baud;//设置波特率4800、9600、19200、38400、115200
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(USART3, &USART_InitStructure);    // 串口3初始化


//USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);// 开启 USART 接收缓冲区非空中断
//USART_ITConfig(USART1, USART_IT_TXE, ENABLE);   // 开启 USART 发送缓冲区空中断

USART_ITConfig(USART3, USART_IT_IDLE, ENABLE);//开启 USART1 总线空闲中断


//第5步:使能 USART, 配置完毕
USART_Cmd(USART3, ENABLE);//使能或失能USART
USART_ClearFlag(USART3, USART_FLAG_TC);   //清除发送完成标志
USART3_DMA_TxConfig();
}


void USART3_DMA_TxConfig(void)
{
DMA_InitTypeDef DMA_InitStruct;

/*开启DMA时钟*/
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);

DMA_Cmd(DMA1_Channel2,DISABLE);                                     //close DMA Channel

DMA_DeInit(DMA1_Channel2);

/*设置DMA源:串口数据寄存器地址*/
DMA_InitStruct.DMA_PeripheralBaseAddr = (uint32_t)(&USART3->DR);    //内存--->外设

/*内存地址(要传输的变量的指针)*/
DMA_InitStruct.DMA_MemoryBaseAddr = (u32)uart3.sendBuf;

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

/*传输大小DMA_BufferSize=SENDBUFF_SIZE*/
DMA_InitStruct.DMA_BufferSize = uart3.sendLen;

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

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

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

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

/*DMA模式:不断循环*/
DMA_InitStruct.DMA_Mode = DMA_Mode_Normal ;
//DMA_InitStruct.DMA_Mode = DMA_Mode_Circular;

/*优先级:中*/
DMA_InitStruct.DMA_Priority = DMA_Priority_Medium;

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


/*配置DMA1的2通道*/   
DMA_Init(DMA1_Channel2, &DMA_InitStruct);

DMA_ClearFlag(DMA1_FLAG_GL4);

//DMA_ITConfig(DMA1_Channel2,DMA_IT_TC,ENABLE);//配置DMA发送完成后产生中断
DMA_ITConfig(DMA1_Channel2,DMA_IT_TC,ENABLE);//open DMA send inttrupt
/*使能DMA*/
//DMA_Cmd (DMA1_Channel2,ENABLE);

USART_DMACmd(USART3, USART_DMAReq_Tx, ENABLE);

}


//下面是调试函数,每500ms调用一次,执行一次发送
int debug = 0;
void USART3_DealRev(void)
{
static long t=0;

t++;
if(t>2)
{
    debug = 2;
    t = 0;
}
if(debug == 1)
{
    for(int i= 0; i<50; i++)
      uart3.sendBuf = i+1;
    uart3.sendLen = 50;
   
    USART3_SendData((unsigned char *)uart3.sendBuf,uart3.sendLen );
    uart3.sendLen = 0;
    debug = 0;
}
else if(debug == 2)
{
    for(int i= 0; i<50; i++)
      uart3.sendBuf = i+1;
    DMA_SetCurrDataCounter(DMA1_Channel2, 50);
    DMA_Cmd (DMA1_Channel2,ENABLE);
    debug = 0;   
}
}

//中断函数一直不进入
void DMA1_Channel2_IRQHandler(void)
{
if(DMA_GetITStatus(DMA1_IT_TC1))
{
    uart3.sendLen = 0;
    DMA_ClearITPendingBit(DMA1_IT_GL1); //清除全部中断标志
    DMA_Cmd(DMA1_Channel2, DISABLE);          //处理完,重开DMA
}
}





edmundlee 发表于 2019-5-27 23:50:34

DMA_Cmd(DMA1_Channel2, DISABLE);          //处理完,重开DMA
你这是重开?
页: [1]
查看完整版本: USART3 用DMA发送只能发送一次,是什么问题呢?