STM32F103VE基于标准库串口1空闲中断+DMA数据接收工程

STM32F103VE基于标准库串口1空闲中断+DMA数据接收工程


  • ✨本例程通过正点原子MINI开发板程序模版进行移植修改得来。

  • usart.c

#include "sys.h"
#include "usart.h"
//#include 
#include 
// 	 
//如果使用ucos,则包括下面的头文件即可.
#if SYSTEM_SUPPORT_OS
#include "includes.h"	//ucos 使用	  
#endif
//	 
//本程序只供学习使用,未经作者许可,不得用于其它任何用途
//ALIENTEK STM32开发板
//串口1初始化		   
//********************************************************************************
//V1.3修改说明 
//支持适应不同频率下的串口波特率设置.
//加入了对printf的支持
//增加了串口接收命令功能.
//修正了printf第一个字符丢失的bug
//V1.4修改说明
//1,修改串口初始化IO的bug
//2,修改了USART_RX_STA,使得串口最大接收字节数为2的14次方
//3,增加了USART_REC_LEN,用于定义串口最大允许接收的字节数(不大于2的14次方)
//4,修改了EN_USART1_RX的使能方式
//V1.5修改说明
//1,增加了对UCOSII的支持
// 	  
 

//
//加入以下代码,支持printf函数,而不需要选择use MicroLIB	  
#if 1
#pragma import(__use_no_semihosting)             
//标准库需要的支持函数                 
struct __FILE 
{ 
	int handle; 

}; 

FILE __stdout; 

//定义_sys_exit()以避免使用半主机模式    
void _sys_exit(int x) 
{ 
	x = x; 
}

//重定义fputc函数 
int fputc(int ch, FILE *f)
{      
	while((USART1->SR&0X40)==0){}//循环发送,直到发送完毕   
    USART1->DR = (u8) ch;      
	return ch;
}

#endif 

 
 
#if EN_USART1_RX   //如果使能了接收
//串口1中断服务程序
//注意,读取USARTx->SR能避免莫名其妙的错误   	
u8 USART_RX_BUF[USART_REC_LEN];     //接收缓冲,最大USART_REC_LEN个字节.
//接收状态
//bit15,	接收完成标志
//bit14,	接收到0x0d
//bit13~0,	接收到的有效字节数目
u16 USART_RX_STA=0;       //接收状态标记	  
  
void uart_init(u32 bound){
  //GPIO端口设置
  GPIO_InitTypeDef GPIO_InitStructure;
	USART_InitTypeDef USART_InitStructure;
	NVIC_InitTypeDef NVIC_InitStructure;
	 
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1|RCC_APB2Periph_GPIOA, ENABLE);	//使能USART1,GPIOA时钟
  
	//USART1_TX   GPIOA.9
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9; //PA.9
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;	//复用推挽输出
  GPIO_Init(GPIOA, &GPIO_InitStructure);//初始化GPIOA.9
   
  //USART1_RX	  GPIOA.10初始化
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;//PA10
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;//浮空输入
  GPIO_Init(GPIOA, &GPIO_InitStructure);//初始化GPIOA.10  

  //Usart1 NVIC 配置
  NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=3 ;//抢占优先级3
	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3;		//子优先级3
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;			//IRQ通道使能
	NVIC_Init(&NVIC_InitStructure);	//根据指定的参数初始化VIC寄存器
  
   //USART 初始化设置

	USART_InitStructure.USART_BaudRate = bound;//串口波特率
	USART_InitStructure.USART_WordLength = USART_WordLength_8b;//字长为8位数据格式
	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(USART1, &USART_InitStructure); //初始化串口1
	
//  USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);//开启串口接受中断
	USART_ITConfig(USART1, USART_IT_IDLE, ENABLE);//开启空闲中断
	USART_DMACmd(USART1, USART_DMAReq_Rx, ENABLE);//开启DMA接收
	USART_Cmd(USART1, ENABLE);
}

void USART1_IRQHandler(void)                	//串口1中断服务程序
	{
			uint16_t data;  
    if(USART_GetITStatus(USART1,USART_IT_IDLE) != RESET)  
    {  
        DMA_Cmd(DMA1_Channel5, DISABLE); //关闭DMA,防止处理其间有数据  
  
        data = USART1->SR;  //清空空闲中断标志位操作
        data = USART1->DR;  
          
        g_uart1ReceiveSize =RECEIVE_BUF_SIZE - DMA_GetCurrDataCounter(DMA1_Channel5);  
        if(g_uart1ReceiveSize !=0)  
        {  
           // OSSemPost(DMAReceiveSize_Sem);  
						printf("shoudao1:%s", g_uart1ReceiveBuff);
						memset(g_uart1ReceiveBuff,0,255);//清空接收缓冲区数据
        }  
        DMA_ClearFlag(DMA1_FLAG_TC5 | DMA1_FLAG_TE5 | DMA1_FLAG_HT5);//清除DMA2_Steam7传输完成标志    
        DMA_SetCurrDataCounter(DMA1_Channel5, RECEIVE_BUF_SIZE);  
        DMA_Cmd(DMA1_Channel5, ENABLE);     //打开DMA,  
  
    }  
  }

	
#endif	


  • usart.h
#ifndef __USART_H
#define __USART_H
#include "stdio.h"	
#include "sys.h" 
#include "dma.h"
//	 
//本程序只供学习使用,未经作者许可,不得用于其它任何用途
//ALIENTEK STM32开发板
//串口1初始化		   
//********************************************************************************
//V1.3修改说明 
//支持适应不同频率下的串口波特率设置.
//加入了对printf的支持
//增加了串口接收命令功能.
//修正了printf第一个字符丢失的bug
//V1.4修改说明
//1,修改串口初始化IO的bug
//2,修改了USART_RX_STA,使得串口最大接收字节数为2的14次方
//3,增加了USART_REC_LEN,用于定义串口最大允许接收的字节数(不大于2的14次方)
//4,修改了EN_USART1_RX的使能方式
//V1.5修改说明
//1,增加了对UCOSII的支持
#define USART_REC_LEN  			200  	//定义最大接收字节数 200
#define EN_USART1_RX 			1		//使能(1)/禁止(0)串口1接收
#define USE_USART_DMA_RX   1
#define  USE_USART_DMA_TX  0
	  	
extern u8  USART_RX_BUF[USART_REC_LEN]; //接收缓冲,最大USART_REC_LEN个字节.末字节为换行符 
extern u16 USART_RX_STA;         		//接收状态标记	
//如果想串口中断接收,请不要注释以下宏定义
void uart_init(u32 bound);

#endif
  • dma.h
#ifndef __DMA_H
#define	__DMA_H	   
#include "sys.h"
#include "stm32f10x.h"

/*********************************************************************
 * DEFINITIONS
 */						    					    
#define  RECEIVE_BUF_SIZE           255
#define  SEND_BUF_SIZE    			255

/*********************************************************************
 * GLOBAL VARIABLES
 */
extern uint8_t g_uart1ReceiveBuff[RECEIVE_BUF_SIZE];   			//接收缓冲  
extern uint8_t g_uart1SendBuff[SEND_BUF_SIZE];    				//发送数据缓冲区  
extern uint16_t g_uart1ReceiveSize;  
  

 
/*********************************************************************
* API FUNCTIONS
*/
void DMA_Config(void);
void DmaSendDataProc(DMA_Channel_TypeDef *DMA_Streamx,uint16_t ndtr);
void Uart1DmaSendByte(uint8_t nSendInfo);
void Uart1DmaSendString(uint8_t* pSendInfo, uint16_t nSendCount);



#endif /* __DMA_H */
  • dma.c
/**===========================================================================
  @file     bsp_dma.c
  @brief    本文件是用于DMA驱动
  @author   青梅煮久
  @version  r0.1
  @date     2021/02/19
----------------------------------------------------------------------------
  Remark: (备注描述)
	串口1、3的接收。
							DMA1各个通道请求映像
外设    通道1   通道2     通道3       通道4        通道5       通道6      通道7
USART   - 	 USART3_TX  USART3_RX  USART1_TX  USART1_RX  USART2_RX  USART2_TX
============================================================================*/

/*********************************************************************
 * INCLUDES
 */
#include "dma.h"
#include 

static void NVIC_Configuration(void);

/*********************************************************************
 * GLOBAL VARIABLES
 */
uint8_t  g_uart1ReceiveBuff[RECEIVE_BUF_SIZE];   //接收缓冲  
uint8_t  g_uart1SendBuff[SEND_BUF_SIZE];    //发送数据缓冲区  
uint16_t g_uart1ReceiveSize = 0;  
  
uint8_t  g_uart3ReceiveBuff[RECEIVE_BUF_SIZE];   //接收缓冲  
uint8_t  g_uart3SendBuff[SEND_BUF_SIZE];    //发送数据缓冲区  
uint16_t g_uart3ReceiveSize = 0;  

/*********************************************************************
 * LOCAL VARIABLES
 */

/*********************************************************************
 * PUBLIC FUNCTIONS
 */
/**
 @brief DMA配置
 @param 无
 @return 无
*/
void DMA_Config(void)
{
	DMA_InitTypeDef  DMA_InitStructure;
	
	RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);	//使能DMA传输
	
	/****************************配置UART1 DMA发送***********************/
    DMA_DeInit(DMA1_Channel4);  
    DMA_InitStructure.DMA_PeripheralBaseAddr = (u32)&USART1->DR;//DMA外设地址  
    DMA_InitStructure.DMA_MemoryBaseAddr = (u32)g_uart1SendBuff;//DMA 存储器0地址  
    DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST;//存储器到外设模式  
    DMA_InitStructure.DMA_BufferSize = SEND_BUF_SIZE;//数据传输量   
    DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;//外设非增量模式  
    DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;//存储器增量模式  
    DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;//外设数据长度:8位  
    DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;//存储器数据长度:8位  
    DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;// 使用普通模式   
    DMA_InitStructure.DMA_Priority = DMA_Priority_Medium;//中等优先级  
    DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;  //DMA通道x没有设置为内存到内存传输
    DMA_Init(DMA1_Channel4, &DMA_InitStructure);//初始化DMA Stream
		DMA_ITConfig(DMA1_Channel4,DMA_IT_TC,ENABLE);
	
	/****************************配置UART1 DMA接收***********************/
    DMA_DeInit(DMA1_Channel5);  
    DMA_InitStructure.DMA_PeripheralBaseAddr = (u32)&USART1->DR;//DMA外设地址  
    DMA_InitStructure.DMA_MemoryBaseAddr = (u32)g_uart1ReceiveBuff;//DMA 存储器0地址  
    DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC ;//外设到存储器模式  
    DMA_InitStructure.DMA_BufferSize = RECEIVE_BUF_SIZE;//数据传输量   
    DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;//外设非增量模式  
    DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;//存储器增量模式  
    DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;//外设数据长度:8位  
    DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;//存储器数据长度:8位  
    DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;// 使用普通模式   
    DMA_InitStructure.DMA_Priority = DMA_Priority_Medium;//中等优先级  
    DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;  //DMA通道x没有设置为内存到内存传输
    DMA_Init(DMA1_Channel5, &DMA_InitStructure);//初始化DMA Stream  
	
	
	/****************************配置NVIC***********************/
	NVIC_Configuration();
	/**********************串口1接收使能DMA*******************/
	DMA_Cmd(DMA1_Channel5, ENABLE);  //开启DMA传输	
	DMA_ITConfig(DMA1_Channel5,DMA_IT_TC,ENABLE);  
  
}

/**
 @brief 开启一次DMA传输 
 @param DMA_Streamx -[in] DMA数据流,通道
 @param ndtr -[in] 数据传输量
 @return 无
*/  
void DmaSendDataProc(DMA_Channel_TypeDef *DMA_Streamx,uint16_t ndtr)  
{  

    DMA_Cmd(DMA_Streamx, DISABLE);                      //关闭DMA传输   

    DMA_SetCurrDataCounter(DMA_Streamx,ndtr);          //数据传输量    

    DMA_Cmd(DMA_Streamx, ENABLE);                      //开启DMA传输   
}

/**
 @brief 串口1使用DMA发送单字节
 @param nSendInfo -[in] 发送数据
 @return 无
*/ 
void Uart1DmaSendByte(uint8_t nSendInfo)  
{  
    uint8_t *pBuf = NULL;  
    //指向发送缓冲区
    pBuf = g_uart1SendBuff;  
    *pBuf++ = nSendInfo;  
  
    DmaSendDataProc(DMA1_Channel4, 1); //开始一次DMA传输!       
} 

/**
 @brief 串口1使用DMA发送多字节
 @param nSendInfo -[in] 发送数据
 @param nSendCount -[in] 发送长度
 @return 无
*/ 
void Uart1DmaSendString(uint8_t* pSendInfo, uint16_t nSendCount)  
{  
    uint16_t i = 0;  
    uint8_t *pBuf = NULL;  
    //指向发送缓冲区  
    pBuf = g_uart1SendBuff;  
  
    for (i=0; i<nSendCount; i++)  
    {  
        *pBuf++ = pSendInfo[i];  
    }  
    //DMA发送方式  
    DmaSendDataProc(DMA1_Channel4, nSendCount); //开始一次DMA传输!      
}  




/**
 @brief 串口1使用DMA发送完成中断
 @param 无
 @return 无
*/
void DMA1_Channel4_IRQHandler(void)  
{  
    //清除标志  
    if(DMA_GetFlagStatus(DMA1_FLAG_TC4)!=RESET)//等待传输完成  
    {   
        DMA_ClearFlag(DMA1_FLAG_TC4);//清除传输完成标志  
    }  
} 

/**
 @brief 串口1使用DMA接完成中断
 @param 无
 @return 无
*/ 
void DMA1_Channel5_IRQHandler(void)  
{  
    //清除标志  
    if(DMA_GetFlagStatus(DMA1_FLAG_TC5)!=RESET)//等待传输完成  
    {   
        DMA_Cmd(DMA1_Channel5, DISABLE); //关闭DMA,防止处理其间有数据  
  
        g_uart1ReceiveSize =RECEIVE_BUF_SIZE - DMA_GetCurrDataCounter(DMA1_Channel5);  
        if(g_uart1ReceiveSize !=0)  
        {  
            // 此处不处理数据,uart处理
        }  
          
        DMA_ClearFlag(DMA1_FLAG_TC5 | DMA1_FLAG_TE5 | DMA1_FLAG_HT5);//清除DMA2_Steam7传输完成标志  
        DMA_SetCurrDataCounter(DMA1_Channel5, RECEIVE_BUF_SIZE);  
        DMA_Cmd(DMA1_Channel5, ENABLE);     //打开DMA,  
    }  
}  

/**
 @brief 串口3使用DMA发送完成中断
 @param 无
 @return 无
*/
void DMA1_Channel2_IRQHandler(void)  
{  
    //清除标志  
    if(DMA_GetFlagStatus(DMA1_FLAG_TC2)!=RESET)//等待传输完成  
    {   
        DMA_ClearFlag(DMA1_FLAG_TC2);//清除传输完成标志  
    }  
} 

/**
 @brief 串口3使用DMA接完成中断
 @param 无
 @return 无
*/ 
void DMA1_Channel3_IRQHandler(void)  
{  
    //清除标志  
    if(DMA_GetFlagStatus(DMA1_FLAG_TC3)!=RESET)//等待传输完成  
    {   
        DMA_Cmd(DMA1_Channel3, DISABLE); //关闭DMA,防止处理其间有数据  
  
        g_uart3ReceiveSize =RECEIVE_BUF_SIZE - DMA_GetCurrDataCounter(DMA1_Channel3);  
        if(g_uart3ReceiveSize !=0)  
        {  
            // 此处不处理数据,uart处理
        }  
          
        DMA_ClearFlag(DMA1_FLAG_TC3 | DMA1_FLAG_TE3 | DMA1_FLAG_HT3);//清除DMA2_Steam7传输完成标志  
        DMA_SetCurrDataCounter(DMA1_Channel3, RECEIVE_BUF_SIZE);  
        DMA_Cmd(DMA1_Channel3, ENABLE);     //打开DMA,  
    }  
} 

/*********************************************************************
 * LOCAL FUNCTIONS
 */
/**
 @brief 配置嵌套向量中断控制器NVIC
 @param 无
 @return 无
*/
static void NVIC_Configuration(void)
{
	NVIC_InitTypeDef NVIC_InitStructure;

	/* 嵌套向量中断控制器组选择 */
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4);
	
	// 配置UART1发送  
	NVIC_InitStructure.NVIC_IRQChannel = DMA1_Channel4_IRQn;    
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;    
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;    
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;    
    NVIC_Init(&NVIC_InitStructure);    
	
	// 配置UART1接收 
    NVIC_InitStructure.NVIC_IRQChannel = DMA1_Channel5_IRQn;    
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2;    
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;    
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;    
    NVIC_Init(&NVIC_InitStructure);       
}


程序源码

链接:https://pan.baidu.com/s/1QU5lrl6VOetuzMbh_d0sbA 
提取码:odsv

你可能感兴趣的:(stm32标准库开发例程,stm32,空闲中断+DMA接收)