stm32f103x_DMA串口接收发送

简要

使用DMA发送和接收不定长USART1串口数据

.H文件

#ifndef __DMA_USART1_H
#define __DMA_USART1_H

#include "stm32f10x.h"

void GPIO_Usart1_Init(void);
void USART_NVIC_Config(void);
void USART_DMA_RX(void);
void USART_DMA_TX(void);

#endif

.c文件

声名两个数组

uint8_t RX_Buffer[128];
uint8_t TX_Buffer[128];

配置GPIOA_Pin9和GPIOA_Pin10

void GPIO_Usart1_Init(void)
	{
	GPIO_InitTypeDef GPIO_InitStruct;
	USART_InitTypeDef USART_InitStruct;
	
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);			   //使能APB2总线的GPPIOA端口
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1,ENABLE);			  //使能APB2总线的USART1外设
	
	/*配置GPIOA_Pin_11引脚*/
	GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IN_FLOATING;				//使用浮空输入模式
	GPIO_InitStruct.GPIO_Pin = GPIO_Pin_10;									 //PIN_11为RX数据接受引脚
	//GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;		    //可定义可不定义都不影响
	GPIO_Init(GPIOA,&GPIO_InitStruct);								     //将赋值的结构体乘员写入寄存器
	
	/*配置GPIOA_Pin_12引脚*/
	GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF_PP;		     //使用复用推挽输出模式复用USART
	GPIO_InitStruct.GPIO_Pin = GPIO_Pin_9;					    //PIN_12为TX数据发送引脚
	GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;		 //可定义可不定义都不影响
	GPIO_Init(GPIOA,&GPIO_InitStruct);
	
		/*配置USART1模式等*/
	USART_InitStruct.USART_BaudRate = 9600;                                            //波特率设置为9600
	USART_InitStruct.USART_HardwareFlowControl = USART_HardwareFlowControl_None;			//不启用硬件控制接收端接收到的数据处理不过来时,就向发送端发送不再接收的信号,发送端接收到这个信号之后就会停止发送,直到收到可以继续发送的信号再继续发送。因此流控本身是可以控制数据传输的进度,进而防止数据丢失。
	USART_InitStruct.USART_Mode = USART_Mode_Rx|USART_Mode_Tx;											 //接收和发送都打开
	USART_InitStruct.USART_Parity = USART_Parity_No;															  //不启用奇偶校验
	USART_InitStruct.USART_StopBits = USART_StopBits_1;														 //一个停止位
	USART_InitStruct.USART_WordLength = USART_WordLength_8b ;											//数据长度为8位
	USART_Init(USART1,&USART_InitStruct);
	
	USART_ITConfig(USART1, USART_IT_IDLE, ENABLE);                               //当检测到总线空闲时,该位被硬件置位。
	USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);															//接收缓冲区非空中断使能
	USART_ITConfig(USART1,USART_IT_TC,ENABLE);																 //当包含有数据的一帧发送完成后,并且TXE=1时,由硬件将该位置’1’。 
	/*配置USART1接收中断*/																  
	USART_NVIC_Config();
  USART_Cmd(USART1, ENABLE);      
	}

配置接收DMA

/*配置USART1—DMA接收*/	
void USART_DMA_RX(void)
{
	DMA_InitTypeDef DMA_InitStruct;
	RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1,ENABLE);			                     //开启DMA1时钟
	
	DMA_InitStruct.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;      //外设接口数据宽度8位                     //发送数据的地址
	DMA_InitStruct.DMA_PeripheralInc = DMA_PeripheralInc_Disable;						 //外设地址增量模式不自增	
	DMA_InitStruct.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;            //存储器数据宽度为8位
	DMA_InitStruct.DMA_PeripheralBaseAddr = USART1_BASE+0x04;              //stm32f10x.h 1327行
	DMA_InitStruct.DMA_MemoryBaseAddr = (uint32_t)RX_Buffer;	          	//指定一块内存用来储存DMA接收到的数据
	DMA_InitStruct.DMA_MemoryInc = DMA_MemoryInc_Enable;                 //内存地址增量模式不自增
	DMA_InitStruct.DMA_Priority = DMA_Priority_VeryHigh ;               //优先级非常高
	DMA_InitStruct.DMA_DIR =  DMA_DIR_PeripheralSRC;                   //外设到内存
	DMA_InitStruct.DMA_Mode =  DMA_Mode_Normal;                       //普通不循环模式{DMA_BufferSize = 8;|normal:上位机发送1234567890接收:12345678//Circular:上位机发送1234567890接收:90345678|}
	DMA_InitStruct.DMA_M2M = DMA_M2M_Disable;												 //禁止内存到内存传输
	DMA_InitStruct.DMA_BufferSize = 128;

	DMA_Init(DMA1_Channel5,&DMA_InitStruct);
	USART_DMACmd(USART1,USART_DMAReq_Rx,ENABLE);									//开启DMA接收串口数据
	DMA_Cmd(DMA1_Channel5,ENABLE);
}

配置发送DMA

/*配置USART1—DMA发送*/	
void USART_DMA_TX(void)
{
	DMA_InitTypeDef DMA_InitStruct;
	RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1,ENABLE);
	
	DMA_InitStruct.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;      //外设接口数据宽度8位                     //发送数据的地址
	DMA_InitStruct.DMA_PeripheralInc = DMA_PeripheralInc_Disable;						 //外设地址增量模式不自增	
	DMA_InitStruct.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;            //存储器数据宽度为8位
	DMA_InitStruct.DMA_PeripheralBaseAddr = (USART1_BASE+0x04);              //stm32f10x.h 1327行
	DMA_InitStruct.DMA_MemoryBaseAddr = (uint32_t)TX_Buffer;	          	//指定一块内存用来DMA发送数据
	DMA_InitStruct.DMA_MemoryInc = DMA_MemoryInc_Enable;                 //内存地址增量模式不自增
	DMA_InitStruct.DMA_Priority = DMA_Priority_High ;                   //优先级非常高
	DMA_InitStruct.DMA_DIR =  DMA_DIR_PeripheralDST;                   //内存到外设
	DMA_InitStruct.DMA_Mode =  DMA_Mode_Normal;                       //普通不循环模式{DMA_BufferSize = 8;|normal:上位机发送1234567890接收:12345678//Circular:上位机发送1234567890接收:90345678|}
	DMA_InitStruct.DMA_M2M = DMA_M2M_Disable;												 //禁止内存到内存传输
	DMA_InitStruct.DMA_BufferSize = 128;
	DMA_Init(DMA1_Channel4,&DMA_InitStruct);
	USART_DMACmd(USART1,USART_DMAReq_Tx,ENABLE);
	DMA_Cmd(DMA1_Channel4,DISABLE);
	
}

配置USART1串口NVIC

/*配置USART1中断*/		
void USART_NVIC_Config(void)
{
	NVIC_InitTypeDef NVIC_InitStruct;
	
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);					  	//一位抢占优先级,3为响应优先级								
	
	NVIC_InitStruct.NVIC_IRQChannel = USART1_IRQn;           	 //选择USART1通道(stm32f10x.h)
	NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE;            	//使能USART1通道
	NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = 1; 	 //抢占优先级(可取0或1)
	NVIC_InitStruct.NVIC_IRQChannelSubPriority = 1;					//响应优先级(可取0到7)				
	NVIC_Init(&NVIC_InitStruct);
}

USART1中断服务函数

/*USART1中断服务程序*/	
void USART1_IRQHandler(void)
{
	int i,l;		
	if(USART_GetITStatus(USART1, USART_IT_IDLE) != RESET)	//监测到总线空闲
	{		
		DMA_Cmd(DMA1_Channel5,DISABLE);											//关闭接收DMA防止数据覆盖(可用双缓存解决,设置两个缓存数组)
		l=128-DMA_GetCurrDataCounter(DMA1_Channel5);
		for(i=0;i<l;i++)//将接收到的内容复制给发送数组
		{
		TX_Buffer[i]=RX_Buffer[i];
		}
		
		DMA_Cmd(DMA1_Channel4,DISABLE);
		DMA_SetCurrDataCounter(DMA1_Channel4,l);
		DMA_Cmd(DMA1_Channel4,ENABLE);
		
		USART_ReceiveData(USART1);
		USART_ClearITPendingBit(USART1,USART_IT_IDLE);									 //清除IDLE标志必须先将SR和DR寄存器的内容读取(手册)
		DMA_SetCurrDataCounter(DMA1_Channel5,128);											//每次接收完需重新设定CNTDR寄存器,否者接收不到数据
	}
	if(USART_GetITStatus(USART1, USART_IT_TC) != RESET)							 //发送完成
	{
		DMA_Cmd(DMA1_Channel4,DISABLE);
		USART_ClearITPendingBit(USART1,USART_IT_TC);
	}
	if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET)					 //触发接收,开启接收DMA
	{		 	
		USART_ClearITPendingBit(USART1,USART_IT_RXNE);
		DMA_Cmd(DMA1_Channel5,ENABLE);
	}
}

man.c

#include "stm32f10x.h"
#include "./DMA_USART/DMA_USART1.h"

extern uint8_t RX_Buffer[128];
extern uint8_t TX_Buffer[128];
int i;
int main (void)
{	
	GPIO_Usart1_Init();		
	USART_DMA_RX();
	USART_DMA_TX();	
	while(1)
	{}
}

运行结果

运行结果

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值