【STM32学习】 串口接收数据 使用串口空闲中断与DMA

【STM32学习】 串口接收数据 使用串口空闲中断与DMA(一)

一. 串口空闲中断
串口空闲中断,串口空闲时产生中断,也就是RXNE(RXNE位在有数据输入时自动置1)被置1开始检测直到串口空闲后,IDLE位被置为1后进入空闲中断。IDLE位只能通过软件序列来清除,即先读USART_SR,在读USART_DR(xx=USART_SR;xx=USART_DR;),并且IDLE位不能通过USART_ClearFlag()与USART_ClearITPendingBit()来清除。

二. DMA
DMA是一种数据传输方式,DMA即(Direct Memory access )直接存储器访问。外设与内存可以直接进行传输数据,通过DMAC操纵总线来控制数据的传输,这种方式能节省CPU资源。

三. 串口空闲+DMA
串口空闲中断+DMA能够用来接收不定长的数据

GPIO配置:

void GPIO_Configuration(void)
{
	GPIO_InitTypeDef GPIO_InitSture;
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);时钟使能
	
		GPIO_InitSture.GPIO_Mode=GPIO_Mode_AF_PP;
	GPIO_InitSture.GPIO_Pin=GPIO_Pin_9;
	GPIO_InitSture.GPIO_Speed=GPIO_Speed_50MHz;
	GPIO_Init(GPIOA,&GPIO_InitSture);					//pa9设置为复用推挽输出
	
		GPIO_InitSture.GPIO_Mode=GPIO_Mode_IN_FLOATING;
	GPIO_InitSture.GPIO_Pin=GPIO_Pin_10;
	GPIO_Init(GPIOA,&GPIO_InitSture);			//pa10设置为浮空输入
}

串口配置:

void USART_Configuration(void)
{

	USART_InitTypeDef USART_Initsture;	
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1,ENABLE);//时钟使能
	USART_Initsture.USART_BaudRate=115200;//波特率为115200
	USART_Initsture.USART_HardwareFlowControl=USART_HardwareFlowControl_None;//无硬件流控制
	USART_Initsture.USART_Mode=USART_Mode_Tx|USART_Mode_Rx;//串口输入输出模式
	USART_Initsture.USART_WordLength=USART_WordLength_8b;//字长8
	USART_Initsture.USART_Parity=USART_Parity_No;//无奇偶校验
	USART_Initsture.USART_StopBits=USART_StopBits_1;//停止位为1位
	USART_Init(USART1,&USART_Initsture);//用上面的结构体初始化USART1
	
	USART_ITConfig(USART1,USART_IT_IDLE,ENABLE);//串口中断配置,注意这里使能的是USART_IT_IDLE位而不是其他
	
	USART_Cmd(USART1, ENABLE);//使能USART1
	
}

NVIC配置:

void NVIC_Configuration(void)
{
	NVIC_InitTypeDef NVIC_InitStructure;
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_0);
	NVIC_InitStructure.NVIC_IRQChannel=USART1_IRQn;//通道为USART1
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=3;
	NVIC_InitStructure.NVIC_IRQChannelSubPriority=3;
	NVIC_InitStructure.NVIC_IRQChannelCmd=ENABLE;
	
	NVIC_Init(&NVIC_InitStructure);
}

DMA配置:

void DMA_Configuration(void)
{
			DMA_InitTypeDef DMA_InitStructure;
			 
			DMA_DeInit(DMA1_Channel5);
			RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1,ENABLE);//时钟使能AHB
			DMA_InitStructure.DMA_PeripheralBaseAddr=(u32)&(ADC1->DR);//DMA的外设基地址
			DMA_InitStructure.DMA_MemoryBaseAddr=(u32)(ADC1_Buffer_RX);//DMA的内存基地址
			DMA_InitStructure.DMA_DIR=DMA_DIR_PeripheralSRC;//以外设作为数据源
			DMA_InitStructure.DMA_BufferSize=PACKSIZE;缓存区大小为PACKSIZE字节
			DMA_InitStructure.DMA_MemoryInc=DMA_MemoryInc_Disable;//禁止内存地址自加
			DMA_InitStructure.DMA_PeripheralInc=DMA_PeripheralInc_Disable;//禁止外设地址自加
			DMA_InitStructure.DMA_MemoryDataSize=DMA_MemoryDataSize_Byte;
			DMA_InitStructure.DMA_PeripheralDataSize=DMA_PeripheralDataSize_Byte;
			DMA_InitStructure.DMA_M2M=DMA_M2M_Disable;//禁止内存到内存的模式
			DMA_InitStructure.DMA_Mode=DMA_Mode_Normal;//正常模式另外一种为循环模式
			DMA_InitStructure.DMA_Priority=DMA_Priority_High;//优先组为高
			DMA_Init(DMA1_Channel5,&DMA_InitStructure);//初始化通道5,因为USART1在通道5上
			
			 
			
			DMA_Cmd(DMA1_Channel5,ENABLE);使能通道5
}

主函数:

#define PACKSIZE    50
int flag;

u8 USART1_Buffer_RX[PACKSIZE];

int main(void)
 {

	GPIO_Configuration();	
	USART_Configuration();
	Delay_init();
	NVIC_Configuration();
//	 Buffer_Init();
	 DMA_Configuration();
	 
	 USART_DMACmd(USART1,USART_DMAReq_Rx,ENABLE);//USART请求接收输入
	 
		printf("hello:\n");
		while(1)
		{		
			if(flag==1)
			{
			printf("%s\n",USART1_Buffer_RX);
			flag=0;
			}				
		}
}

中断服务程序:

void USART1_IRQHandler(void)
{
	u8 abu;
	if(USART_GetITStatus(USART1,USART_IT_IDLE)==SET)
	{
				flag=1;
				abu=USART1->SR;
				abu=USART1->DR;		//软件序列清除空闲IDLE位
		
			DMA_Cmd(DMA1_Channel5,DISABLE);//必须关闭通道5才能进行重新设置
		
	
			abu=128-DMA_GetCurrDataCounter(DMA1_Channel5);//128减去最近接收的数据长度
			USART1_Buffer_RX[abu]=0;
			
			DMA1_Channel5->CNDTR=PACKSIZE;
			DMA_SetCurrDataCounter(DMA1_Channel5,PACKSIZE);								
			DMA_Cmd(DMA1_Channel5,ENABLE);//设置数据长度完成重新开启DMA通道5
						
	}

}

测试截图
整了一天发篇文章记录一下。。。。。。。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值