一、中断系统介绍
1.中断流程
中断处理流程:中断请求、中断响应、中断服务和中断返回
2.STM32外部中断EXT
EXTI(External interrupt/event controller,外部中断/事件控制器)支持19个外部中断/事件请求,每个中断/事件都有独立的触发和屏蔽设置,具有中断模式和事件模式两种设置模式。
二、实验项目
1)用stm32F103核心板的GPIOA端一管脚接一个LED,GPIOB端口一引脚接一个开关(用杜邦线模拟代替)。采用中断模式编程,当开关接高电平时,LED亮灯;接低电平时,LED灭灯。如果完成后,尝试在main函数while循环中加入一个串口每隔1s 发送一次字符的代码片段,观察按键中断对串口发送是否会带来干扰或延迟。
代码:
main.c
#include "stm32f10x.h"
#include "led.h"
#include "exti_key.h"
int main(void)
{
LED_Init();
GPIO_ResetBits(GPIOB,GPIO_Pin_5);
EXTI_Key_Init();
while(1)
{
}
}
void EXTI3_IRQHandler(void)
{
if(EXTI_GetITStatus(EXTI_Line3) != RESET)
{
GPIO_WriteBit(GPIOB,GPIO_Pin_5,(BitAction)((1-GPIO_ReadOutputDataBit(GPIOB,GPIO_Pin_5))));
EXTI_ClearITPendingBit(EXTI_Line3);
}
}
exti_key.c
#include "exti_key.h"
#include "misc.h"
void EXTI_Key_Init(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOE|RCC_APB2Periph_AFIO,ENABLE);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
GPIO_Init(GPIOE,&GPIO_InitStructure);
NVIC_InitTypeDef NVIC_InitStructure;
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
NVIC_InitStructure.NVIC_IRQChannel = EXTI3_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
EXTI_InitTypeDef EXTI_InitStructure;
EXTI_ClearITPendingBit(EXTI_Line3);
GPIO_EXTILineConfig(GPIO_PortSourceGPIOA,GPIO_PinSource3);
EXTI_InitStructure.EXTI_Line = EXTI_Line3;
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
结果:
2)采用串口中断方式重做上周查询方式的串口通信作业,分别实现:
(1)当stm32接收到1个字符“s”时,停止持续发送“hello windows!”; 当接收到1个字符“t”时,持续发送“hello windows!”(提示:采用一个全局标量做信号灯);
代码:
#include "stm32f10x.h"
int send=0;//?????
void Delay(__IO uint32_t nCount) {
for(; nCount != 0; nCount--);
}
void hellowindows()
{
if(send==1)
{
int i;
char a [14]={'h','e','l','l','o','w','i','n','d','o','w','s','!',' '};
for (i = 0; i < 14; i++)
{
USART_SendData(USART1,a[i]);
while (USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET);
}
Delay(1);
}
}
void USART1_IRQHandler(void)
{
if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET)
{
uint8_t receivedChar = USART_ReceiveData(USART1);
if (receivedChar == 's')
{
send = 0;
}
else if (receivedChar == 't')
{
send = 1;
}
}
}
int main(void)
{
USART_InitTypeDef USART_InitStructure;
// 1,????---GPIOA(??1),AFIO
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1|RCC_APB2Periph_GPIOA,ENABLE);
// 2,GPIO???
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_Mode=GPIO_Mode_IN_FLOATING;
GPIO_Init(GPIOA,&GPIO_InitStructure);
// 3,?????
USART_InitStructure.USART_BaudRate = 9600;
USART_InitStructure.USART_WordLength= USART_WordLength_8b;
USART_InitStructure.USART_StopBits= USART_StopBits_1;
USART_InitStructure.USART_Parity = USART_Parity_No;
USART_InitStructure.USART_Mode=USART_Mode_Tx|USART_Mode_Rx;
USART_InitStructure.USART_HardwareFlowControl=USART_HardwareFlowControl_None;
USART_Init(USART1, &USART_InitStructure);
USART_ClearFlag(USART1, USART_FLAG_TC);
// ?????
USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);//?USART??????????,???USART??
// 4.??????????????????????
NVIC_InitTypeDef NVIC_InitStructure;
NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=3; //????(?)???
NVIC_InitStructure.NVIC_IRQChannelSubPriority =3; // ??????
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
// 5,????
USART_Cmd(USART1, ENABLE);
while(1)
{
hellowindows();
}
}
结果:
(2)当stm32接收到字符“stop stm32!”时,停止持续发送“hello windows!”; 当接收到字符“go stm32!”时,持续发送“hello windows!”(提示:要将接收到的连续字符保存到一个字符数组里,进行判别匹配。写一个接收字符串的函数。
代码:
#include "stm32f10x.h"
int send=0;//????,????
int count=0;//????,???????????
char data[100];//?????
void Delay(__IO uint32_t nCount) {
for(; nCount != 0; nCount--);
}
void receive_data_init()//????????
{
count=0;
for(int i=0;i<11;i++)
{
data[i]=0;
}
}
void hellowindows()
{
if(send==1)
{
int i;
char a [14]={'h','e','l','l','o','w','i','n','d','o','w','s','!',' '};
for (i = 0; i < 14; i++)
{
USART_SendData(USART1,a[i]);
while (USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET);
}
Delay(100000);
}
}
void USART1_IRQHandler(void)
{
if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET)
{
data[count]= USART_ReceiveData(USART1);
count++;
}
}
int main(void)
{
USART_InitTypeDef USART_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1|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_Mode=GPIO_Mode_IN_FLOATING;
GPIO_Init(GPIOA,&GPIO_InitStructure);
USART_InitStructure.USART_BaudRate = 9600;
USART_InitStructure.USART_WordLength= USART_WordLength_8b;
USART_InitStructure.USART_StopBits= USART_StopBits_1;
USART_InitStructure.USART_Parity = USART_Parity_No;
USART_InitStructure.USART_Mode=USART_Mode_Tx|USART_Mode_Rx;
USART_InitStructure.USART_HardwareFlowControl=USART_HardwareFlowControl_None;
USART_Init(USART1, &USART_InitStructure);
USART_ClearFlag(USART1, USART_FLAG_TC);
// ?????
USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);//?USART??????????,???USART??
// 4.??????????????????????
NVIC_InitTypeDef NVIC_InitStructure;
NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=3; //????(?)???
NVIC_InitStructure.NVIC_IRQChannelSubPriority =3; // ??????
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
// 5,????
USART_Cmd(USART1, ENABLE);
//-----------------------------------------------(??)---------------------------------------------------
receive_data_init();//????????
while(1)
{
hellowindows();
if(strcmp(data,"stop stm32!")==0)
{
send = 0;
receive_data_init();
}
else if(strcmp(data,"go stm32!")==0)
{
send = 0;
receive_data_init();
}
else if(strcmp(data,"go stm32!")==0)
{
send = 0;
receive_data_init();
}
}
}
结果:
三、总结
本次实验初步认识并使用stm32的中断系统,如有错误还望指正。