本文介绍,通过中断方式运用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));
}
}