中断程序的解释.docx
- 文档编号:17607558
- 上传时间:2023-07-27
- 格式:DOCX
- 页数:24
- 大小:47.94KB
中断程序的解释.docx
《中断程序的解释.docx》由会员分享,可在线阅读,更多相关《中断程序的解释.docx(24页珍藏版)》请在冰点文库上搜索。
中断程序的解释
关于V2.0版本
一在main函数中的定义
intmain(void)
{
DisableInterrupt;//关闭CPU总中断
RCC_Configuration();
GPIO_Configuration();
EXTI_Configuration();
NVIC_Configuration();
EnableInterrupt;//翻开总中断
while
(1)
{
}
}
注意以下问题:
(1)头文件局部
写的是#include"main.h"
在main.h中定义了
#ifndef__MAIN_H
#define__MAIN_H
#include"myfun.h"
#endif
以上关于_MAIN_H的宏定义,是为了防止多个重名头文件存在。
在〞myfun.h〞对应myfun.c文件
里面定义了
#include"stm32f10x_conf.h"
#include"cortexm3_macro.h"
#include"stm32f10x_lib.h"
#defineLED1_ONGPIO_ResetBits(GPIOD,GPIO_Pin_2)///控制的是PD2
#defineLED1_OFFGPIO_SetBits(GPIOD,GPIO_Pin_2)
#defineDisableInterrupt__SETPRIMASK()
#defineEnableInterrupt__RESETPRIMASK()
voidDelayMs(vu32nms);
voidDelayUs(vu32nus);
#endif
其中,LED1_ON和LED1_OFF对应于一个GPIO的位操作。
对应书上P101页的函数定义。
两个延迟函数,放在了myfun.c。
很好理解。
延迟函数是自己做的。
然而在myfun.h中还是做了很多定义。
GPIO用到的头文件。
(2)关于时钟的初始化配置
voidRCC_Configuration(void);
内容
voidRCC_Configuration(void)
{
ErrorStatusHSEStartUpStatus;///HSE起振状态0表示出错,其他的表示成果SUCCESS
RCC_DeInit();
RCC_HSEConfig(RCC_HSE_ON);
HSEStartUpStatus=RCC_WaitForHSEStartUp();
///假设选择HSE做系统时钟:
先调用RCC_HSEConfig()使能HSE,后调用//RCC_WaitForHSEStartUp()函数等待HSE起震,最后调用RCC_GetFlagStatus()函数获取HSE
//晶振状态
if(HSEStartUpStatus==SUCCESS)
{
FLASH_PrefetchBufferCmd(FLASH_PrefetchBuffer_Enable);//使能Flash半周期访问
FLASH_SetLatency(FLASH_Latency_2);//设置FLASH存储器延时周期数
RCC_HCLKConfig(RCC_SYSCLK_Div1);//设置AHB时钟
RCC_PCLK2Config(RCC_HCLK_Div1);//设置APB2时钟
RCC_PCLK1Config(RCC_HCLK_Div2);//设置APB1时钟
RCC_PLLConfig(RCC_PLLSource_HSE_Div1,RCC_PLLMul_9);//设置锁相环的倍频
RCC_PLLCmd(ENABLE);//使能锁相环
while(RCC_GetFlagStatus(RCC_FLAG_PLLRDY)==RESET)//等待PLL就绪
{
}
RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK);//设置系统时钟为PLL时钟
while(RCC_GetSYSCLKSource()!
=0x08)//确认系统时钟是否为PLL时钟
{
}
}
}
其中,ErrorStatus在stm32f10x_type.h中定义
typedefenum{ERROR=0,SUCCESS=!
ERROR}ErrorStatus;
RCC_DeInit();//在stm32f10x_rcc.c中定义。
表示复位RCC时钟到默认的配置。
voidRCC_DeInit(void)
{
/*SetHSIONbit*/
RCC->CR|=(u32)0x00000001;
/*ResetSW[1:
0],HPRE[3:
0],PPRE1[2:
0],PPRE2[2:
0],ADCPRE[1:
0]andMCO[2:
0]bits*/
RCC->CFGR&=(u32)0xF8FF0000;
/*ResetHSEON,CSSONandPLLONbits*/
RCC->CR&=(u32)0xFEF6FFFF;
/*ResetHSEBYPbit*/
RCC->CR&=(u32)0xFFFBFFFF;
/*ResetPLLSRC,PLLXTPRE,PLLMUL[3:
0]andUSBPREbits*/
RCC->CFGR&=(u32)0xFF80FFFF;
/*Disableallinterrupts*/
RCC->CIR=0x00000000;
}
RCC_HSEConfig(RCC_HSE_ON);///表示配置externalhighspeedoscillator外部高速振荡源
FLASH_PrefetchBufferCmd(FLASH_PrefetchBuffer_Enable);在stm32f10x_flash.c中定义
FLASH_SetLatency(FLASH_Latency_2);在stm32f10x_flash.c中定义
Stm32f10x_rcc.c中定义了如下
RCC_HCLKConfig(RCC_SYSCLK_Div1);
RCC_PCLK2Config(RCC_HCLK_Div1);
RCC_PCLK1Config(RCC_HCLK_Div2);
RCC_PLLConfig(RCC_PLLSource_HSE_Div1,RCC_PLLMul_9);
RCC_PLLCmd(ENABLE);
RCC_GetFlagStatus(RCC_FLAG_PLLRDY);
RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK);
RCC_GetSYSCLKSource();
在#include"stm32f10x_lib.h"中已经把"stm32f10x_rcc.h"加进去了。
所以可以正常使用。
(3)关于GPIO的配置。
根据我们的电路图,按键接PA15,LED接PD2
voidGPIO_Configuration(void)
{
GPIO_InitTypeDefGPIO_InitStructure;//定义一个GPIO_InitTypeDef类型的构造体
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA
|RCC_APB2Periph_GPIOD,ENABLE);
//KEY1PA15
GPIO_InitStructure.GPIO_Pin=GPIO_Pin_15;
GPIO_InitStructure.GPIO_Mode=GPIO_Mode_IPU;//配置为上拉输入模式
GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;///GPIO速度定义为50MHz
GPIO_Init(GPIOA,&GPIO_InitStructure);
//LED配置PD2LED1
GPIO_InitStructure.GPIO_Pin=GPIO_Pin_2;
GPIO_InitStructure.GPIO_Mode=GPIO_Mode_Out_PP;//配置为通用推挽输出模式
GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
GPIO_Init(GPIOD,&GPIO_InitStructure);
GPIO_SetBits(GPIOD,GPIO_Pin_2);///置位为高电平
}
GPIO_InitTypeDefGPIO_InitStructure;//定义一个GPIO_InitTypeDef类型的构造体,该构造体在stm32f10x_gpio.h中,里面声明了枚举。
分别为速度定义和模式定义。
typedefstruct
{
u16GPIO_Pin;
GPIOSpeed_TypeDefGPIO_Speed;
GPIOMode_TypeDefGPIO_Mode;
}GPIO_InitTypeDef;
typedefenum
{
GPIO_Speed_10MHz=1,
GPIO_Speed_2MHz,
GPIO_Speed_50MHz
}GPIOSpeed_TypeDef;
typedefenum
{GPIO_Mode_AIN=0x0,
GPIO_Mode_IN_FLOATING=0x04,
GPIO_Mode_IPD=0x28,
GPIO_Mode_IPU=0x48,
GPIO_Mode_Out_OD=0x14,
GPIO_Mode_Out_PP=0x10,
GPIO_Mode_AF_OD=0x1C,
GPIO_Mode_AF_PP=0x18
}GPIOMode_TypeDef;
按键的输入,为什么要定义为上拉输入?
而不是浮空输入?
与外部电路有关?
我们中断触发方式用的是下降沿触发,要保证出现下降沿,所以就配置为上拉输入,保持高电平输入,按键按下就出现一个下降沿,触发中断。
浮空输入就不能出现下降沿。
LED的输出定义为高速的推挽输出
GPIO的初始化对应的函数,都是在stm32f10x_gpio.c中。
(4)关于EXTI的配置。
voidEXTI_Configuration(void)
{
EXTI_InitTypeDefEXTI_InitStructure;
//KEY1PA15
EXTI_ClearITPendingBit(EXTI_Line15);//去除LINE15上的中断标志位
GPIO_EXTILineConfig(GPIO_PortSourceGPIOA,GPIO_PinSource15);//选择中断管脚
EXTI_InitStructure.EXTI_Line=EXTI_Line15;//选择中断线路
EXTI_InitStructure.EXTI_Mode=EXTI_Mode_Interrupt;//中断模式
EXTI_InitStructure.EXTI_Trigger=EXTI_Trigger_Falling;//中断触发方式,下降沿触发
EXTI_InitStructure.EXTI_LineCmd=ENABLE;//中断线路使能
EXTI_Init(&EXTI_InitStructure);
}
关于EXTI_InitTypeDef的构造体在stm32f10x_exti.h中定义
typedefstruct
{
u32EXTI_Line;
EXTIMode_TypeDefEXTI_Mode;
EXTITrigger_TypeDefEXTI_Trigger;
FunctionalStateEXTI_LineCmd;
}EXTI_InitTypeDef;
其中,EXTIMode_TypeDef为定义事件模式还是中断模式的枚举
typedefenum
{
EXTI_Mode_Interrupt=0x00,
EXTI_Mode_Event=0x04
}EXTIMode_TypeDef;
EXTITrigger_TypeDef为触发类型的定义。
有3种,上升沿,下降沿,上升下降沿。
typedefenum
{
EXTI_Trigger_Rising=0x08,
EXTI_Trigger_Falling=0x0C,
EXTI_Trigger_Rising_Falling=0x10
}EXTITrigger_TypeDef;
EXTI_ClearITPendingBit(EXTI_Line15);
关于此函数,在stm32f10x_exti.c中。
voidEXTI_ClearITPendingBit(u32EXTI_Line)
{
/*Checktheparameters*/
assert_param(IS_EXTI_LINE(EXTI_Line));
EXTI->PR=EXTI_Line;
}
输入参数为EXTI_Line,完成的功能是EXTI->PR=EXTI_Line;
在这里EXTI的构造体的定义在stm3210x_map.h中。
typedefstruct
{
vu32IMR;
vu32EMR;
vu32RTSR;
vu32FTSR;
vu32SWIER;
vu32PR;
}EXTI_TypeDef;
对应于书上123页的存放器中的最后一个。
功能为挂起,和清零的区别?
在表6-4中关于EXTI_PR的解释是,用用保存中断/事件。
PR:
挂起存放器。
当外部中断线上发生了选择的边沿事件,该存放器的对应位会被置为1。
0,表示对应线上没有发生触发请求。
通过向该存放器的对应位写入1可以去除该位。
在中断效劳函数里面经常会要向该存放器的对应位写1来去除中断请求。
还有,EXTI->PR=EXTI_Line;是对存放器的写操作。
在stm32f10x_exti.h中,定义为#defineEXTI_Line15((u32)0x08000)
相当于将数0x08000赋给了PR存放器。
还有,EXTI->PR=EXTI_Line;是对存放器的一种什么操作?
在stm32f10x_exti.h中,定义为#defineEXTI_Line15((u32)0x08000)
相当于将数0x08000赋给了PR存放器
很重要的一点,书上解释,使用EXTI_ClearITPendingBit函数去除中断标志位。
进入中断效劳程序后,首先要做的就是去除中断标志位,否那么它不会不断响应中断,不断进入中断函数〔P126〕。
引出了一个问题。
挂起和去除是一样的吗?
从函数的英文上看,是clearpending,理解为去除挂起。
关于GPIO_EXTILineConfig的详细内容在stm32f10x_gpio.c中,其description为:
selectstheGPIOpinusedasEXTILine.选择GPIO引脚作为EXTI的输入线。
内部是对AFIO存放器进展操作,本存放器的定义在_map.h。
属于外设存放器。
voidGPIO_EXTILineConfig(u8GPIO_PortSource,u8GPIO_PinSource)
{
u32tmp=0x00;
/*Checktheparameters*/
assert_param(IS_GPIO_EXTI_PORT_SOURCE(GPIO_PortSource));
assert_param(IS_GPIO_PIN_SOURCE(GPIO_PinSource));
tmp=((u32)0x0F)<<(0x04*(GPIO_PinSource&(u8)0x03));
AFIO->EXTICR[GPIO_PinSource>>0x02]&=~tmp;
AFIO->EXTICR[GPIO_PinSource>>0x02]|=(((u32)GPIO_PortSource)<<(0x04*(GPIO_PinSource&(u8)0x03)));
}
本程序中用了GPIO_EXTILineConfig(GPIO_PortSourceGPIOA,GPIO_PinSource15);
#defineGPIO_PortSourceGPIOA((u8)0x00)///在_gpio.h中定义的
#defineGPIO_PinSource15((u8)0x0F)//在_gpio.h中定义的
EXTI_Init(&EXTI_InitStructure);
在设置完EXTI的参数之后,用了初始化函数。
此函数在stm32f10x_exti.c中。
(5)关于NVIC存放器的配置
voidNVIC_Configuration(void)
{
NVIC_InitTypeDefNVIC_InitStructure;
//设置中断向量表的入口
NVIC_SetVectorTable(NVIC_VectTab_FLASH,0x0);
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//设置中断优先级分组为2,即两位抢先优先级,两位副优先级。
//KEY1PA15
NVIC_InitStructure.NVIC_IRQChannel=EXTI15_10_IRQChannel;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=0;//抢先优先级为0
NVIC_InitStructure.NVIC_IRQChannelSubPriority=0;//副优先级
NVIC_InitStructure.NVIC_IRQChannelCmd=ENABLE;
NVIC_Init(&NVIC_InitStructure);
}
NVIC_InitTypeDef的定义在stm32fl0x_nvic.h中
typedefstruct
{
u8NVIC_IRQChannel;
u8NVIC_IRQChannelPreemptionPriority;
u8NVIC_IRQChannelSubPriority;
FunctionalStateNVIC_IRQChannelCmd;
}NVIC_InitTypeDef;
//在stm32f10x_nvic.c中,本例程为FLASH启动。
voidNVIC_SetVectorTable(u32NVIC_VectTab,u32Offset)
{
/*Checktheparameters*/
assert_param(IS_NVIC_VECTTAB(NVIC_VectTab));
assert_param(IS_NVIC_OFFSET(Offset));
SCB->VTOR=NVIC_VectTab|(Offset&(u32)0x1FFFFF80);
}
////在stm32f10x_nvic.c中,
voidNVIC_PriorityGroupConfig(u32NVIC_PriorityGroup)
{
/*Checktheparameters*/
assert_param(IS_NVIC_PRIORITY_GROUP(NVIC_PriorityGroup));
/*SetthePRIGROUP[10:
8]bitsaccordingtoNVIC_PriorityGroupvalue*/
SCB->AIRCR=AIRCR_VECTKEY_MASK|NVIC_PriorityGroup;
}
其中,#defineAIRCR_VECTKEY_MASK((u32)0x05FA0000)////也是在stm32f10x_nvic.c中
#defineNVIC_PriorityGroup_2((u32)0x500)/*2bitsforpre-emptionpriority////为stm32f10x_nvic.h文件中。
这两个合起来给SCB的AIRCR存放器。
与课本上p111页说的一样。
#defineEXTI15_10_IRQChannel((u8)0x28)/*ExternalLine[15:
10]Interrupts*/在stm32f10x_nvic.h中。
开总中断和关总中断
书上用的是:
voidNVIC_SETPRIMASK(void)
{
__SETPRIMASK();
}
voidNVIC_RESETPRIMASK(void)
{
__RESETPRIMASK();
}
本例题中,直接定义了
#defineDisableInterrupt__SETPRIMASK()
#defineEnableInterrupt__RESETPRIMASK()
更容易理解。
__SETPRIMASK()下划线如何解释?
?
一个下划线表示私有,两个表示系统默认的。
这两个函数是在cortexm3_macro.s中实现的是汇编函数;
二中断函数在stm32f10x_it.c中做定义
voidEXTI15_10_IRQHandler(void)
{
staticu8flag=0;
DelayMs(10);//用了一个延迟来消除抖动
if(GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_15)==Bit_RESET)
{
while(GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_15)==Bit_RESET);//松手检测
//按键KEY动作
flag=!
flag;
if(flag)
{
LED1_ON;
}
else
{
LED1_OFF;
}
}
EXTI_ClearITPendingBit(EXTI_Line15);//去除LINE15上的中断标志
}
加了头文件main.h。
使用了LED1_ON和LED_OFF。
三在stm32f10x_vector.s中定义了中断向量的入口地址。
中断向量表。
以及_main
同样的功能,在V3.5版本的工程中的实现过程如下
一main函数中的定义
主函数更简单。
intmain(void)
{
DisableInterrupt;//关总中断
GPIO_Configuration();
EXTI_Configuration();
NVIC_Configuration();
EnableInterrupt;//开总中断
while
(1)
{
}
}
〔
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 中断 程序 解释
![提示](https://static.bingdoc.com/images/bang_tan.gif)