STM32
直播中

梅利号

8年用户 1474经验值
擅长:可编程逻辑
私信 关注
[问答]

如何去实现STM32F10X UART1开启DMA时钟的设计呢

如何去实现STM32F10X UART1开启DMA时钟的设计呢?

回帖(2)

王文娥

2021-12-8 11:54:28
UART1.c

/********************************************************************************************
*                                                变                        量                        声                        明                                          *
*********************************************************************************************/
Stu_USART1_INFO     Usart1_Info;

/********************************************************************************************
*                                                函                        数                        声                        明                                          *
*********************************************************************************************/
unsigned int CirclePosition( unsigned int position, unsigned int length )
{
    if( position >= length )
        position -= length;
   
    return position;
}
/********************************************************************************
*       函 数   名      :   Usart1_ParameterInit                                 *
*       功 能   说  明  :   UART1通信参数初始化                                 *
*       形      参      :   baudrate:波特率                                     *
*       形      参      :   parity:奇偶校验                                     *
*       形      参      :   databits:数据位                                     *
*       形      参      :   stopbits:停止位                                     *
*       返  回  值      :   无                                                  *
*********************************************************************************/
void Usart1_ParameterInit(unsigned int baudrate,unsigned char parity,unsigned int databits,unsigned int stopbits )
{
    unsigned int i;
   
    Usart1_Info.Baudrate = baudrate;

    if( parity == 'N' )
    {
        Usart1_Info.Parity = USART_Parity_No;                        
    }
    else if ( parity == 'E' )
    {
        Usart1_Info.Parity = USART_Parity_Even;                        
    }
    else
    {
        Usart1_Info.Parity = USART_Parity_Odd;                          
    }

    if( databits == 8 )
    {
        Usart1_Info.DataBit = USART_WordLength_8b;                  
    }
    else
    {
        Usart1_Info.DataBit = USART_WordLength_9b;                  
    }

    if( stopbits == 1 )
    {
        Usart1_Info.StopBit = USART_StopBits_1;                     
    }
    else
    {
        Usart1_Info.StopBit = USART_StopBits_2;                    
    }
   
    Usart1_Info.RxIndex = 0;
    Usart1_Info.RxHead = 0;
    Usart1_Info.RxLength =0;
   
    Usart1_Info.TxIndex = 0;
    Usart1_Info.TxTail = 0;
    Usart1_Info.TxLength = 0;
    Usart1_Info.TxDMABusy = USART1_DMA_IDLE;
   
    for( i=0;i     {
        Usart1_Info.RxBuf = 0x00;
        Usart1_Info.TxBuf = 0x00;
        Usart1_Info.TxDMABuf = 0x00;
    }   
   
    Usart1_Info.PreRxDMACounter = USART1_BUFLENGTH;
    Usart1_Info.OverTime =0;
}

/********************************************************************************
*       函 数   名      :   Usart1_HardwareInit                                 *
*       功 能   说  明  :   Usart1硬件初始化                                    *
*       形      参      :   无                                                  *
*       返  回  值      :   无                                                  *
*********************************************************************************/
void Usart1_HardwareInit(void)
{
    NVIC_InitTypeDef  NVIC_InitStructure;                       //中断向量初始化结构体
    GPIO_InitTypeDef  GPIO_InitStructure;                       //GPIO初始化结构体
    USART_InitTypeDef USART_InitStructure;                      //USART初始化结构体

    // Configure the NVIC Preemption Priority Bits
    NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);             //设置优先级组
    NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;           //USART1全局中断
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;   //抢占优先级0
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;          //响应优先级2
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;             //使能中断
    NVIC_Init( &NVIC_InitStructure );

    //使能串口时钟: USART1对应APB1
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);      //使能USART1时钟
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_AFIO, ENABLE);//使能GPIOA时钟(设置TX/RX引脚)与复用时钟

    //USART1发送引脚配置
    GPIO_InitStructure.GPIO_Pin = USART1_TX_PIN;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(USART1_TX_PORT, &GPIO_InitStructure);

    //USART1接收引脚配置
    GPIO_InitStructure.GPIO_Pin = USART1_RX_PIN;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
    GPIO_Init(USART1_RX_PORT, &GPIO_InitStructure);

    //USART1参数设置
    USART_InitStructure.USART_BaudRate = Usart1_Info.Baudrate;
    USART_InitStructure.USART_Parity = Usart1_Info.Parity ;
    USART_InitStructure.USART_WordLength = Usart1_Info.DataBit;
    USART_InitStructure.USART_StopBits = Usart1_Info.StopBit;
    USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
    USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
    USART_Init(USART1, &USART_InitStructure);
    USART1->BRR = 0x271;

    //串口空闲中断(DMA模式)
    USART_ITConfig(USART1,USART_IT_IDLE,ENABLE);                                

    //启用 USART1
    USART_Cmd(USART1, ENABLE);

   
    USART_ClearFlag(USART1, USART_FLAG_TC);
   
}

/********************************************************************************
*       函 数   名      :   Usart1_DMAInit                                      *
*       功 能   说  明  :   Usart1DMA初始化                                     *
*       形      参      :   无                                                  *
*       返  回  值      :   无                                                  *
*********************************************************************************/
void Usart1_DMAInit(void)
{
    NVIC_InitTypeDef NVIC_InitStructure;
    DMA_InitTypeDef  DMA_Initstructure;

    // Configure the NVIC Preemption Priority Bits配置引脚优先级
    NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
    NVIC_InitStructure.NVIC_IRQChannel = DMA1_Channel4_IRQn;
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3;
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
    NVIC_Init( &NVIC_InitStructure );

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

陈斌

2021-12-8 11:54:31
//发送DMA配置
    DMA_Cmd(DMA_USART1_TX_CHANNEL, DISABLE);                                    // 关DMA通道
    DMA_DeInit(DMA_USART1_TX_CHANNEL);                                          // 恢复缺省值
    DMA_Initstructure.DMA_PeripheralBaseAddr =(unsigned int)(&USART1->DR);      // 设置串口接收数据寄存器     
    DMA_Initstructure.DMA_MemoryBaseAddr = (unsigned int)Usart1_Info.TxDMABuf;  // 设置发送缓冲区首地址
    DMA_Initstructure.DMA_DIR = DMA_DIR_PeripheralDST;                          // 设置外设为目的地址,内存缓冲区 ->外设寄存器
    DMA_Initstructure.DMA_BufferSize = USART1_BUFLENGTH;                        // 需要最大可能接收到的字节数
    DMA_Initstructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;            // 外设地址不做增加调整,调整不调整是DMA自动实现的
    DMA_Initstructure.DMA_MemoryInc =DMA_MemoryInc_Enable;                      // 内存缓冲区地址增加调整
    DMA_Initstructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;     // 外设数据宽度8位,1个字节
    DMA_Initstructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;             // 内存数据宽度8位,1个字节
    DMA_Initstructure.DMA_Mode = DMA_Mode_Normal;                               // 循环传输模式:DMA_Mode_Circular; 单次传输模式DMA_Mode_Normal;
    DMA_Initstructure.DMA_Priority = DMA_Priority_High;                         // 优先级设置,设置为高
    DMA_Initstructure.DMA_M2M = DMA_M2M_Disable;

    //启动发送DMA
    DMA_Init(DMA_USART1_TX_CHANNEL,&DMA_Initstructure);                         // 开启接收DMA通道,等待接收数据

    // 开启发送DMA通道中断
    DMA_ITConfig(DMA_USART1_TX_CHANNEL, DMA_IT_TC, ENABLE);                     //DMA_IT_TC传输完成中断(transfer complete)
    DMA_ITConfig(DMA_USART1_TX_CHANNEL, DMA_IT_TE, ENABLE);                     //DMA_IT_TE传输错误中断(transfer error)
   
    DMA_ClearFlag(DMA_USART1_TX_FLAG);                                          // 清除DMA所有标志

    DMA_Cmd(DMA_USART1_TX_CHANNEL,DISABLE);                                      //启用DMA通道

    //接收DMA配置
    DMA_Cmd(DMA_USART1_RX_CHANNEL,DISABLE);                                     //关DMA通道
    DMA_DeInit(DMA_USART1_RX_CHANNEL);
    DMA_Initstructure.DMA_PeripheralBaseAddr =(unsigned int)(&USART1->DR);      // 设置串口接收数据寄存器     
    DMA_Initstructure.DMA_MemoryBaseAddr = (unsigned int)Usart1_Info.RxBuf;     // 设置发送缓冲区首地址
    DMA_Initstructure.DMA_DIR = DMA_DIR_PeripheralSRC;                          // 设置外设为数据源,外设寄存器 ->内存缓冲区
    DMA_Initstructure.DMA_BufferSize = USART1_BUFLENGTH;                        // 需要最大可能接收到的字节数
    DMA_Initstructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;            // 外设地址不做增加调整,调整不调整是DMA自动实现的
    DMA_Initstructure.DMA_MemoryInc =DMA_MemoryInc_Enable;                      // 内存缓冲区地址增加调整
    DMA_Initstructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;     // 外设数据宽度8位,1个字节
    DMA_Initstructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;             // 内存数据宽度8位,1个字节
    DMA_Initstructure.DMA_Mode = DMA_Mode_Circular;                             // 循环传输模式:DMA_Mode_Circular; 单次传输模式DMA_Mode_Normal;
    DMA_Initstructure.DMA_Priority = DMA_Priority_High;                         // 优先级设置,设置为高
    DMA_Initstructure.DMA_M2M = DMA_M2M_Disable;                                //关闭存储器到存储器传输模式

    //开启接收DMA通道
    DMA_Init(DMA_USART1_RX_CHANNEL,&DMA_Initstructure);
   
    DMA_ITConfig(DMA_USART1_RX_CHANNEL,DMA_IT_TC,ENABLE);
    DMA_ITConfig(DMA_USART1_RX_CHANNEL,DMA_IT_TE,ENABLE);

    DMA_ClearFlag(DMA_USART1_RX_FLAG);

    DMA_Cmd(DMA_USART1_RX_CHANNEL,ENABLE);
   
    //开启USART1的DMA模式
    USART_DMACmd(USART1,USART_DMAReq_Rx|USART_DMAReq_Tx,ENABLE);

}

/********************************************************************************
*       函 数   名      :   Usart1_SendtoTXbuf                                  *
*       功 能   说  明  :   Usart1发送数据到TX缓存区                            *
*       形      参      :   data:待发送数据首地址                               *
*                           length:待发送数据长度
*       返  回  值      :   无                                                  *
*********************************************************************************/
void Usart1_SendtoTXbuf( unsigned char *data, unsigned int length )
{
    unsigned int i;

    if( length )
    {
        for( i=0;i         {
            Usart1_Info.TxLength++;
            Usart1_Info.TxBuf[Usart1_Info.TxTail++]= data;                     //循环缓冲区装载数据
            if( Usart1_Info.TxTail >= USART1_BUFLENGTH )
            {
                Usart1_Info.TxTail -= USART1_BUFLENGTH;
            }
        }
    }
}

/********************************************************************************
*       函 数   名      :   Usart1_SendtoTXDMAbuf                               *
*       功 能   说  明  :   Usart1发送数据到TX缓存区                            *
*       形      参      :   无                                                  *
*       返  回  值      :   无                                                  *
*********************************************************************************/
void Usart1_SendtoTXDMAbuf( void )
{
    unsigned int i;
   
    if( Usart1_Info.TxLength && ( Usart1_Info.TxDMABusy == USART1_DMA_IDLE ) )
    {
        //有数据发送,往DMA缓冲区转移
        for( i=0; i         {
            Usart1_Info.TxDMABuf = Usart1_Info.TxBuf[Usart1_Info.TxIndex++];
            Usart1_Info.TxIndex = CirclePosition( Usart1_Info.TxIndex, USART1_BUFLENGTH );
        }
        
        //启动DMA数据发送
        DMA_SetCurrDataCounter(DMA_USART1_TX_CHANNEL,Usart1_Info.TxLength);
        Usart1_Info.TxLength = 0x00;
        Usart1_Info.TxDMABusy = USART1_DMA_BUSY;
        DMA_Cmd(DMA_USART1_TX_CHANNEL, ENABLE);
    }
}

/********************************************************************************
*       函 数   名      :   USART1_IRQHandler                                   *
*       功 能   说  明  :   Usart1中断处理函数                                  *
*       形      参      :   无                                                  *
*       返  回  值      :   无                                                  *
*********************************************************************************/
void USART1_IRQHandler(void)
{
   //DMA模式
    unsigned int num;
    unsigned int Length;
   
    //DMA_GetCurrDataCounter
    if( USART_GetITStatus( USART1,USART_IT_IDLE ) == SET )                      //整帧接收完成中断
    {
       DMA_Cmd(DMA_USART1_RX_CHANNEL,DISABLE);                                  //关闭接收DMA通道
       //num = USART1->SR;
       num = USART1->DR;                                                        //读SR后读DR清USART_IT_IDLE标志
       num = DMA_GetCurrDataCounter(DMA_USART1_RX_CHANNEL);                     //DMA接收数据后剩余缓存区间大小  

       //计算接收数据的长度
       if( Usart1_Info.PreRxDMACounter >= num )
       {
            Length = Usart1_Info.PreRxDMACounter - num;                        
       }
       else
       {
            Length = USART1_BUFLENGTH - num + Usart1_Info.PreRxDMACounter;
       }
      
       Usart1_Info.RxLength += Length;
       Usart1_Info.PreRxDMACounter = num;
       Usart1_Info.RxIndex = CirclePosition( Usart1_Info.RxIndex + Length, USART1_BUFLENGTH );
      
       USART_ClearITPendingBit(USART1, USART_IT_IDLE);                          //清除中断标志
       DMA_Cmd(DMA_USART1_RX_CHANNEL,ENABLE);                                   //重新开启DMA接收
    }  

    if(USART_GetFlagStatus(USART1,USART_FLAG_ORE)==SET)
        {
                USART_ClearFlag(USART1,USART_FLAG_ORE);        //读SR
                USART_ReceiveData(USART1);                                //读DR
        }
}

/********************************************************************************
*       函 数   名      :   DMA1_Channel2_IRQHandler                            *
*       功 能   说  明  :   发送DMA中断处理函数                                 *
*       形      参      :   无                                                  *
*       返  回  值      :   无                                                  *
*********************************************************************************/
void DMA1_Channel4_IRQHandler(void)
{
    DMA_ClearFlag(DMA1_FLAG_GL4);               //清除DMA发送完成标志

    DMA_Cmd(DMA_USART1_TX_CHANNEL, DISABLE);    //关闭发送DMA通道

    Usart1_Info.TxDMABusy = USART1_DMA_IDLE;    //发送通道空闲
}

/********************************************************************************
*       函 数   名      :   Usart1_Init                                          *
*       功 能   说  明  :   Usart1初始化                                         *
*       形      参      :   无                                                  *
*       返  回  值      :   无                                                  *
*********************************************************************************/
void Usart1_Init(void)
{
    Usart1_ParameterInit(115200,'N',8,1);
    Usart1_HardwareInit();
    Usart1_DMAInit();
}

UART1.h


#ifndef _BSP_UART1_H_
#define _BSP_UART1_H_

#include "stm32f10x.h"

#define USART1_BUFLENGTH        256

#define DMA_USART1_RX_CHANNEL   DMA1_Channel5
#define DMA_USART1_TX_CHANNEL   DMA1_Channel4


#define DMA_USART1_RX_FLAG      DMA1_FLAG_GL5       //DMA1_CHANNEL5全局中断标志
#define DMA_USART1_TX_FLAG      DMA1_FLAG_GL4       //DMA1_CHANNEL4全局中断标志

#define USART1_DMA_IDLE         0x00                //USART3_DMA 空闲
#define USART1_DMA_BUSY         0x01                //USART3_DMA 忙

typedef struct
{
    unsigned long Baudrate;                                                        //波特率
    unsigned int  Parity;                                                                //奇偶校验
    unsigned int  DataBit;                                                                //数据位
    unsigned int  StopBit;                                                                //停止位

    unsigned char RxBuf[USART1_BUFLENGTH];                                //接收缓存区长度
    unsigned int  RxIndex;                                                                //
    unsigned int  RxHead;                                                                //
    unsigned int  RxLength;                               //接收数据长度
    unsigned int  PreRxDMACounter;                        //DMA剩余缓存区间大小

    unsigned char TxBuf[USART1_BUFLENGTH];                                //发送缓存区长度
    unsigned char TxDMABuf[USART1_BUFLENGTH ];             //DMA缓冲区
    unsigned int  TxIndex;                                                                //
    unsigned int  TxTail;                                                                //
    unsigned int  TxLength;                               //待发送数据长度
    unsigned int  TxDMABusy;                            //DMA发送忙信号

    unsigned int  OverTime;                               //通讯延时

} Stu_USART1_INFO;

//GPIO定义
#define USART1_TX_PORT          GPIOA
#define USART1_TX_PIN           GPIO_Pin_9
#define USART1_RX_PORT          GPIOA
#define USART1_RX_PIN           GPIO_Pin_10

/********************************************************************************************
*                                                变                        量                        声                        明                                            *
*********************************************************************************************/
extern Stu_USART1_INFO     Usart1_Info;
/********************************************************************************************
*                                                函                        数                        声                        明                                            *
*********************************************************************************************/
extern void Usart1_SendtoTXbuf( unsigned char *data, unsigned int length );
extern void Usart1_SendtoTXDMAbuf( void );
extern void Usart1_Init(void);
extern unsigned int CirclePosition( unsigned int position, unsigned int length );
#endif
举报

更多回帖

×
20
完善资料,
赚取积分