OpenEdv-开源电子网

 找回密码
 立即注册
正点原子全套STM32/Linux/FPGA开发资料,上千讲STM32视频教程免费下载...
查看: 4376|回复: 2

stm32时钟系统中断处理含实例

[复制链接]

25

主题

25

帖子

0

精华

初级会员

Rank: 2

积分
110
金钱
110
注册时间
2020-6-16
在线时间
20 小时
发表于 2020-7-28 14:25:55 | 显示全部楼层 |阅读模式
1金钱
本帖最后由 rich111 于 2020-7-30 16:28 编辑

  1. 设置相应的时钟
  首先需要打开GPIOB、GPIOC和GPIOE(因为按键另外一端连接的是PE口)。然后由于是要用于触发中断,所以还需要打开GPIO复用的时钟。相应的函数在GPIO的学习笔记中有了详细了解释。详细代码如下:
  void RCC_cfg()
  {
  //打开PE PD PC PB端口时钟,并且打开复用时钟
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOE| RCC_APB2Periph_GPIOC | RCC_APB2Periph_GPIOD | RCC_APB2Periph_GPIOB |RCC_APB2Periph_AFIO, ENABLE);
  }
  设置相应的时钟所需要的RCC函数在stm32f10x_rcc.c中,所以要在工程中添加此文件。
  2. 设置好相应的中断
  设置相应的中断实际上就是设置NVIC,在STM32的固件库中有一个结构体NVIC_InitTypeDef,里面有相应的标志位设置,然后再用NVIC_Init()函数进行初始化。详细代码如下:
  void NVIC_cfg()
  {
  NVIC_InitTypeDefNVIC_InitStructure;
  NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); //选择中断分组2
  NVIC_InitStructure.NVIC_IRQChannel= EXTI2_IRQChannel; //选择中断通道2
  NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority= 0; //抢占式中断优先级设置为0
  NVIC_InitStructure.NVIC_IRQChannelSubPriority= 0; //响应式中断优先级设置为0
  NVIC_InitStructure.NVIC_IRQChannelCmd=ENABLE; //使能中断
  NVIC_Init(&NVIC_InitStructure);
  NVIC_InitStructure.NVIC_IRQChannel=EXTI3_IRQChannel; //选择中断通道3
  NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority= 1; //抢占式中断优先级设置为1
  NVIC_InitStructure.NVIC_IRQChannelSubPriority= 1; //响应式中断优先级设置为1
  NVIC_InitStructure.NVIC_IRQChannelCmd=ENABLE; //使能中断
  NVIC_Init(&NVIC_InitStructure);
  NVIC_InitStructure.NVIC_IRQChannel= EXTI9_5_IRQChannel; //选择中断通道5
  NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority= 2; //抢占式中断优先级设置为2
  NVIC_InitStructure.NVIC_IRQChannelSubPriority= 2; //响应式中断优先级设置为2
  NVIC_InitStructure.NVIC_IRQChannelCmd=ENABLE; //使能中断
  NVIC_Init(&NVIC_InitStructure);
  }
  由于有3个中断,因此根据前文所述,需要有3个bit来指定抢占优先级,所以选择第2组。又由于EXTI5-9共用一个中断响应函数,所以EXTI5选择的中断通道是EXTI9_5_IRQChannel,详细信息可以在头文件中查询得到。用到的NVIC相关的库函数在stm32f10x_nivc.c中,需要将此文件复制并添加到工程中。具体位置可以查看关于GPIO的笔记。这段代码编译起来没有任何问题,但是在链接的时候就会报错,需要把STM32F10xR.LIB加入工程中,具体位置在…\Keil\ARM\RV31\LIB\ST\STM32F10xR.LIB。
  3. IO口初始化
  void IO_cfg()
  {
  GPIO_InitTypeDefGPIO_InitStructure;
  GPIO_InitStructure.GPIO_Pin=GPIO_Pin_2; //选择引脚2
  GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz; //输出频率最大50MHz
  GPIO_InitStructure.GPIO_Mode=GPIO_Mode_Out_PP; //带上拉电阻输出
  GPIO_Init(GPIOE,&GPIO_InitStructure);
  GPIO_ResetBits(GPIOE,GPIO_Pin_2); //将PE.2引脚设置为低电平输出
  GPIO_InitStructure.GPIO_Pin= GPIO_Pin_2 | GPIO_Pin_3 | GPIO_Pin_5; //选择引脚2 3 5
  GPIO_InitStructure.GPIO_Mode= GPIO_Mode_IN_FLOATING; //选择输入模式为浮空输入
  GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz; //输出频率最大50MHz
  GPIO_Init(GPIOC,&GPIO_InitStructure); //设置PC.2/PC.3/PC.5
  GPIO_InitStructure.GPIO_Pin= GPIO_Pin_3 |GPIO_Pin_6; //选择引脚3 6
  GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz; //输出频率最大50MHz
  GPIO_InitStructure.GPIO_Mode=GPIO_Mode_Out_PP; //带上拉电阻输出
  GPIO_Init(GPIOD,&GPIO_InitStructure);
  GPIO_InitStructure.GPIO_Pin=GPIO_Pin_5; //选择引脚5
  GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz; //输出频率最大50MHz
  GPIO_InitStructure.GPIO_Mode=GPIO_Mode_Out_PP; //带上拉电阻输出
  GPIO_Init(GPIOB,&GPIO_InitStructure);
  }
  其中连接外部中断的引脚需要设置为输入状态,而连接LED的引脚需要设置为输出状态,初始化PE.2是为了使得按键的另外一端输出低电平。GPIO中的函数在stm32f10x_gpio.c中。
  4. 把相应的IO口设置为中断线路
  由于GPIO并不是专用的中断引脚,因此在用GPIO来触发外部中断的时候需要设置将GPIO相应的引脚和中断线连接起来,具体代码如下:
  void EXTI_cfg()
  {
  EXTI_InitTypeDefEXTI_InitStructure;
  //清空中断标志
  EXTI_ClearITPendingBit(EXTI_Line2);
  EXTI_ClearITPendingBit(EXTI_Line3);
  EXTI_ClearITPendingBit(EXTI_Line5);
  //选择中断管脚PC.2 PC.3 PC.5
  GPIO_EXTILineConfig(GPIO_PortSourceGPIOC,GPIO_PinSource2);
  GPIO_EXTILineConfig(GPIO_PortSourceGPIOC,GPIO_PinSource3);
  GPIO_EXTILineConfig(GPIO_PortSourceGPIOC,GPIO_PinSource5);
  EXTI_InitStructure.EXTI_Line= EXTI_Line2 | EXTI_Line3 | EXTI_Line5; //选择中断线路2 3 5
  EXTI_InitStructure.EXTI_Mode= EXTI_Mode_Interrupt; //设置为中断请求,非事件请求
  EXTI_InitStructure.EXTI_Trigger= EXTI_Trigger_Rising_Falling; //设置中断触发方式为上下降沿触发
  EXTI_InitStructure.EXTI_LineCmd=ENABLE; //外部中断使能
  EXTI_Init(&EXTI_InitStructure);
  }
  EXTI_cfg中需要调用到的函数都在stm32f10x_exti.c。
  5. 写中断响应函数
  STM32不像C51单片机那样,可以用过interrupt关键字来定义中断响应函数,STM32的中断响应函数接口存在中断向量表中,是由启动代码给出的。默认的中断响应函数在stm32f10x_it.c中。因此我们需要把这个文件加入到工程中来。
  在这个文件中,我们发现,很多函数都是只有一个函数名,并没有函数体。我们找到EXTI2_IRQHandler()这个函数,这就是EXTI2中断响应的函数。我的目标是将LED灯点亮,所以函数体其实很简单:
  voidEXTI2_IRQHandler(void)
  {
  //点亮LED灯
  GPIO_SetBits(GPIOD,GPIO_Pin_6);
  //清空中断标志位,防止持续进入中断
  EXTI_ClearITPendingBit(EXTI_Line2);
  }
  voidEXTI3_IRQHandler(void)
  {
  GPIO_SetBits(GPIOD,GPIO_Pin_3);
  EXTI_ClearITPendingBit(EXTI_Line3);
  }
  voidEXTI9_5_IRQHandler(void)
  {
  GPIO_SetBits(GPIOB,GPIO_Pin_5);
  EXTI_ClearITPendingBit(EXTI_Line5);
  }
  由于EXTI5-9是共用一个中断响应函数,因此所有的EXTI5 – EXTI9的响应函数都写在这个里面。
  6. 写主函数
  #include"stm32f10x_lib.h"
  void RCC_cfg();
  void IO_cfg();
  void EXTI_cfg();
  void NVIC_cfg();
  int main()
  {
  RCC_cfg();
  IO_cfg();
  NVIC_cfg();
  EXTI_cfg();
  while(1);
  }
  main函数前是函数声明,main函数函数体中都是调用初始化配置函数,然后进入死循环,等待中断响应。
下面返分享一些视频资料,提供大家学习也可以加裙:1126743406

最佳答案

正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

558

主题

11万

帖子

34

精华

管理员

Rank: 12Rank: 12Rank: 12

积分
164897
金钱
164897
注册时间
2010-12-1
在线时间
2100 小时
发表于 2020-7-28 14:25:56 | 显示全部楼层
回复

使用道具 举报

4

主题

15

帖子

0

精华

新手上路

积分
37
金钱
37
注册时间
2020-9-2
在线时间
8 小时
发表于 2020-9-3 19:06:09 | 显示全部楼层
666666666666666666666666
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则



关闭

原子哥极力推荐上一条 /2 下一条

正点原子公众号

QQ|手机版|OpenEdv-开源电子网 ( 粤ICP备12000418号-1 )

GMT+8, 2024-6-10 20:15

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

快速回复 返回顶部 返回列表