实验指导书1-5 下载本文

内容发布更新时间 : 2024/12/26 1:46:15星期一 下面是文章的全部内容请认真阅读。

《嵌入式系统开发》0806504130 实验指导书

NVIC_Init(&NVIC_InitStructure); //中断优先级分组初始化 (4)中断服务函数

我们配置完中断优先级之后,接着要做的就是编写中断服务函数。中断服务函数的名字是在MDK中事先有定义的。这里需要说明一下,STM32的IO口外部中断函数只有6个,分别为:

EXPORT EXTI0_IRQHandler EXPORT EXTI1_IRQHandler EXPORT EXTI2_IRQHandler EXPORT EXTI3_IRQHandler EXPORT EXTI4_IRQHandler EXPORT EXTI9_5_IRQHandler EXPORT EXTI15_10_IRQHandler

中断线0-4每个中断线对应一个中断函数,中断线5-9共用中断函数EXTI9_5_IRQHandler,中断线10-15共用中断函数EXTI15_10_IRQHandler。在编写中断服务函数的时候会经常使用到两个函数,第一个函数是判断某个中断线上的中断是否发生(标志位是否置位):

ITStatus EXTI_GetITStatus(uint32_t EXTI_Line);

这个函数一般使用在中断服务函数的开头判断中断是否发生。另一个函数是清除某个中断线上的中断标志位:

void EXTI_ClearITPendingBit(uint32_t EXTI_Line);

这个函数一般应用在中断服务函数结束之前,清除中断标志位。 常用的中断服务函数格式为: void EXTI2_IRQHandler(void) {

if(EXTI_GetITStatus(EXTI_Line2)!=RESET)//判断某个线上的中断是否发生 {

中断逻辑…

EXTI_ClearITPendingBit(EXTI_Line2); //清除LINE上的中断标志位 } }

在这里需要说明一下,固件库还提供了两个函数用来判断外部中断状态以及清除外部状态标志位的函数EXTI_GetFlagStatus和EXTI_ClearFlag,他们的作用和前面两个函数的作用类似。只是在EXTI_GetITStatus函数中会先判断这种中断是否使能,使能了才去判断中断标志位,而EXTI_GetFlagStatus直接用来判断状态标志位。 (5)使用IO口外部中断的一般步骤:

1)初始化IO口为输入。

2)开启IO口复用时钟,设置IO口与中断线的映射关系。 3)初始化线上中断,设置触发条件等。 4)配置中断分组(NVIC),并使能中断。 5)编写中断服务函数。 3.5软件设计(学生完成)

完成中断函数exti.c、exti.h的编写。

提示:WK_UP(PA0)按键的中断检测, void EXTI0_IRQHandler(void)是外部中断0的服务函数,KEY0(PC5)按键的中断检测,void EXTI9_5_IRQHandler (void)是外部中断5~9的

10

《嵌入式系统开发》0806504130 实验指导书

服务函数;KEY1(PA15)按键的中断检测,void EXTI15_10_IRQHandler (void) 是外部中断10~15的服务函数。

编写:void EXTIX_Init(void) // 外部中断初始化函数 void EXTI0_IRQHandler(void) //中断0函数

void EXTI9_5_IRQHandler(void) //中断5函数 void EXTI15_10_IRQHandler(void) //中断15函数 (学生完成程序)

四、实验结果与分析

将调试结果的照片粘贴在这里。

11

《嵌入式系统开发》0806504130 实验指导书

实验四 PWM输出实验

实验时间:2016-04-26(周二3,4节),实验学时:2,实验地点:C105

一、实验目的与要求:

(1)掌握STM32定时器的结构

(2)掌握STM32中断配置的基本方法;

(2)使用STM32的定时器来产生PWM输出、改变占空比;

二、实验器材:

计算机,STM32F103RCT6实验平台。

三、实验过程

本实验用到的硬件资源有: 1) 指示灯DS0 2) 定时器TIM3

从TIM1_CH1通道和CH2通道的输出两列互补的20KHz的PWM波,从原理图(图6.2.1)可以看到,TIM1_CH1是和PA8复用的,而TIM1_CH2是和PA9复用的,占空比从0%-80%可调。

主要配置步骤如下:

1)开启TIM1时钟,使能PA时钟,配置PA8、PA9为复用输出。

要使用TIM1,我们必须先开启TIM1的时钟,还要配置PA8、PA9为复用输出(当然还要时能PORTA的时钟),这是因为TIM1_CH1、CH2通道将使用PA8、PA9的复用功能作为输出。库函数使能TIM1时钟的方法是:

RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1, ENABLE); //使能定时器1时钟 RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA , ENABLE); //使能GPIO外设时钟使能

设置PA8、PA9为复用功能输出的方法在前面的几个实验都有类似的讲解,这里简单列出GPIO初始化的一行代码即可:

GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //复用推挽输出 2)设置TIM1的ARR和PSC。

在开启了TIM1的时钟之后,我们要设置ARR和PSC两个寄存器的值来控制输出PWM的周期。当PWM周期太慢(低于50Hz)的时候,我们就会明显感觉到闪烁了。因此,PWM周期在这里不宜设置的太小。这在库函数是通过TIM_TimeBaseInit函数实现的,在上一节定时器中断章节我们已经有讲解,这里就不详细讲解,调用的格式为:

TIM_TimeBaseStructure.TIM_Period = arr; //设置自动重装载值 TIM_TimeBaseStructure.TIM_Prescaler =psc; //设置预分频值

12

《嵌入式系统开发》0806504130 实验指导书

TIM_TimeBaseStructure.TIM_ClockDivision = 0; //设置时钟分割:TDTS = Tck_tim TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; //向上计数模式 TIM_TimeBaseInit(TIM1, &TIM_TimeBaseStructure); //根据指定的参数初始化TIMx的 3)设置TIM1_CH1、CH2的PWM模式及通道方向, 使能TIM1的CH1、CH2输出。

接下来,我们要设置TIM1_CH1、CH2为PWM模式(默认是冻结的),因为我们的DS0是低电平亮,而我们希望当CCR1的值小的时候,DS0就暗,CCR1值大的时候,DS0就亮,所以我们要通过配置TIM1_CCMR1的相关位来控制TIM1_CH1的模式。在库函数中,PWM通道设置是通过函数TIM_OC1Init()~TIM_OC4Init()来设置的,不同的通道的设置函数不一样,这里我们使用的是通道1、2,所以使用的函数是TIM_OC1Init()、TIM_OC2Init()。

void TIM_OC1Init(TIM_TypeDef* TIMx, TIM_OCInitTypeDef* TIM_OCInitStruct); void TIM_OC2Init(TIM_TypeDef* TIMx, TIM_OCInitTypeDef* TIM_OCInitStruct); 这种初始化格式大家学到这里应该也熟悉了,所以我们直接来看看结构体TIM_OCInitTypeDef的定义:

typedef struct {

uint16_t TIM_OCMode;

uint16_t TIM_OutputState; uint16_t TIM_OutputNState; */

uint16_t TIM_Pulse; uint16_t TIM_OCPolarity; uint16_t TIM_OCNPolarity; uint16_t TIM_OCIdleState; uint16_t TIM_OCNIdleState; } TIM_OCInitTypeDef;

这里我们讲解一下与我们要求相关的几个成员变量:

参数TIM_OCMode设置模式是PWM还是输出比较,这里我们是PWM模式。 参数TIM_OutputState用来设置比较输出使能,也就是使能PWM输出到端口。 参数TIM_OCPolarity用来设置极性是高还是低。

其他的参数TIM_OutputNState,TIM_OCNPolarity,TIM_OCIdleState和TIM_OCNIdleState是高级定时器TIM1和TIM8才用到的。

要实现我们上面提到的场景,方法是:

TIM_OCInitTypeDef TIM_OCInitStructure;

TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM2; //选择PWM模式2 TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; //比较输出使能 TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High; //输出极性高 TIM_OC1Init(TIM1, &TIM_OCInitStructure); //初始化TIM1 OC1 4)使能TIM1。

在完成以上设置了之后,我们需要使能TIM1。使能TIM1的方法前面已经讲解过: TIM_Cmd(TIM1, ENABLE); //使能TIM1 5)设置MOE输出,使能PWM输出。

普通定时器在完成以上设置了之后,就可以输出PWM了,但是高级定时器,我们还需要 使能刹车和死区寄存器(TIM1_BDTR)的MOE位,以使能整个OCx(即PWM)输出。库函数的设置函数为:

TIM_CtrlPWMOutputs(TIM1,ENABLE); // MOE主输出使能

13

《嵌入式系统开发》0806504130 实验指导书

TIM_OC1PreloadConfig(TIM1, TIM_OCPreload_Enable); //CH1预装载使能 TIM_OC2PreloadConfig(TIM1, TIM_OCPreload_Enable); //CH2预装载使能 6)修改TIM1_CCR1来控制占空比。

最后,在经过以上设置之后,PWM 其实已经开始输出了,只是其占空比和频率都是固定的,而我们通过修改TIM1_CCR1则可以控制CH1的输出占空比。继而控制DS0的亮度。 在库函数中,修改TIM1_CCR1占空比的函数是:

void TIM_SetCompare1(TIM_TypeDef* TIMx, uint16_t Compare1);

理所当然,对于其他通道,分别有一个函数名字,函数格式为TIM_SetComparex(x=1,2,3,4)。 通过以上6个步骤,我们就可以控制TIM1的CH1输出PWM波了。 软件设计(学生完成)

完成中断函数pwm.c、pwm.h及main.c的编写。 下载验证

在完成软件设计之后,将我们将编译好的文件下载到MiniSTM32开发板上,用示波器观看产生的CH1、CH2通道的波形。 四、实验结果与分析

1、将调试结果的示波器波形图粘贴在这里。 2、思考实现互补的PWM波形有哪两种方法? 方法一:在设置CH1

TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM2; // TIM1脉冲宽度调制模式2 TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High; //TIM输出比较极性高 在设置CH2时

TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_Low; // TIM输出比较极性低 方法二呢?

3.写出产生PWM频率为20kHz的设置方法:

f?72MHz/(arr?1)/(psc?1)

arr=? Psc=?

14