嵌入式系统 流水灯、按键、定时器实验报告 联系客服

发布时间 : 星期日 文章嵌入式系统 流水灯、按键、定时器实验报告更新完毕开始阅读d3214c3304a1b0717ed5dd9f

电平变化触发,但是不能配置成高电平触发和低电平触发。这里根据自己的实际情况来配置。同时要开启中断线上的中断,这里需要注意的是:如果使用外部中断,并设置该中断的EMR位的话,会引起软件仿真不能跳到中断,而硬件上是可以的。而不设置EMR,软件仿真就可以进入中断服务函数,并且硬件上也是可以的。建议不要配置EMR位。

(4) 配置中断分组(NVIC),并使能中断。这一步,我们就是配置中断的分组以及使能,对STM32的中断来说,只有配置了 NVIC 的设置,并开启才能被执行,否则是不会执行到中断服务函数里面去的。

(5)编写中断服务函数。这是中断设置的最后一步,中断服务函数,是必不可少的,如果在代码里面开启了中断,但是没编写中断服务函数,就可能引起硬件错误,从而导致程序崩溃。所以在开启了某个中断后,应为该中断编写服务函数。在中断服务函数里面编写要执行的中断后的操作,并很据情况判断是否要对中断产生的标志位进行清零 。

由原理图可知,按键未按下时,GPIO读到的为高电平,按键按下后,IO口接地,产生一个电平跳变,所以外部中断触发方式应该设置为下降沿触发。

2.3程序分析

LED灯的点亮与实验一中相同,不过多赘述。程序首先对按键进行初始化,初始化函数为GPIO_KEY_Config()(见附录4),配置过程与实验一中GPIO配置基本一致。由于此处GPIO需要采集外界按键信号,故GPIO模式应该为调整为内部上拉电阻输入

GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU。

然后执行GPIO中断初始化函数KEY_EXIT_Init()(见附录5),首先将连接按键的IO口与EXTI线链接到一起:

GPIO_EXTILineConfig(GPIO_KEY1_EXTI_PORT_SOURCE,GPIO_KEY1_EXTI_PIN_SOURCE);

然后将触发方式设置为下降沿触发并写入中断配置寄存器,并使能中断: EXTI_InitStructure.EXTI_Line = GPIO_KEY1_EXTI_LINE; EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;

EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling; EXTI_InitStructure.EXTI_LineCmd = ENABLE; EXTI_Init(&EXTI_InitStructure)。

之后进行中断分组配置及中断优先级配置,函数为InterruptConfig()(见附录6)。

配置过程较为复杂,涉及到抢占优先级和响应优先级的概念。程序首先将所有外部中断归为NVIC_PriorityGroup_2,即2位抢占优先级和2位响应优先级:

NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);

然后将所有外部中断信号的抢占优先级规定为0、1、2,使其可以相互区别,并将配置好的参数写入对应寄存器中,完成配置:

NVIC_InitStructure.NVIC_IRQChannel = GPIO_KEY1_EXTI_IRQn; NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; NVIC_Init(&NVIC_InitStructure);

NVIC_InitStructure.NVIC_IRQChannel = GPIO_KEY2_EXTI_IRQn; NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1; NVIC_Init(&NVIC_InitStructure);

NVIC_InitStructure.NVIC_IRQChannel = GPIO_KEY3_EXTI_IRQn; NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2; NVIC_Init(&NVIC_InitStructure)。

初始化完成后,程序进入等待按键中断触发状态,一旦按键按下,则进入中断服务函数EXTI9_5_IRQHandler()(见附录7)中。在函数中对LED灯进行点亮、熄灭操作,并重置中断产生标志位。

实验流程图如下(主函数代码见附录8):

硬件连接方式如下图所示:

2.3实验结果

实验三、定时器实验

3.1实验要求

利用STM32的通用定时器 TIM5 产生一个1S的中断,在中断函数中实现 LED1、LED2、LED3、LED4同时翻转的效果。

3.2原理分析

实验主要考察对STM32F10X系列单片机定时器的使用。

实验中使用的STM32F107单片机有多达10个定时器,包括:

◇多达4个16位定时器,每个定时器有多达4个用于输入捕获/输出比较/PWM 或脉冲计数的通道和增量编码器输入

◇1个16位带死区控制和紧急刹车,用于电机控制的 PWM 高级控制定时器

◇2个独立的看门狗定时器(独立的和窗口型的) ◇系统时间定时器:24 位自减型计数器 ◇2个 16 位基本定时器用于驱动DAC

根据时钟树可知,系统时钟经过分频之后,进入TIM5的时钟模块入口,在经过预分频处理,才供给TIM5作时钟使用。预分频器的系数为:TIMx_PSC,当TIMx_PSC = 0时表示不分频,则TIM5定时器的时钟

用CK_CNT =模块入口时钟72MHz;当TIMx_PSC = 1时表示不分频,则TIM5定时器的时钟用CK_CNT=模块入口时钟36MHz;以此类推。公式为:CK_CNT =fCK_PSC/(PSC[15:0]+1),其中PSC最大为65535。

其次是TIM5计数器计数值的设置,TIM5计数器以CK_CNT为时钟计数,向下计数到0或向上计数到设定值(TIMx_ARR)则产生中断。以向上计数为例,从 0 开始计数到设定值TIMx_ARR 时产生中断。要产生一秒一次中断则要使计数器的值乘以预分频的值=系统时钟72MHz,其中计数器的值和预分频值都必须小于65535。我们使预分频值为7200,计数器值为10000,则7200 * 10000 = 72,000,000即72M。其中拆分方法很多35000*2000 = 72,000,000,只要注意计数器的值和预分频值都必须小于65535即可。当计数值溢出后,会改变计数溢出标志位,并产生定时器中断,实验中使用其产生中断来进行LED灯翻转。

3.3程序分析

LED初始化部分与实验一相同,完成初始化后,点亮所有LED灯。定时器配置函数为TIM5_Init()(见附录6)。配置函数首先使能计数器时钟:

RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM5, ENABLE);