STM32基础设计(3)---中断串口通信

本文介绍,通过中断方式运用STM32串口USART1。

首先,总结全文,设计步骤主要如下:

1,初始化GPIO

2,初始化USART1

3,初始化NVIC(嵌套向量中断控制器)

4,编写中断服务函数

5,编写主函数

详细步骤如下:

1,初始化GPIO

void IO_Init()
{
	GPIO_InitTypeDef Uart_A;
	GPIO_InitTypeDef led;
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_GPIOC| RCC_APB2Periph_AFIO,ENABLE);
	
	GPIO_PinRemapConfig(GPIO_Remap_SWJ_Disable|GPIO_Remap_SWJ_JTAGDisable,ENABLE);
	
	led.GPIO_Pin = GPIO_Pin_13;//博主开发板上的LED灯接的GPIOC的13引脚
	led.GPIO_Mode = GPIO_Mode_Out_PP;
	led.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOC,&led);
	
	Uart_A.GPIO_Pin = GPIO_Pin_9;
	Uart_A.GPIO_Speed = GPIO_Speed_50MHz;
	Uart_A.GPIO_Mode = GPIO_Mode_AF_PP;
	GPIO_Init(GPIOA,&Uart_A);
	
	Uart_A.GPIO_Pin = GPIO_Pin_10;
	Uart_A.GPIO_Speed = GPIO_Speed_50MHz;
	Uart_A.GPIO_Mode = GPIO_Mode_IN_FLOATING; 
	GPIO_Init(GPIOA,&Uart_A);
	
}

以上代码不在详细介绍,前参看STM32基础设计(1)---点亮LED灯、SEM32基础设计(2)---查询串口通信

2,初始化USART1

void Usart1_Init()
{
	USART_InitTypeDef Uart;
	
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1,ENABLE);
	Uart.USART_BaudRate = 115200;
	Uart.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
	Uart.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
	Uart.USART_Parity = USART_Parity_No;
	Uart.USART_StopBits = USART_StopBits_1;
	Uart.USART_WordLength = USART_WordLength_8b;
	USART_Init(USART1,&Uart);
	
	USART_Cmd(USART1,ENABLE);
	USART_ClearFlag(USART1,USART_FLAG_TC); 
}

以上代码不在详细介绍,具体请参看STM32基础设计(2)---查询串口通信

3,初始化NVIC

首先,让我们来了解库函数中的NVIC结构体:

typedef struct
{//指明那个中断通道
  uint8_t NVIC_IRQChannel;                    /*!< Specifies the IRQ channel to be enabled or disabled.
                                                   This parameter can be a value of @ref IRQn_Type 
                                                   (For the complete STM32 Devices IRQ Channels list, please
                                                    refer to stm32f10x.h file) */
//抢占优先级
  uint8_t NVIC_IRQChannelPreemptionPriority;  /*!< Specifies the pre-emption priority for the IRQ channel
                                                   specified in NVIC_IRQChannel. This parameter can be a value
                                                   between 0 and 15 as described in the table @ref NVIC_Priority_Table */
//子优先级
  uint8_t NVIC_IRQChannelSubPriority;         /*!< Specifies the subpriority level for the IRQ channel specified
                                                   in NVIC_IRQChannel. This parameter can be a value
                                                   between 0 and 15 as described in the table @ref NVIC_Priority_Table */
//中断通道使能
  FunctionalState NVIC_IRQChannelCmd;         /*!< Specifies whether the IRQ channel defined in NVIC_IRQChannel
                                                   will be enabled or disabled. 
                                                   This parameter can be set either to ENABLE or DISABLE */   
} NVIC_InitTypeDef;

了解了这个结构体后,就可以在初始化函数中定义这个变量了

NVIC_InitTypeDef nvic;

另外在NVIC初始化中还设置优先级分组(哪怕只有一个中断也要分组,这是规定)。具体使用这个库函数:

void NVIC_PriorityGroupConfig(uint32_t NVIC_PriorityGroup)
{
  /* Check the parameters */
  assert_param(IS_NVIC_PRIORITY_GROUP(NVIC_PriorityGroup));
  
  /* Set the PRIGROUP[10:8] bits according to NVIC_PriorityGroup value */
  SCB->AIRCR = AIRCR_VECTKEY_MASK | NVIC_PriorityGroup;
}

关于优先级分组此处不再赘述,请大家参考这位博主的博客:

http://blog.csdn.net/DLUTXIE/article/details/7059184?locationNum=4&fps=1

接下来,设置结构体中变量的值:

nvic.NVIC_IRQChannelPreemptionPriority = 1;//抢占优先级
nvic.NVIC_IRQChannelSubPriority = 0;//子优先级
nvic.NVIC_IRQChannel = USART1_IRQn;//中断通道
nvic.NVIC_IRQChannelCmd = ENABLE;//通道使能
NVIC_Init(&nvic);//NVIC寄存器初始化

4,编写中断服务函数

先贴代码,在解释

void USART1_IRQHandler(void)//注意,这个函数名必须这样写,否则进不了USART1中断。详见库函数中的  IRQn_Type 结构体
{
	char temp= '0';
	if(USART_GetFlagStatus(USART1,USART_FLAG_RXNE) == SET)//判断是否接收到数据
	{
		temp = USART1->DR;//如果接收到数据,就将其读出,这样才可将RXNE寄存器清除
		if(temp == 'G')//如果接收到G  则关灯
		{
			GPIOC->BRR = GPIO_Pin_13;
		}else if(temp == 'K')//开灯
		{
			GPIOC->BSRR = GPIO_Pin_13;
		}
	}
		if(USART_GetFlagStatus(USART1,USART_FLAG_TXE) && temp != '0')//如果发送寄存器为空,即可以发送数据
		{
			USART1->DR = temp;将接收到的数据再发送回去
			while(!USART_GetFlagStatus(USART1,USART_FLAG_TC));等待数据发送完毕
		}
}

5,编写主函数

老规矩,先贴代码再解释:

int main()
{
	IO_Init();
	Usart1_Init();
	Nvic_Init();
	USART_ITConfig(USART1,USART_IT_RXNE,ENABLE);//这里是打开串口的接收中断,以便在USART1收到数据时,进入中断函数。这里特别提一下,现在不用打开发送中断,只有在准备发送数据时才应打开,否则会直接进入中断函数。
	GPIOC->BSRR = GPIO_Pin_13;
	while(1){}
}

额。。。突然发现没什么好解释的。

中断串口通信介绍到此完毕。

本文完整代码如下:

#include<stm32f10x.h>
#define uint unsigned int
#define uchar unsigned char
void delay(uint n)
{
	int i,j;
	for(i=0;i<n;i++)
	for(j=0;j<8500;j++);
}

void IO_Init()
{
	GPIO_InitTypeDef Uart_A;
	GPIO_InitTypeDef led;
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_GPIOC| RCC_APB2Periph_AFIO,ENABLE);
	
	GPIO_PinRemapConfig(GPIO_Remap_SWJ_Disable|GPIO_Remap_SWJ_JTAGDisable,ENABLE);
	
	led.GPIO_Pin = GPIO_Pin_13;
	led.GPIO_Mode = GPIO_Mode_Out_PP;
	led.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOC,&led);
	
	Uart_A.GPIO_Pin = GPIO_Pin_9;
	Uart_A.GPIO_Speed = GPIO_Speed_50MHz;
	Uart_A.GPIO_Mode = GPIO_Mode_AF_PP;
	GPIO_Init(GPIOA,&Uart_A);
	
	Uart_A.GPIO_Pin = GPIO_Pin_10;
	Uart_A.GPIO_Speed = GPIO_Speed_50MHz;
	Uart_A.GPIO_Mode = GPIO_Mode_IN_FLOATING; //page 110
	GPIO_Init(GPIOA,&Uart_A);
	
}
void Usart1_Init()
{
	USART_InitTypeDef Uart;
	
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1,ENABLE);
	Uart.USART_BaudRate = 115200;
	Uart.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
	Uart.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
	Uart.USART_Parity = USART_Parity_No;
	Uart.USART_StopBits = USART_StopBits_1;
	Uart.USART_WordLength = USART_WordLength_8b;
	USART_Init(USART1,&Uart);
	
	USART_Cmd(USART1,ENABLE);
	USART_ClearFlag(USART1,USART_FLAG_TC); //page 540
}
void Nvic_Init()
{
	NVIC_InitTypeDef nvic;
	
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);
	
	nvic.NVIC_IRQChannelPreemptionPriority = 1;
	nvic.NVIC_IRQChannelSubPriority = 0;
	nvic.NVIC_IRQChannel = USART1_IRQn;
	nvic.NVIC_IRQChannelCmd = ENABLE;
	NVIC_Init(&nvic);
}

int main()
{
	IO_Init();
	Usart1_Init();
	Nvic_Init();
	USART_ITConfig(USART1,USART_IT_RXNE,ENABLE);
	GPIOC->BSRR = GPIO_Pin_13;
	while(1){}
}

void USART1_IRQHandler(void)
{
	char temp= '0';
	if(USART_GetFlagStatus(USART1,USART_FLAG_RXNE) == SET)
	{
		temp = USART1->DR;
		if(temp == 'G')
		{
			GPIOC->BRR = GPIO_Pin_13;
		}else if(temp == 'K')
		{
			GPIOC->BSRR = GPIO_Pin_13;
		}
	}
		if(USART_GetFlagStatus(USART1,USART_FLAG_TXE) && temp != '0')
		{
			USART1->DR = temp;
			while(!USART_GetFlagStatus(USART1,USART_FLAG_TC));
		}
}

猜你喜欢

转载自blog.csdn.net/aa867734398/article/details/79640665