一、STM32中断是什么?
STM32有84个中断,包括16个内核中断和68个可屏蔽中断,具有16级可编程中断优先级。
STM32F103在内核水平上搭载了一个异常响应系统,支持为数众多的系统异常和外部中断。
中断是一种重要的机制,用于处理实时事件和优先级任务。通过使用中断,可以在程序执行期间立即响应外部事件,而无需不断轮询检查状态
二、STM32中断
1.任务要求
要求为:用stm32F103核心板的GPIOA端一管脚接一个LED,GPIOB端口一引脚接一个开关(用杜邦线模拟代替)。采用中断模式编程,当开关接高电平时,LED亮灯;接低电平时,LED灭灯。如果完成后,尝试在main函数while循环中加入一个串口每隔1s 发送一次字符的代码片段,观察按键中断对串口发送是否会带来干扰或延迟。
2.任务代码
其中main代码如下:
#include "stm32f10x.h"
#include "exti_key.h"
uint8_t led =1;
void GPIO_Configuration(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOA , ENABLE);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_Init(GPIOA, &GPIO_InitStructure);
}
void delay_ms(uint16_t time)
{
uint16_t i = 0;
while(time--)
{
i = 10000;
while(i--);
}
}
int main(void)
{
GPIO_Configuration();
delay_ms(1000);
GPIO_ResetBits(GPIOB,GPIO_Pin_5);
EXTI_Key_Init();
while(1)
{
}
}
void EXTI15_10_IRQHandler(void)
{
if(EXTI_GetITStatus(EXTI_Line14) != RESET)
{
led = ~led; //状态翻转
//如果等于1,则PB5复位点亮,否则置1熄灭
if(led == 1)
GPIO_ResetBits(GPIOA,GPIO_Pin_0);
else
GPIO_SetBits(GPIOA,GPIO_Pin_0);
}
EXTI_ClearITPendingBit(EXTI_Line14);
}
exti_key.c代码如下:
#include "exti_key.h"
#include "misc.h"
void EXTI_Key_Init(void)
{
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB|RCC_APB2Periph_AFIO,ENABLE);
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_14;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOB,&GPIO_InitStructure);
GPIO_EXTILineConfig(GPIO_PortSourceGPIOB,GPIO_PinSource14);
NVIC_InitTypeDef NVIC_InitStructure;
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
NVIC_InitStructure.NVIC_IRQChannel = EXTI15_10_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
EXTI_InitTypeDef EXTI_InitStructure;
EXTI_InitStructure.EXTI_Line = EXTI_Line14;
EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;
EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling;
EXTI_InitStructure.EXTI_LineCmd = ENABLE;
EXTI_Init(&EXTI_InitStructure);
}
exti_key.h代码如下:
#ifndef __EXTI_KEY_H
#define __EXTI_KEY_H
#include "stm32f10x.h"
void EXTI_Key_Init(void);
#endif
3.运行效果
运行效果如下:
三、串口通信
1.任务要求1
任务要求为:(1)当stm32接收到1个字符“s”时,停止持续发送“hello windows!”; 当接收到1个字符“t”时,持续发送“hello windows!”(提示:采用一个全局标量做信号灯)
2.任务代码
main代码如下:
#include "stm32f10x.h"
#include "Serial.h"
#include <string.h>
uint8_t RxData;
void delay_ms(uint16_t time)
{
uint16_t i = 0;
while(time--)
{
i = 10000;
while(i--);
}
}
int main(void)
{
Serial_Init();
uint8_t data[]={'h','e','l','l','o',' ','w','i','n','d','o','w','s','!'};
while(1)
{
if(Serial_GetRxFlag()==1)
{
RxData=Serial_GetRxData();
}
if(RxData=='s')
{
Serial_SendArray(data,14);
delay_ms(1000);
}
}
}
.h代码如下:
#ifndef __SERIAL_H
#define __SERIAL_H
#include <stdio.h>
void Serial_Init(void);
void Serial_SendByte(uint8_t Byte);
void Serial_SendArray(uint8_t* Array, uint16_t Length);
uint8_t Serial_GetRxFlag(void);
uint8_t Serial_GetRxData(void);
#endif
.c代码如下:
#include "stm32f10x.h"
#include <stdio.h>
#include <stdarg.h>
uint8_t Serial_RxData;
uint8_t Serial_RxFlag;
void Serial_Init(void)
{
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1,ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_Init(GPIOA, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
GPIO_Init(GPIOA, &GPIO_InitStructure);
USART_InitTypeDef USART_InitStructure;
USART_InitStructure.USART_BaudRate=9600;
USART_InitStructure.USART_HardwareFlowControl=USART_HardwareFlowControl_None;
USART_InitStructure.USART_Mode=USART_Mode_Tx|USART_Mode_Rx;
USART_InitStructure.USART_Parity=USART_Parity_No;
USART_InitStructure.USART_StopBits=USART_StopBits_1;
USART_InitStructure.USART_WordLength=USART_WordLength_8b;
USART_Init(USART1,&USART_InitStructure);
USART_ITConfig(USART1,USART_IT_RXNE,ENABLE);
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
NVIC_InitTypeDef NVIC_InitStructure;
NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
USART_Cmd(USART1,ENABLE);
}
void Serial_SendByte(uint8_t Byte)
{
USART_SendData(USART1,Byte);
while(USART_GetFlagStatus(USART1,USART_FLAG_TXE)==RESET);
}
void Serial_SendArray(uint8_t* Array, uint16_t Length)
{
uint16_t i;
for(i=0;i<Length;i++)
{
Serial_SendByte(Array[i]);
}
}
uint8_t Serial_GetRxFlag(void)
{
if(Serial_RxFlag==1)
{
Serial_RxFlag=0;
return 1;
}
return 0;
}
uint8_t Serial_GetRxData(void)
{
return Serial_RxData;
}
void USART1_IRQHandler(void)
{
if(USART_GetITStatus(USART1,USART_IT_RXNE)==SET)
{
Serial_RxData=USART_ReceiveData(USART1);
Serial_RxFlag=1;
USART_ClearITPendingBit(USART1,USART_IT_RXNE);
}
}
3.任务要求二
要求为:当stm32接收到字符“stop stm32!”时,停止持续发送“hello windows!”; 当接收到字符“go stm32!”时,持续发送“hello windows!”
4.任务代码
main代码如下:
#include "stm32f10x.h"
#include "Serial.h"
#include <string.h>
#include <stdio.h>
uint8_t RxData=0;
void delay_ms(uint16_t time)
{
uint16_t i = 0;
while(time--)
{
i = 10000;
while(i--);
}
}
int main(void)
{
Serial_Init();
uint8_t data[]={'h','e','l','l','o',' ','w','i','n','d','o','w','s','!'};
while(1)
{
if(Serial_GetRxFlag()==1)
{
if (strcmp(Serial_RxPacket,"go stm32!")==0)
{
RxData=1;
}
else
RxData=0;
}
if(RxData==1)
{
Serial_SendArray(data,14);
delay_ms(1000);
}
}
}
.h代码如下:
#ifndef __SERIAL_H
#define __SERIAL_H
#include <stdio.h>
extern char Serial_RxPacket[];
void Serial_Init(void);
void Serial_SendByte(uint8_t Byte);
void Serial_SendArray(uint8_t* Array, uint16_t Length);
void Serial_SendString(char *String);
uint8_t Serial_GetRxFlag(void);
#endif
.c代码如下:
#include "stm32f10x.h"
#include <stdio.h>
#include <stdarg.h>
char Serial_RxPacket[100];
uint8_t Serial_RxFlag;
void Serial_Init(void)
{
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1,ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_Init(GPIOA, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
GPIO_Init(GPIOA, &GPIO_InitStructure);
USART_InitTypeDef USART_InitStructure;
USART_InitStructure.USART_BaudRate=9600;
USART_InitStructure.USART_HardwareFlowControl=USART_HardwareFlowControl_None;
USART_InitStructure.USART_Mode=USART_Mode_Tx|USART_Mode_Rx;
USART_InitStructure.USART_Parity=USART_Parity_No;
USART_InitStructure.USART_StopBits=USART_StopBits_1;
USART_InitStructure.USART_WordLength=USART_WordLength_8b;
USART_Init(USART1,&USART_InitStructure);
USART_ITConfig(USART1,USART_IT_RXNE,ENABLE);
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
NVIC_InitTypeDef NVIC_InitStructure;
NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
USART_Cmd(USART1,ENABLE);
}
void Serial_SendByte(uint8_t Byte)
{
USART_SendData(USART1,Byte);
while(USART_GetFlagStatus(USART1,USART_FLAG_TXE)==RESET);
}
void Serial_SendArray(uint8_t* Array, uint16_t Length)
{
uint16_t i;
for(i=0;i<Length;i++)
{
Serial_SendByte(Array[i]);
}
}
void Serial_SendString(char *String)
{
uint8_t i;
for(i=0;String[i]!='\0';i++)
{
Serial_SendByte(String[i]);
}
}
uint8_t Serial_GetRxFlag(void)
{
if(Serial_RxFlag==1)
{
Serial_RxFlag=0;
return 1;
}
return 0;
}
void USART1_IRQHandler(void)
{
static uint8_t RxState=0;
static uint8_t pRxPacket=0;
if(USART_GetITStatus(USART1,USART_IT_RXNE)==SET)
{
uint8_t RxData=USART_ReceiveData(USART1);
if(RxState==0)
{
if(RxData=='@')
{
RxState=1;
pRxPacket=0;
}
}
else if(RxState==1)
{
if(RxData=='\r')
{
RxState=2;
}
else
{
Serial_RxPacket[pRxPacket]=RxData;
pRxPacket++;
}
}
else if(RxState==2)
{
if(RxData=='\n')
{
RxState=0;
Serial_RxPacket[pRxPacket]='\0';
Serial_RxFlag=1;
}
}
USART_ClearITPendingBit(USART1,USART_IT_RXNE);
}
}
四、总结
本次实验学习了中断函数和串口通信的知识,本次学到最多的是了解了开发板上的接口所对应的GPIO的接口数,以及所对应的EXTI接口。