STM32F10X UART3 + DMA

UART3.c

#include "BSP_Uart3.h"
#include "BMS.h"

/********************************************************************************************
*						变			量			声			明					  *
*********************************************************************************************/
Stu_USART3_INFO     Usart3_Info;

/********************************************************************************************
*						函			数			声			明					  *
*********************************************************************************************/

/********************************************************************************
*       函 数   名      :   Usart3_ParameterInit                                 *
*       功 能   说  明  :   UART1通信参数初始化                                 *
*       形      参      :   baudrate:波特率                                     *
*       形      参      :   parity:奇偶校验                                     *
*       形      参      :   databits:数据位                                     *
*       形      参      :   stopbits:停止位                                     *
*       返  回  值      :   无                                                  *
*********************************************************************************/
void Usart3_ParameterInit(unsigned int baudrate,unsigned char parity,unsigned int databits,unsigned int stopbits )
{
    unsigned int i;
    
    Usart3_Info.Baudrate = baudrate;

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

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

    if( stopbits == 1 )
    {
        Usart3_Info.StopBit = USART_StopBits_1;                     
    }
    else 
    {
        Usart3_Info.StopBit = USART_StopBits_2;                    
    }
    
    Usart3_Info.RxIndex = 0;
    Usart3_Info.RxHead = 0;
    Usart3_Info.RxLength =0;
    
    Usart3_Info.TxIndex = 0;
    Usart3_Info.TxTail = 0;
    Usart3_Info.TxLength = 0;
    Usart3_Info.TxDMABusy = USART3_DMA_IDLE;
   
    for( i=0;i<USART3_BUFLENGTH;i++)
    {
        Usart3_Info.RxBuf[i] = 0x00;
        Usart3_Info.TxBuf[i] = 0x00;
        Usart3_Info.TxDMABuf[i] = 0x00;
    }   
    
    Usart3_Info.PreRxDMACounter = USART3_BUFLENGTH;
    Usart3_Info.OverTime =0;
}

/********************************************************************************
*       函 数   名      :   Usart3_HardwareInit                                 *
*       功 能   说  明  :   Usart3硬件初始化                                    *
*       形      参      :   无                                                  *
*       返  回  值      :   无                                                  *
*********************************************************************************/
void Usart3_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 = USART3_IRQn;           //USART3全局中断
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;   //抢占优先级1
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;          //响应优先级0
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;             //使能中断
    NVIC_Init( &NVIC_InitStructure );

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

    //USART3发送引脚配置
    GPIO_InitStructure.GPIO_Pin = USART3_TX_PIN;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;             //复用推挽输出
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(USART3_TX_PORT, &GPIO_InitStructure);

    //USART3接收引脚配置
    GPIO_InitStructure.GPIO_Pin = USART3_RX_PIN;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
    GPIO_Init(USART3_RX_PORT, &GPIO_InitStructure);

    //USART3参数设置
    USART_InitStructure.USART_BaudRate = Usart3_Info.Baudrate;
    USART_InitStructure.USART_Parity = Usart3_Info.Parity ;
    USART_InitStructure.USART_WordLength = Usart3_Info.DataBit;
    USART_InitStructure.USART_StopBits = Usart3_Info.StopBit;
    USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
    USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;    //无硬件流控制
    USART_Init(USART3, &USART_InitStructure);
    USART3->BRR = 0x138;

    //串口中断(DMA模式)
    USART_ITConfig(USART3,USART_IT_IDLE,ENABLE);                                

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

    
    USART_ClearFlag(USART3, USART_FLAG_TC);
    
}

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

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

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

    
    //发送DMA配置
    DMA_Cmd(DMA_USART3_TX_CHANNEL, DISABLE);                                    // 关DMA通道
    DMA_DeInit(DMA_USART3_TX_CHANNEL);                                          // 恢复缺省值
    DMA_Initstructure.DMA_PeripheralBaseAddr =(unsigned int)(&USART3->DR);      // 设置串口接收数据寄存器     
    DMA_Initstructure.DMA_MemoryBaseAddr = (unsigned int)Usart3_Info.TxDMABuf;  // 设置发送缓冲区首地址
    DMA_Initstructure.DMA_DIR = DMA_DIR_PeripheralDST;                          // 设置外设为目的地址,内存缓冲区 ->外设寄存器 
    DMA_Initstructure.DMA_BufferSize = USART3_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_USART3_TX_CHANNEL,&DMA_Initstructure);                         // 开启接收DMA通道,等待接收数据

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

    DMA_Cmd(DMA_USART3_TX_CHANNEL,DISABLE);                                      //关DMA通道

    //接收DMA配置
    DMA_Cmd(DMA_USART3_RX_CHANNEL,DISABLE);                                     //关DMA通道
    DMA_DeInit(DMA_USART3_RX_CHANNEL);
    DMA_Initstructure.DMA_PeripheralBaseAddr =(unsigned int)(&USART3->DR);      // 设置串口接收数据寄存器     
    DMA_Initstructure.DMA_MemoryBaseAddr = (unsigned int)Usart3_Info.RxBuf;     // 设置接收缓冲区首地址
    DMA_Initstructure.DMA_DIR = DMA_DIR_PeripheralSRC;                          // 设置外设为数据源,外设寄存器 ->内存缓冲区
    DMA_Initstructure.DMA_BufferSize = USART3_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_USART3_RX_CHANNEL,&DMA_Initstructure);
    
    DMA_ITConfig(DMA_USART3_RX_CHANNEL,DMA_IT_TC,ENABLE);
    DMA_ITConfig(DMA_USART3_RX_CHANNEL,DMA_IT_TE,ENABLE);

    DMA_ClearFlag(DMA_USART3_RX_FLAG);

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

}

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

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

/********************************************************************************
*       函 数   名      :   Usart3_SendtoTXDMAbuf                               *
*       功 能   说  明  :   Usart3发送数据到TX缓存区                            *
*       形      参      :   无                                                  *
*       返  回  值      :   无                                                  *
*********************************************************************************/
void Usart3_SendtoTXDMAbuf( void )
{
    unsigned int i;
    
    if( Usart3_Info.TxLength && ( Usart3_Info.TxDMABusy == USART3_DMA_IDLE ) )
    {
        //有数据发送,往DMA缓冲区转移
        for( i=0; i<Usart3_Info.TxLength; i++ )
        {
            Usart3_Info.TxDMABuf[i] = Usart3_Info.TxBuf[Usart3_Info.TxIndex++];
            Usart3_Info.TxIndex = CirclePosition( Usart3_Info.TxIndex, USART3_BUFLENGTH );
        }
        
        //启动DMA数据发送
        DMA_SetCurrDataCounter(DMA_USART3_TX_CHANNEL,Usart3_Info.TxLength);
        Usart3_Info.TxLength = 0x00;                                        //发送数据长度清零
        Usart3_Info.TxDMABusy = USART3_DMA_BUSY;
        DMA_Cmd(DMA_USART3_TX_CHANNEL, ENABLE);                             //开启DMA发送
    }
}

/********************************************************************************
*       函 数   名      :   USART3_IRQHandler                                   *
*       功 能   说  明  :   Usart3接收中断处理函数                                  *
*       形      参      :   无                                                  *
*       返  回  值      :   无                                                  *
*********************************************************************************/
void USART3_IRQHandler(void)
{
    //DMA模式
    unsigned int num;
    unsigned int Length;

    //DMA_GetCurrDataCounter
    if( USART_GetITStatus( USART3,USART_IT_IDLE ) == SET )                      //整帧接收完成中断
    {
        DMA_Cmd(DMA_USART3_RX_CHANNEL,DISABLE);                                  //关闭接收DMA通道
        num = USART3->SR;
        num = USART3->DR;
        num = DMA_GetCurrDataCounter(DMA_USART3_RX_CHANNEL);                     //DMA接收数据后剩余缓存区间大小  

        //计算接收数据的长度
        if( Usart3_Info.PreRxDMACounter >= num )
        {
            Length = Usart3_Info.PreRxDMACounter - num;                         
        }
        else
        {
            Length = USART3_BUFLENGTH - num + Usart3_Info.PreRxDMACounter;
        }

        Usart3_Info.RxLength += Length;
        Usart3_Info.PreRxDMACounter = num;
        Usart3_Info.RxIndex = CirclePosition( Usart3_Info.RxIndex + Length, USART3_BUFLENGTH );

        USART_ClearITPendingBit(USART3, USART_IT_IDLE);                          //清除中断标志
        DMA_Cmd(DMA_USART3_RX_CHANNEL,ENABLE);                                   //重新开启DMA接收
    }  

    if(USART_GetFlagStatus(USART3,USART_FLAG_ORE)==SET)                     //接收过载中断
    {
        USART_ClearFlag(USART3,USART_FLAG_ORE);	//清除中断标志
        USART_ReceiveData(USART3);				//
    }
}

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

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

    Usart3_Info.TxDMABusy = USART3_DMA_IDLE;    //发送通道空闲
}

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


UART3.h

#ifndef _BSP_UART3_H_
#define _BSP_UART3_H_

#include "stm32f10x.h"

#define USART3_BUFLENGTH    256

#define DMA_USART3_TX_CHANNEL   DMA1_Channel2
#define DMA_USART3_RX_CHANNEL   DMA1_Channel3

#define DMA_USART3_TX_FLAG      DMA1_FLAG_GL2       //DMA1_CHANNEL2全局中断标志
#define DMA_USART3_RX_FLAG      DMA1_FLAG_GL3       //DMA1_CHANNEL3全局中断标志

#define USART3_DMA_IDLE         0x00                //USART3_DMA 空闲
#define USART3_DMA_BUSY         0x01                //USART3_DMA 忙

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

    unsigned char RxBuf[USART3_BUFLENGTH];				//接收缓存区长度
    unsigned int  RxIndex;								//
    unsigned int  RxHead;								//接收数据第一个字节所在位置
    unsigned int  RxLength;                               //接收数据长度
    unsigned int  PreRxDMACounter;                        //DMA剩余缓存区间大小

    unsigned char TxBuf[USART3_BUFLENGTH];				//发送缓存区长度
    unsigned char TxDMABuf[USART3_BUFLENGTH ];             //DMA缓冲区
    unsigned int  TxIndex;								//
    unsigned int  TxTail;								//发送数据第一个字节所在位置
    unsigned int  TxLength;                               //待发送数据长度
    unsigned int  TxDMABusy;                            //DMA发送忙信号

    unsigned int  OverTime;                               //通讯延时

} Stu_USART3_INFO;

//GPIO定义
#define USART3_TX_PORT          GPIOB
#define USART3_TX_PIN           GPIO_Pin_10
#define USART3_RX_PORT          GPIOB
#define USART3_RX_PIN           GPIO_Pin_11
/********************************************************************************************
*						变			量			声			明					    *
*********************************************************************************************/
extern Stu_USART3_INFO     Usart3_Info;
/********************************************************************************************
*						函			数			声			明					    *
*********************************************************************************************/
extern void Usart3_SendtoTXbuf( unsigned char *data, unsigned int length );
extern void Usart3_SendtoTXDMAbuf( void );
extern void Usart3_Init(void);
#endif



 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值