【stm32f103】USART RX实现(寄存器版)

本讲主要实现usart RX的实现,主要分几部分的应用

1.      USART 1 RX polling的实现

2.      USART1 RX DMA的实现

3.      USART1 RX DMA中断的实现

4. 配合着TIMER进行RX DMA中断实现实现(用途很大)

本文章不在对寄存器贴图,直接上代码以及运行图,有兴趣的可以去调试下看看寄存器,以下历程都必须调用Init函数,Init函数源码

void USART1_Init()
{
	/* 1. ENABLE USART1 GPIOA CLOCK */
	RCC->APB2ENR |= RCC_APB2ENR_IOPAEN;
	/* 2. ENABLE USART1 IN APB2 BUS CLOCK */
	RCC->APB2ENR |= RCC_APB2ENR_USART1EN;
	/* 3. CONFIG GPIOA PA9 AF MODE */
	GPIOA->CRH &= ~(GPIO_CRH_MODE9 | GPIO_CRH_CNF9);
	GPIOA->CRH |= GPIO_CRH_MODE9 | GPIO_CRH_CNF9_1;
	
	GPIOA->CRH &= ~(GPIO_CRH_MODE10 | GPIO_CRH_CNF10);
	GPIOA->CRH |= GPIO_CRH_CNF10_1;
	/* 4. CONFIG USART1 BAUD RATE 115200 */
	USART1->BRR |= 0x271;
	/* 5. ENBALE TRANSPORT AND ENABLE USART1 */
	USART1->CR1 |= USART_CR1_UE | USART_CR1_TE | USART_CR1_RE;
	
}

例1:USART1 RX Polling实现

代码:

void USART1_RX_Polling()
{
	int index = 0;
	
	while(1)
	{
		if((USART1->SR & USART_SR_RXNE) != 0)
		{
			if(index > 50)
				break;
			buffer[index++] = USART1->DR;
		}
	}
	printf("receive :%s",buffer);
}

运行效果图,直到收到index >50,会整个打印出来

例2:USART1 RX DMA的实现,源码:

void USART1_RX_DMA()
{
	RCC->AHBENR |= RCC_AHBENR_DMA1EN;
	USART1->CR3 |= USART_CR3_DMAR;
	
	/* 6. CONFIG DMA */
	DMA1_Channel5->CMAR = (uint32_t)buffer;
	DMA1_Channel5->CPAR = (uint32_t)&USART1->DR;
	DMA1_Channel5->CNDTR = 20;
	DMA1_Channel5->CCR |= DMA_CCR5_PL | DMA_CCR5_MINC | DMA_CCR5_EN;
	
	while(DMA1_Channel5->CNDTR != 0);
	
	printf("RX :%s\n",buffer);
}

运行效果图,DMA搬运20个数据,等待搬运完成,就会打印出来

例3:USART1 RX DMA中断的实现

程序源码:

void DMA1_Channel5_IRQHandler(void)
{
	TIM2->EGR = TIM_EGR_UG;
	TIM2->SR &= ~TIM_SR_UIF;
	NVIC_ClearPendingIRQ(TIM2_IRQn);
	if (DMA1->ISR & DMA_ISR_HTIF5)
	{
		DMA1->IFCR = DMA_IFCR_CHTIF5;
		printf("HTIF: %d\n", DMA1_Channel5->CNDTR);
	}
	
	if (DMA1->ISR & DMA_ISR_TCIF5)
	{
		DMA1->IFCR = DMA_IFCR_CTCIF5;
		printf("TCIF: %d\n", DMA1_Channel5->CNDTR);
	}
}
void USART1_RX_DMA_IRPT()
{
	
	NVIC_SetPriorityGrouping(4);
	
	NVIC_SetPriority(DMA1_Channel5_IRQn, 1);
	RCC->AHBENR |= RCC_AHBENR_DMA1EN;
	USART1->CR3 |= USART_CR3_DMAR;
	
	/* 6. CONFIG DMA */
	DMA1_Channel5->CMAR = (uint32_t)buffer;
	DMA1_Channel5->CPAR = (uint32_t)&USART1->DR;
	DMA1_Channel5->CNDTR = 20;
	DMA1_Channel5->CCR |= DMA_CCR5_PL | DMA_CCR5_MINC | DMA_CCR5_EN | DMA_CCR5_HTIE | DMA_CCR5_TCIE;
	NVIC_EnableIRQ(DMA1_Channel5_IRQn);
	
	
	while(1);
}
运行图,从串口发送数据,不光发送多少个,发送10个时候,会触发发送一半中断,发送到20个的时候,会触发发送完成中断
例4: 配合着TIMER进行RX DMA中断实现实现
源码:
void TIM2_IRQHandler(void)
{
	TIM2->SR &= ~TIM_SR_UIF;
	
	printf("timeout! CNDTR=%d\n", DMA1_Channel5->CNDTR);
}

void Time2_Enable(int arr,int psc)
{
	RCC->APB1ENR = RCC_APB1ENR_TIM2EN; // 72M clock
	
	TIM2->ARR = arr;
	TIM2->PSC = psc;
	
	TIM2->EGR = TIM_EGR_UG;
	
	TIM2->CR1 = TIM_CR1_URS;
	TIM2->DIER = TIM_DIER_UIE;
	TIM2->CR1 |= TIM_CR1_CEN;
	NVIC_SetPriority(TIM2_IRQn, 1);
	NVIC_EnableIRQ(TIM2_IRQn);
}
void DMA1_Channel5_IRQHandler(void)
{
	TIM2->EGR = TIM_EGR_UG;
	TIM2->SR &= ~TIM_SR_UIF;
	NVIC_ClearPendingIRQ(TIM2_IRQn);
	if (DMA1->ISR & DMA_ISR_HTIF5)
	{
		DMA1->IFCR = DMA_IFCR_CHTIF5;
		printf("HTIF: %d\n", DMA1_Channel5->CNDTR);
	}
	
	if (DMA1->ISR & DMA_ISR_TCIF5)
	{
		DMA1->IFCR = DMA_IFCR_CTCIF5;
		printf("TCIF: %d\n", DMA1_Channel5->CNDTR);
	}
}


void USART1_RX_DMA_IRPT()
{
	
	NVIC_SetPriorityGrouping(4);
	
	NVIC_SetPriority(DMA1_Channel5_IRQn, 1);
	RCC->AHBENR |= RCC_AHBENR_DMA1EN;
	USART1->CR3 |= USART_CR3_DMAR;
	
	/* 6. CONFIG DMA */
	DMA1_Channel5->CMAR = (uint32_t)buffer;
	DMA1_Channel5->CPAR = (uint32_t)&USART1->DR;
	DMA1_Channel5->CNDTR = 20;
	DMA1_Channel5->CCR |= DMA_CCR5_PL | DMA_CCR5_MINC | DMA_CCR5_EN | DMA_CCR5_HTIE | DMA_CCR5_TCIE;
	NVIC_EnableIRQ(DMA1_Channel5_IRQn);
	
	
	while(1);
}
运行效果图,timer每2S触发一次中断,打印DMA还需要传输多少数据才能完成,知道串口发送完20byte数据

发布了200 篇原创文章 · 获赞 548 · 访问量 76万+

猜你喜欢

转载自blog.csdn.net/XiaoXiaoPengBo/article/details/77479359