300 likes | 875 Views
STM32 的中断、定时器. 目录. 1. 什么是“中断”?. 2. STM32 中的优先级概念. 3. STM32 外部中断 例程讲解. 4. STM32 的定时器简介. 5. STM32 定时器例程讲解. 什么是“中断 ” ?. CPU. 中断示意图. 外 设. 发申请. 中断服务程序. 发申请. 中断服务程序.
E N D
目录 1 什么是“中断”? 2 STM32中的优先级概念 3 STM32外部中断例程讲解 4 STM32的定时器简介 5 STM32定时器例程讲解
什么是“中断”? CPU 中断示意图 外 设 发申请 中断服务程序 发申请 中断服务程序 CPU执行程序时,由于发生了某种随机的事件(外部或内部),引起CPU暂时中断正在运行的程序,转去执行一段特殊的服务程序(中断服务子程序或中断处理程序),以处理该事件,该事件处理完后又返回被中断的程序继续执行,这一过程称为中断。 EG:吃饭时突然手机铃响…
STM32中的优先级概念 STM32(Cortex-M3)中有两个优先级的概念:抢占式优先级和响应优先级,也把响应优先级称作“亚优先级”或“副优先级”,每个中断源都需要被指定这两种优先级。 1. 何为占先式优先级(pre-emption priority) 高占先式优先级的中断事件会打断当前的主程序/中断程序运行—抢断式优先响应,俗称中断嵌套。 2. 何为副优先级(subpriority) 在占先式优先级相同的情况下,高副优先级的中断优先被响应; 在占先式优先级相同的情况下,如果有低副优先级中断正在执行,高副优先级的中断要等待已被响应的低副优先级中断执行结束后才能得到响应—非抢断式响应(不能嵌套)。 3. 判断中断是否会被响应的依据 首先是占先式优先级,其次是副优先级; 占先式优先级决定是否会有中断嵌套;
STM32中的优先级概念 4. 优先级冲突的处理 具有高抢占式优先级的中断可以在具有低抢占式优先级的中断处理过程中被响应,即中断的嵌套,或者说高抢占式优先级的中断可以嵌套低抢占式优先级的中断。 当两个中断源的抢占式优先级相同时,这两个中断将没有嵌套关系,当一个中断到来后,如果正在处理另一个中断,这个后到来的中断就要等到前一个中断处理完之后才能被处理。如果这两个中断同时到达,则中断控制器根据他们的响应优先级高低来决定先处理哪一个;如果他们的抢占式优先级和响应优先级都相等,则根据他们在中断表中的排位顺序决定先处理哪一个。
STM32中的优先级概念 5. stm32中对中断优先级的定义 STM32中指定中断优先级的寄存器位有4位,这4个寄存器位的分组方式如下: 第0组:所有4位用于指定响应优先级第1组:最高1位用于指定抢占式优先级,最低3位用于指定响应优先级第2组:最高2位用于指定抢占式优先级,最低2位用于指定响应优先级第3组:最高3位用于指定抢占式优先级,最低1位用于指定响应优先级第4组:所有4位用于指定抢占式优先级 具体怎样设置在例程中详细讲解!
STM32外部中断 STM32单片机80个通用I/O端口连接到19个外部中断/事件源上。左图为STM32单片机通用I/O与外部中断的映射关系:PAx、PBx 、PCx 、PDx和PEx端口对应的是同一个外部中断/事件源EXTIx(x:0-15)。 EXTI_Line值:P99 NVIC_IRQChannel值:P166
STM32外部中断例程讲解 void GPIO_Configuration(void) //输入输出管脚配置 { GPIO_InitTypeDef GPIO_InitStructure; //配置输出脚PC0控制LED灯 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; GPIO_Init(GPIOC, &GPIO_InitStructure); //配置输入脚PA0控制按键 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; GPIO_Init(GPIOA, &GPIO_InitStructure); }
STM32外部中断例程讲解 void NVIC_Configuration(void) //嵌套向量中断控制器配置 { NVIC_InitTypeDef NVIC_InitStructure; NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1); //选择优先级组别 NVIC_InitStructure.NVIC_IRQChannel = EXTI0_IRQn; //选择中断通道:EXTI线0中断,因为按键连接的是PA0脚 NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; //0级抢占式优先级 NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; //0级副优先级 NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //使能引脚作为中断源 NVIC_Init(&NVIC_InitStructure); //调用NVIC_Init固件库函数进行设置 } 固件中P166!
STM32外部中断例程讲解 void EXTI_Configuration(void) { //调用固件库中的GPIO_EXTILineConfig函数, //其中两个参数分别是中断口和中断口对应的引脚号 GPIO_EXTILineConfig(GPIO_PortSourceGPIOA, GPIO_PinSource0); EXTI_InitStructure.EXTI_Line = EXTI_Line0; //将中断映射到中断/事件源Line0 EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt; //中断模式 EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling //设置为下降沿中断 EXTI_InitStructure.EXTI_LineCmd = ENABLE; //中断使能,即开中断 EXTI_Init(&EXTI_InitStructure); //调用EXTI_Init固件库函数,将结构体写入EXTI相关寄存器中 } 固件中P99!
STM32外部中断例程讲解 void EXTI0_IRQHandler(void) { if(EXTI_GetITStatus(EXTI_Line0) != RESET) { //将LED1的状态反转 GPIO_WriteBit(GPIOC, GPIO_Pin_0, (BitAction)((1- GPIO_ReadOutputDataBit(GPIOC, GPIO_Pin_0)))); //清中断 EXTI_ClearITPendingBit(EXTI_Line0); } } 注意:中断服务函数都包含在“stm32f10x_it.c”文件中, 用的时候只需添加指令即可!
STM32外部中断下载测试 下载完程序后,按按键K1触发中断,LED灯B1状态反转。实际操作:修改程序,使中断通过按键K3触发,同时4个LED灯状态反转?
STM32定时器简介 STM32中一共有11个定时器,其中2个高级控制定时器,4个普通定时器和2个基本定时器,以及2个看门狗定时器和1个系统嘀嗒定时器。其中系统嘀嗒定时器是前文中所描述的SysTick。主要讲普通定时器定时器。 TIM2-TIM5是普通定时器,TIM6和TIM7是基本定时器,其时钟由APB1输出产生。
STM32定时器简介 2.1时钟来源 计数器时钟可以由下列时钟源提供: ·内部时钟(CK_INT) ·外部时钟模式1:外部输入脚(TIx) ·外部时钟模式2:外部触发输入(ETR) ·内部触发输入(ITRx):使用一个定时器作为另一个定时器的预分频器,如可以配置一个定时器Timer1而作为另一个定时器Timer2的预分频器。 由于今天的学习是最基本的定时功能,所以采用内部时钟。TIM2-TIM5的时钟不是直接来自于APB1,而是来自于输入为APB1的一个倍频器。这个倍频器的作用是:当APB1的预分频系数为1时,这个倍频器不起作用,定时器的时钟频率等于APB1的频率;当APB1的预分频系数为其他数值时(即预分频系数为2、4、8或16),这个倍频器起作用,定时器的时钟频率等于APB1的频率的2倍。通过倍频器给定时器时钟的好处是:APB1不但要给TIM2-TIM5提供时钟,还要为其他的外设提供时钟;设置这个倍频器可以保证在其他外设使用较低时钟频率时,TIM2-TIM5仍然可以得到较高的时钟频率。
STM32定时器简介 2.2计数器模式 TIM2-TIM5可以由向上计数、向下计数、向上向下双向计数。向上计数模式中,计数器从0计数到自动加载值(TIMx_ARR计数器内容),然后重新从0开始计数并且产生一个计数器溢出事件。在向下模式中,计数器从自动装入的值(TIMx_ARR)开始向下计数到0,然后从自动装入的值重新开始,并产生一个计数器向下溢出事件。而中央对齐模式(向上/向下计数)是计数器从0开始计数到自动装入的值-1,产生一个计数器溢出事件,然后向下计数到1并且产生一个计数器溢出事件;然后再从0开始重新计数。
STM32定时器例程讲解(查询方式) void GPIO_Config(void) { GPIO_InitTypeDef GPIO_InitStructure; //定义固件函数库中已经定义好的数据结构的变量 //变量类型:GPIO_InitTypeDef、变量名 :GPIO_InitStructure //使能各端口时钟,和利用端口AFIO时钟 RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_GPIOB|RCC_APB2Periph_ GPIOC|RCC_APB2Periph_GPIOD|RCC_APB2Periph_GPIOE|RCC_APB2Periph_AFIO, ENABLE); GPIO_InitStructure.GPIO_Pin =GPIO_Pin_0|GPIO_Pin_1|GPIO_Pin_2|GPIO_Pin_3; //选择端口位 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //选择端口时钟 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; //选择端口输出方式 GPIO_Init(GPIOC, &GPIO_InitStructure); //按以上设置初始化该端口 GPIO_ResetBits(GPIOC,GPIO_Pin_0); //C端口的0,1,2,3 管脚输出0 GPIO_ResetBits(GPIOC,GPIO_Pin_1); GPIO_ResetBits(GPIOC,GPIO_Pin_2); GPIO_ResetBits(GPIOC,GPIO_Pin_3); }
STM32定时器例程讲解(查询方式) void Timer_Config(void) { TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure; //定义TIM结构体变量 RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2,ENABLE); //使能TIM2外设 TIM_DeInit(TIM2);//复位时钟TIM2,恢复到初始状态 TIM_TimeBaseStructure.TIM_Period=35999; TIM_TimeBaseStructure.TIM_Prescaler=1999; TIM_TimeBaseStructure.TIM_ClockDivision=TIM_CKD_DIV1; //TIM2时钟分频 TIM_TimeBaseStructure.TIM_CounterMode=TIM_CounterMode_Up; //计数方式 //定时时间T计算公式: T=(TIM_Period+1)*(TIM_Prescaler+1)/TIMxCLK=(35999+1)*(1999+1)/72MHz=1s TIM_TimeBaseInit(TIM2,&TIM_TimeBaseStructure); //初始化 TIM_ClearFlag(TIM2,TIM_FLAG_Update); //清除标志 TIM_Cmd(TIM2,ENABLE); //使能TIM2 }
STM32定时器例程讲解(查询方式) //程序主循环 while(1) { if(TIM_GetFlagStatus(TIM2,TIM_FLAG_Update)!=RESET) //查询TIM_FLAG_Update标志置位了就清除标志 { TIM_ClearFlag(TIM2,TIM_FLAG_Update); //清标志 switch(state) { case 0: GPIO_SetBits(GPIOC,GPIO_Pin_0); GPIO_ResetBits(GPIOC,GPIO_Pin_1); GPIO_ResetBits(GPIOC,GPIO_Pin_2); …… default: break; } if(++state>=5) state=0; } }
STM32定时器例程讲解(中断方式) void NVIC_Config(void) { NVIC_InitTypeDef NVIC_InitStructure;//定义结构体变量 NVIC_PriorityGroupConfig(NVIC_PriorityGroup_0); //设置优先分级组 NVIC_InitStructure.NVIC_IRQChannel=TIM2_IRQn; //选择中断通道。注意:固件库中为XXX_IRQChannel,但该程序预定义为 XXX_IRQn,所以要特别注意 NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=0; //先占优先级 NVIC_InitStructure.NVIC_IRQChannelSubPriority=0; //从优先级 NVIC_InitStructure.NVIC_IRQChannelCmd=ENABLE; //使能中断向量配置 NVIC_Init(&NVIC_InitStructure); //按以上设置初始化中断向量 } 固件中P166!
STM32定时器例程讲解(中断方式) void Timer_Config(void) { TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure; //定义TIM结构体变量 RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2,ENABLE); //使能TIM2外设 TIM_DeInit(TIM2);//复位时钟TIM2,恢复到初始状态 TIM_TimeBaseStructure.TIM_Period=35999; TIM_TimeBaseStructure.TIM_Prescaler=1999; TIM_TimeBaseStructure.TIM_ClockDivision=TIM_CKD_DIV1; //TIM2时钟分频 TIM_TimeBaseStructure.TIM_CounterMode=TIM_CounterMode_Up; //计数方式 //定时时间T计算公式: T=(TIM_Period+1)*(TIM_Prescaler+1)/TIMxCLK=(35999+1)*(1999+1)/72MHz=1s TIM_TimeBaseInit(TIM2,&TIM_TimeBaseStructure); //初始化 TIM_ClearFlag(TIM2,TIM_FLAG_Update); //清除标志 TIM_ITConfig(TIM2,TIM_IT_Update,ENABLE); //使能中断源 TIM_Cmd(TIM2,ENABLE); //使能TIM2 }
STM32定时器例程讲解(中断方式) void TIM2_IRQHandler(void) { if(TIM_GetITStatus(TIM2,TIM_IT_Update)==SET) { TIM_ClearITPendingBit(TIM2,TIM_FLAG_Update); //清中断 switch(state) { case 0: GPIO_SetBits(GPIOC,GPIO_Pin_0); GPIO_ResetBits(GPIOC,GPIO_Pin_1); GPIO_ResetBits(GPIOC,GPIO_Pin_2); GPIO_ResetBits(GPIOC,GPIO_Pin_3); …… default: break; } if(++state>=5) state=0; } } 注意:中断服务函数都包含在“stm32f10x_it.c”文件中,用的时候只需添加指令即可!
STM32通用定时器下载测试 下载完程序后,4个LED灯隔1s依次点亮,即流水灯。 实际操作:修改程序,通过定时器使4个LED灯依次点亮间隔时间为0.5s?