STM32F10X UART2 + DMA

UART2.c

stu_usart2_info     usart2_info;

/********************************************************************************
*       函 数   名      :   usart2_parameter_init                                 *
*       功 能   说  明  :   UART1通信参数初始化                                 *
*       形      参      :   baudrate:波特率                                     *
*       形      参      :   parity:奇偶校验                                     *
*       形      参      :   databits:数据位                                     *
*       形      参      :   stopbits:停止位                                     *
*       返  回  值      :   无                                                  *
*********************************************************************************/
void usart2_parameter_init(unsigned int baudrate,unsigned char parity,unsigned int databits,unsigned int stopbits)
{
	unsigned int i = 0;
	
	usart2_info.baudrate = baudrate;
	
	if( parity == 'N' )		//无
		usart2_info.parity = USART_Parity_No;
	else if ( parity == 'E' )	//偶
		usart2_info.parity = USART_Parity_Even;
	else
		usart2_info.parity = USART_Parity_Odd;
	
	if( databits == 8 )
		usart2_info.data_bit = USART_WordLength_8b;
	else
		usart2_info.data_bit = USART_WordLength_9b;
	
	 if( stopbits == 1 )
		usart2_info.stop_bit = USART_StopBits_1;
	 else
		usart2_info.stop_bit =  USART_StopBits_2;
	 
	 usart2_info.rx_index = 0;
	 usart2_info.rx_head = 0;
	 usart2_info.rx_length = 0;
	 
	 usart2_info.tx_index = 0;
	 usart2_info.tx_tail = 0;
	 usart2_info.tx_length = 0;
	 usart2_info.tx_DMA_busy = 0;
	 
	 for( i=0;i<USART2_BUFLENGTH;i++)
	 {
		usart2_info.rx_buf[i] = 0;
		usart2_info.tx_buf[i] = 0;
		usart2_info.tx_DMA_buf[i] = 0; 
	 }
	 usart2_info.pre_rx_DMA_counter = USART2_BUFLENGTH;
	 usart2_info.over_time = 0;	 
}

/********************************************************************************
*       函 数   名      :   Usart3_HardwareInit                                 *
*       功 能   说  明  :   Usart3硬件初始化                                    *
*       形      参      :   无                                                  *
*       返  回  值      :   无                                                  *
*********************************************************************************/
void usart2_hardware_init(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 = USART2_IRQn;           //USART2全局中断
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;   //抢占优先级1
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;          //响应优先级0
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;             //使能中断
    NVIC_Init( &NVIC_InitStructure );
	
	 //使能串口时钟: USART2对应APB1
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2, ENABLE);      //使能USART3时钟
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_AFIO, ENABLE);//使能GPIOa时钟(设置TX/RX引脚)与复用时钟
	
    //USART2发送引脚配置
    GPIO_InitStructure.GPIO_Pin = USART2_TX_PIN;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;             //复用推挽输出
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(USART2_TX_PORT, &GPIO_InitStructure);

    //USART2接收引脚配置
    GPIO_InitStructure.GPIO_Pin = USART2_RX_PIN;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
    GPIO_Init(USART2_RX_PORT, &GPIO_InitStructure);	
	
    //USART2参数设置
    USART_InitStructure.USART_BaudRate 		= usart2_info.baudrate;
    USART_InitStructure.USART_Parity 		= usart2_info.parity;
    USART_InitStructure.USART_WordLength 	= usart2_info.data_bit;
    USART_InitStructure.USART_StopBits 	 	= usart2_info.stop_bit;
    USART_InitStructure.USART_Mode 		 	= USART_Mode_Rx | USART_Mode_Tx;
    USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;    //无硬件流控制
    USART_Init(USART2, &USART_InitStructure);	
	
	//串口中断(DMA模式)
	
    USART_ITConfig(USART2, USART_IT_IDLE, ENABLE);
	USART_Cmd(USART2, ENABLE);
	USART_ClearFlag(USART2, USART_FLAG_TC);
}

/********************************************************************************
*       函 数   名      :   Usart3_DMAInit                                      *
*       功 能   说  明  :   Usart1DMA初始化                                     *
*       形      参      :   无                                                  *
*       返  回  值      :   无                                                  *
*********************************************************************************/
void usart2_DMA_init(void)
{
	NVIC_InitTypeDef NVIC_InitStructure;
    DMA_InitTypeDef  DMA_Initstructure;
	
	// Configure the NVIC Preemption Priority Bits配置引脚优先级 
    NVIC_InitStructure.NVIC_IRQChannel = DMA_USART2_TX_IRQ;	
    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_USART2_TX_CHANNEL, DISABLE);                                    // 关DMA通道
    DMA_DeInit(DMA_USART2_TX_CHANNEL);                                          // 恢复缺省值
    DMA_Initstructure.DMA_PeripheralBaseAddr =(unsigned int)(&USART2->DR);      // 设置串口接收数据寄存器     
    DMA_Initstructure.DMA_MemoryBaseAddr = (unsigned int)usart2_info.tx_DMA_buf;  // 设置发送缓冲区首地址
    DMA_Initstructure.DMA_DIR = DMA_DIR_PeripheralDST;                          // 设置外设为目的地址,内存缓冲区 ->外设寄存器 
    DMA_Initstructure.DMA_BufferSize = USART2_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_USART2_TX_CHANNEL,&DMA_Initstructure);                         // 开启接收DMA通道,等待接收数据

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

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


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

    DMA_ClearFlag(DMA_USART2_RX_FLAG);

    DMA_Cmd(DMA_USART2_RX_CHANNEL, ENABLE);
    
    //开启USART2的DMA模式
    USART_DMACmd(USART2, USART_DMAReq_Rx|USART_DMAReq_Tx,ENABLE);
}


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

    if( length )
    {
        for(i = 0; i < length; i++)
        {
            usart2_info.tx_length++; 
            usart2_info.tx_buf[usart2_info.tx_tail++] = data[i];        //循环缓冲区装载数据
            if( usart2_info.tx_tail >= USART2_BUFLENGTH ) 
            {
                usart2_info.tx_tail -= USART2_BUFLENGTH;
            }
        }
    }
}

/********************************************************************************
*       函 数   名      :   Usart2_SendtoTXDMAbuf                               
*       功 能   说  明  :   Usart2发送数据到TX缓存区                            
*       形      参      :   无                                                  
*       返  回  值      :   无                                                  
*********************************************************************************/
void Usart2_SendtoTXDMAbuf( void )
{
    unsigned int i;
    
    if( usart2_info.tx_length && ( usart2_info.tx_DMA_busy == USART2_DMA_IDLE ) )
    {
        //有数据发送,往DMA缓冲区转移
        for( i = 0; i < usart2_info.tx_length; i++ )
        {
            usart2_info.tx_DMA_buf[i] = usart2_info.tx_buf[usart2_info.tx_index++];
            usart2_info.tx_index = CirclePosition( usart2_info.tx_index, USART2_BUFLENGTH );
        }
        
        //启动DMA数据发送
        DMA_SetCurrDataCounter(DMA_USART2_TX_CHANNEL, usart2_info.tx_length);
        usart2_info.tx_length = 0x00;                                        //发送数据长度清零
        usart2_info.tx_DMA_busy = USART2_DMA_BUSY;
        DMA_Cmd(DMA_USART2_TX_CHANNEL, ENABLE);                             //开启DMA发送
    }
}


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

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

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

        usart2_info.rx_length += Length;
        usart2_info.pre_rx_DMA_counter = num;
        usart2_info.rx_index = CirclePosition( usart2_info.rx_index + Length, USART2_BUFLENGTH );

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

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

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

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

    usart2_info.tx_DMA_busy = USART2_DMA_IDLE;  //发送通道空闲
}

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

 

UART2.h

#ifndef _BSP_UART2_H_
#define _BSP_UART2_H_

#include "stm32f10x.h"

#define USART2_BUFLENGTH    256

#define DMA_USART2_TX_CHANNEL   DMA1_Channel7
#define DMA_USART2_RX_CHANNEL   DMA1_Channel6

#define DMA_USART2_TX_FLAG      DMA1_FLAG_GL7       //DMA1_CHANNEL2全局中断标志
#define DMA_USART2_RX_FLAG      DMA1_FLAG_GL6       //DMA1_CHANNEL3全局中断标志

#define DMA_USART2_TX_IRQ		DMA1_Channel7_IRQn
#define DMA_USART2_RX_IRQ		DMA1_Channel6_IRQn

#define USART2_DMA_IDLE         0x00                //USART3_DMA 空闲
#define USART2_DMA_BUSY         0x01                //USART3_DMA 忙

typedef struct 
{
    unsigned long baudrate;							    //波特率
    unsigned int  parity;								//奇偶校验
    unsigned int  data_bit;								//数据位
    unsigned int  stop_bit;								//停止位

    unsigned char rx_buf[USART2_BUFLENGTH];				//接收缓存区长度
    unsigned int  rx_index;								//
    unsigned int  rx_head;								//接收数据第一个字节所在位置
    unsigned int  rx_length;                               //接收数据长度
    unsigned int  pre_rx_DMA_counter;                        //DMA剩余缓存区间大小

    unsigned char tx_buf[USART2_BUFLENGTH];				//发送缓存区长度
    unsigned char tx_DMA_buf[USART2_BUFLENGTH ];             //DMA缓冲区
    unsigned int  tx_index;								//
    unsigned int  tx_tail;								//发送数据第一个字节所在位置
    unsigned int  tx_length;                               //待发送数据长度
    unsigned int  tx_DMA_busy;                            //DMA发送忙信号

    unsigned int  over_time;                               //通讯延时

}stu_usart2_info;

//GPIO定义
#define USART2_TX_PORT          GPIOA
#define USART2_TX_PIN           GPIO_Pin_2
#define USART2_RX_PORT          GPIOA
#define USART2_RX_PIN           GPIO_Pin_3




extern stu_usart2_info     usart2_info;

void usart2_send_to_tx_buf( unsigned char *data, unsigned int length );
void Usart2_SendtoTXDMAbuf( void );
void usart2_init(void);
#endif

 

 

 

 

 

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值