中断编程入门

(一)学习stm32中断原理和开发编程方法

1.STM32中断的工作原理如下:
中断源:STM32芯片内部或外部的各种外设、模块或传感器都可以作为中断源,当其中的某个事件发生时,会触发相应的中断请求。
中断控制器:STM32芯片内部集成了一个中断控制器(Nested Vectored Interrupt Controller,NVIC),用于管理和分配中断优先级以及处理器的中断向量表。
中断优先级:每个中断源都具有一个优先级,用于确定中断的相对重要性。优先级较高的中断将被优先处理。
中断向量表:中断向量表是一个存储中断处理函数地址的表格,每个中断源都有一个与之对应的中断向量。当中断请求发生时,处理器会根据中断号查找中断向量表,找到相应的中断处理函数的地址,并跳转到该地址开始执行中断服务程序。
中断服务程序:中断服务程序是由用户编写的处理中断事件的代码段。一旦中断被触发,处理器会暂停当前任务,跳转到中断服务程序,执行相应的操作。在中断服务程序执行完毕后,处理器会返回到之前的任务继续执行。
2.用stm32F103核心板的GPIOA端一管脚接一个LED,GPIOB端口一引脚接一个开关(用杜邦线模拟代替)。采用中断模式编程,当开关接高电平时,LED亮灯;接低电平时,LED灭灯。
led.c文件源码如下:

#include "stm32f10x.h"                  // Device header
#include "LED.h"
​
void LED_Init(void)
{
    GPIO_InitTypeDef GPIO_InitStructure;//定义一个GPIO_InitTypeDef类型的结构体变量
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);//开启GPIOB时钟
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5;//选择PB5所以引脚
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;//设置引脚输出模式为浮空输入
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;//设置输出速度为50MHz
    GPIO_Init(GPIOB,&GPIO_InitStructure);//调用初始化库函数初始化GPIOB端口
}

led.h文件

#ifndef __LED_H
#define __LED_H
#include "stm32f10x.h"                  // Device header
​
void LED_Init(void);
​
#endif

exti_key.h文件

#ifndef __EXTI_KEY_H
#define __EXTI_KEY_H
#include "stm32f10x.h"
void EXTI_Key_Init(void);
#endif

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_PortSourceGPIOE,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);
}

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);
    }
}

效果图如下:
在这里插入图片描述

(二)采用串口中断方式

1.当stm32接收到1个字符“s”时,停止持续发送“hello windows!”; 当接收到1个字符“t”时,持续发送“hello windows!”(提示:采用一个全局标量做信号灯。

#include "stm32f10x.h"                 
#include "Delay.h"
int send=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_s(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"                 
#include "Delay.h"
int send=0;//全局变量,记录状态
int count=0;//全局变量,表示缓冲区的数组的下标
char  receive_data[11];//接收缓存区
void  receive_data_init()//接收缓存区初始化
{
	count=0;
	for(int i=0;i<11;i++)
	{
		receive_data[i]=0;
	}
}
void hellowindows()
{
	if(send==1)//当send为1,输出hellowindows!
	{
	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_s(1);//延时1s
  }
}
void USART1_IRQHandler(void)//中断函数,接收数据存入接收缓冲区
{
   if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET)//判断中断是接收数据中断
    {
       receive_data[count]= USART_ReceiveData(USART1); //接收字符
				count++;
    } 

	}
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);
    //-----------------------------------------------(同上)---------------------------------------------------
    
		receive_data_init();//初始化接收缓存区
	while(1)
	{
		hellowindows();
		if ( strcmp(receive_data,"stop stm32!")==0)
				{
            			send = 0;//结束发送
						receive_data_init();
					
        }
else if (strcmp(receive_data,"go stm32!")==0)
        {
           				 send = 1;//发送数据
						receive_data_init();//重新初始化接收缓存区,以便下次接收数据
        }
	}
}

效果图:
在这里插入图片描述

  • 4
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值