外部中断代码编写|学习笔记

简介: 快速学习外部中断代码编写

开发者学堂课程【嵌入式之RFID开发与应用2020版外部中断代码编写】学习笔记与课程紧密联系,让用户快速学习知识

课程地址:https://developer.aliyun.com/learning/course/665/detail/11156


外部中断代码编写

 

内容介绍:

一、触发方式

二、下拉输入

三、中断源

四、中断优先级

 

接下来讲代码,直接把写好的代码拿来,查询过程没有给,给一个带中断的按键,把它拖过来替换掉。

替换完后,在工程里要适当的修改一下,还要再添加一些文件进来,

image.png

再同步一下,

添加进来后,首先,代码写的会稍微复杂些,led也不是很复杂,

u16 time_count;

static u8 led_flag = 日;

static u8 buzzer flag = 0;6:

u8 led flicker count;

u8 buzzerflicker_count;8:

void led_init(void)

{

GpIo InitTypeDef GPIO Initstructure:

RCC APB2PeriphClockCmd(RCC XXXLED,ENABLE);

GPIo_Initstructure.GPIO_Pin = GPIO_XXX_LED;

GpIo Initstructure.GPIO Mode =GPIO Mode Out PP;

Gpio Initstructure.GPIO Speed = GPIO Speed 10MHz;

GPIo Init(GPIO XXX LED_PORT, &GPIO_Initstructure);

LED XXX OFF();//初始化结束熄灭LED

}

包括轰鸣器,在按键这里就有很大的区别。

重点来看,如果想让按键支持中断。那么首先就来明确一下让谁来输出固定的电频,由另一个引角作为终端的输入采集。

static signed char key_status=0;5:

void key init(void)7:{1

GPIO InitTypeDef GPIO Initstructure fix;

EXTI InitTypeDef ExTI Initstructure:

NVIC_InitTypeDefNVIC Initstructure;

GPIO InitTypeDef GPIO_Initstructure:

RCC_APB2PeriphClockCmd(RCC_XXX_KEYFIX,ENABLE);

GpIO Initstructure fixPIo PinmGPIO XXX KEYFIX:

GPIo Initstructure fix.GPIo Mode=GPIO Mode out PP:

GPIO_Initstructure fix.GPIO Speed=GPIO_Sped_10MHz;

GPIO Init(GPIO XXX KEY FIX PORT,&GPIO Initstructure fix):

GPIO SetBits(GPIO XXX_KEY FIX PORTGPIO XXX_KEY_FIX);

要提醒一下在这里其实并没有去配置它的抢占优先级和子优先级。要去配置也是没有问题的,就是需要把>WVIC PriorityGroupConfig(NVIC PriorityGroup_1)复制放在代码的首位,

while(i--);

}

int main(void)11:

NVIC_PriorityGroupCohfig(NVIC_priorityGroup_1);

led_init();

buzzer init();

key_init();

while(1){

if(get_key_status()){

led_flicker();

buzzer_flicker();

}

把它配置成第二种情况,也就是让抢占优先级和子优先级各占两位。配置完后,按键是怎么初始化的?

首先,这里按键用的是A0,另一个是A1。把管角固定输出固定值,setbits说明固定是高电频。

ExtI InitTypeDef EXTI Initstructure;

NvIc InittypeDef NVIc Initstructure;

GPIo_InitTypeDef GPIO_Initstructure;

RCC APB2PeriphClockCmd(RCC XXX KEY FIX,ENABLE);

GpIo Initstructure fix.gpio Pin = GPIO XXX KEY FIX;//输出固定值 1 GPIo Initstructure fix.GPIO Mode = GPIO Mode Out pp;

GPIo Initstructure fix.gpio Speed = GPIO Speed 10MHz;

GPIO_Init(GPIO_XXX_KEY_FIX_PORT,&GPIO_Initstructure fix); I

GPIo SetBits(GPIO XXX KEY FIX PORT,GPIO XXX KEY FIX);

RCC APB2PeriphClockCmd(RCC XXX KEYRCC APB2Periph AFIO, ENABLE);

GPIo Initstructure.GPIo Pin = GPIO XXX KEY;

GPIO Initstructure.GPIO Mode = GPIO Mode IPD;

GPIO Init(GPIO XXX KEY PORT, &GPIO Initstructure);

GPIO EXTILineConfig(GPIO XXX KEY PORTSOURCE, GPIO XXX KEY SOURCE);

另一个IPD管角就要把它设成输入。一个是输出高电频,另一个是输入,这刚好就符合按键图,A0是输出高电频,A1是设置输入,而要把它设成中断的方式,中断在没有键按下时相当于中断是不触发的,一旦按下它就触发,还要选择触发方式。

 image.png

一、触发方式:

首先,利用有关GPLO的数据结构,把RCC打开,引角的确认模式为输出频率十兆,IO口配置set输出高电频完;另一个同理。除了要把按键的时钟打开外还增加个afio。

需要开启和中断相关的时钟配置,包括要用到串口并把串口的时钟打开,所以就多个过程,中断和io的时钟全部打开,并且将io设置成模式。

 

二、下拉输入:

ipd叫做下拉输入,它连接一个下拉电阻,并且是输入状态。

下拉电阻的含义是在没有按键时,pae默认应是低电阻,当按下去时,它就由低电频变高电频,所以就应有一个跳变,当你的手松开之后,它应又回到低电频。

它有一个上升音、高电频、下降音三种变化,要选一种作为它的处罚方式,设好后,把通关退完,接下来这里就是配置中断。

RCC APB2PeriphClockCmd(RCC XXX KEYRCC APB2Periph AFIO,ENABLE);

GPIO Initstructure.GPIO Pin =GPIO XXX KEY;

GPIO Initstructure.GPIO Mode =GPIO Mode IPD;

GPIO_Init(GPIO XXX KEY PORT,&GPIO_Initstructure);

GPIO EXTILineConfig(GPIO XXX KEYIPORTSOURCE, GPIO XXX KEY SOURCE);

 

三、中断源:

要指定这个案件的中断源,它是gpla的第几个引脚,

/*限位开关*/

#define  RCC XXX KEY RCC APB2Periph GPIOA

#define  GPIO_XXX KEY_PORT GPIOA

#define  GPIO XXX KEY GPIO_Pin_1

#define  GPIO XXX KEY PORTSOURCE GPIo PortSourceGPIOA

#define  GPIO_XXX KEY_SOURCE  GPIO PinSource1 I

#define  GPIO XXX KEY LINE  EXTI Line1

#define  GPIO_XXX KEY_EXTI  EXTI1_IRQn

用的是第一个引脚是Source1,如果是第零个引脚是Source0,第二个就是Source2,以此类推,每组io口就四五个引脚。

A组的第一个引脚,这就决定io不是普通的输入引脚,换句话说,因为在这后面的配置中,它自动去修改引导属性为中断模式。配置的是io的东西。

配置外部中断相关的,首先外部中断属于哪个中断线,它是A0就是第零个中断线,A1就是第一个,中断线A2就是第二个中断线。中断线有16个指的是外部中断,它有一些互联互通型的,还有一些特殊中断。

/* Configure Button EXTI line */

/*将KEY按键配置为中断模式,上升沿触发中断*/

EXTI Initstructure.EXTI Line =GPIO XXX KEY LINE;

EXTI Initstructure.EXTI Mode=EXTI Mode Interrupt:

EXTI Initstructure.EXTI Trigger = EXTI Trigger Rising

EXTT Initstructure EXTT lineCmd =FNABLE. 

另外,它有中断模式、事件模式,处罚方式

有上升沿,下降沿,还有上升沿加下降沿(也就是双沿)。

typedef enum

EXTI TriggerIRising =0x08

EXTI Trigger Falling=0x0C,

EXTI Trigger Rising Falling =0x10

}EXTITriggerTypeDef;

选择上升沿触发,当按键在按下时由默认的下拉电阻低电频变成高电频。用下降沿也可以,因为按键一旦松开,它就会回到低电频。所以你上升沿或下降沿甚至是双沿都可以。中断就会进一次按键,所以这里用的是上升沿,保证键只要按下中断立马响应。

对于中断进行初始化(优先级配置),

/*Enable and set Button EXTI Interrupt to the lowest priority*/

/* 将KEY按键的中断优先级配置为最低 */

NVIC Initstructure.NVIC IRQChannel=GPIO XXX KEY EXTI;

NvIc

Initstructure.NVIC IRChannelPreemptionPriority=0xOF;

Nvic

Initstructure.NVIc IRochannelsubPriority=0x0F;

NVIC Initstructure.NVIC IRQChannelCmd=ENABLE;

NVIC Init(&NVIc Initstructure);

 

四、中断优先级:

对于中断优先级,首先,先确定中断的通道,一共有七个,这里用的是EXTI1_IRQn,一共有七个中断的入口,后面还有五到九,十到一十五,那么一共七个,用的是第一个中断的通道,它是独立的。

如果用的是外部中断567,这就是共享,进到同一个函数里由自己去分辨是谁被触发。

抢占优先级总共提供的是四个比特位,数字化里定义成扩占两位,设成3,Nvic Initstructure.Nvic IrochannelPreemptionPriority=0x03,是最低的优先级,这也设成3 NVIC Initstructure.NVIC IROchannelsubPriority=0x03;//3,依然是最低的优先级,因为0就是数字,越小的优先级是越高的,(0到3)设成3,抢占优先级有四个,子优先级也有四个,最后,把优先级的通道初始化。中断配置就算是完成了。基本上stm32的开发只要有一个程序是正常的,其他的程序几乎就是故技重施了。

另外,中断一已经配置成功,要找到中断它对应的入口,EXT0到E15只有7个入口,外部中断1是独立的入口。

外部16个中断线对应的7个中断入口:

EXTIO_IRQHandler

EXTI1 IRQHandler

EXTI2 IRQHandler

EXTI3_IRQHandler

EXTI4 IRQHandler

EXTI5 9 IRQHandler

EXTI10 15 IRQHandler

具体实现请参考代码

其它中断入口可以参考startup stm32f10xxx件

入口函数它本身是已经在启动代码当中定义好,自己去写要去修改启动代码。EXTI1 IROHandler,给改掉后,就可以在程序里面写一个你自己的公关付款。

void EXTI1_IRQHandlen(void)

{

if(EXTI GetITstatus(GPIO XXX KEYLINE)!=RESET

{

delay_ms(KEY_SHAKE);//去抖

if(XXX KEY STATUSGET()==1){

key_status = 1;

SET_BUZZER FLICKER(5);

EXTI_ClearITPendingBit(GPIO_XXX_KEY_LINE); 

因为50有终端向量表,通过向量表跳转到指定的地址,它启动代码已经固定。

中断函数的特点是没有参数也没有返回。异常向量表是cpu调的,Cpu是让程序计数器PC直接发生偏转,PC直接指向某个入口,就并没有函数调用的上下文(没办法传参),也没有办法去处理返回值,返回值的参数是没有任何意义的。

进来后,可以通过 GetITStstus 去发现中断的标志位是不是被置位是不想中断的非常有效的方法。比如现在是一号中断,你判不判断都是它,中断是第五和第六要做判断,如果第五个中断触发,否则再加一段,要重新复制下来

}else

if(EXTI_GetITstatus(GPIO_XXX_KEY_LINE)!= RESET){

如果是Line1, Line5,要把它改成6,到底是5触发还是6触发,从而可以在同个中断服务函数里执行多个中断的响应。但要记住5和6同一时刻肯定只能有一个进来,当把5处理完后,如果再退出去,中断标注为6依然自卫,函数还会再执行,所以不会漏掉。

独立中断的好处是可以支持抢占,中断正在执行时,另一个中断打断还可以再次去,比如对于这种5到9的中断,把它设成抢占,5到9之间抢占就没有任何意义,自己的函数不是同一个函数没有必要去抢占。

这时就相当于函数就有点像递归了,去抖做法不是很科学,尽量不要在中断里面去延时,希望它更快的完成处理。

简单的演示,让按键更准确,在这里做一个延时delay ms(KEYSHAKE)://去抖 大概20毫秒过后,再去通过 ReadInputDataBit 去判断读出来的状态是一个高电频,表示按键确实是按下。

按下后, key_status给它制1,轰鸣器和灯闪烁五次 SET BUZZER FLICKER(5); 只设置一个标志位需要定时器的配合。可以先忽略这句话,执行完要把中断线的标志位给清除掉,这就是中断服务函数。

key_status状态其实是和其他的任务通信的,可以选择把代码直接放到这里,也可以给它制个标志位,然后在外面判断获取按键状态有没有 status 返回是1,返回来它就会把清零

//轮询接口

signed char get key status(void)

signed char temp = key_status;

key_status = 0;

return temp;

就是状态,相当于每获取一次就会清掉1。

get_key_status 在主程序里只要读到为灯飞离就让这个轰鸣器的灯闪一下,就达到按键触发轰鸣器和开灯关灯的动作,这就是中断。

相关文章
|
7月前
|
开发者
STM32中断详解及其编程实践
STM32中断详解及其编程实践
428 1
|
7月前
|
传感器
STM32标准库外部中断和定时器知识点总结-2
STM32标准库外部中断和定时器知识点总结
|
7月前
|
传感器
STM32标准库外部中断和定时器知识点总结-1
STM32标准库外部中断和定时器知识点总结
|
7月前
|
传感器 监控 C++
外部中断的使用方法
这篇文章介绍了中断的概念,以一个生动的故事比喻,说明中断是如何打断主程序执行并调用中断函数的。文章提到了Arduino控制器和"吃货"模型,展示了如何编写处理吃和开门的代码,并介绍了设置中断的函数`attachInterrupt`。接着,列举了不同Arduino型号的外部中断引脚,并详细解释了中断函数、中断触发模式。最后,提供了一个官方的外部中断例程和其可能的应用场景,如使用旋转编码器或构建监控装置。
|
7月前
|
内存技术
模块化编程+LCD1602调试工具——“51单片机”
模块化编程+LCD1602调试工具——“51单片机”
模块化编程+LCD1602调试工具——“51单片机”
【单片机】简单的自定义延时程序设计(代码演示)
【单片机】简单的自定义延时程序设计(代码演示)
|
C语言 Windows
C语言课设项目-51单片机-定时器和计数器
C语言课设项目-51单片机-定时器和计数器
239 0
|
程序员 C语言
C语言课设项目-51单片机-中断系统
C语言课设项目-51单片机-中断系统
174 0
编写使用中断的按键驱动程序
编写使用中断的按键驱动程序
109 0