STM32初识---概念了解(下)

文章详细介绍了STM32的复位类型,包括系统复位、电源复位和备份区复位。接着,讨论了时钟控制,包括HSI、HSE和PLL等时钟源,并展示了如何使用CubeMX配置时钟。此外,文章还涵盖了中断的基本概念、EXTI控制器、优先级分组以及NVIC中断管理。最后,通过实例演示了如何使用中断和CubeMX配置GPIO来实现按键控制LED灯,从而提高程序响应速度。
摘要由CSDN通过智能技术生成

复位和时钟控制(RCC)

系统复位

当发生以下任一事件时,产生一个系统复位:

1. NRST引脚上的低电平(外部复位)

2. 窗口看门狗计数终止(WWDG复位)

3. 独立看门狗计数终止(IWDG复位)

4. 软件复位(SW复位)

5. 低功耗管理复位

电源复位

当以下事件中之一发生时,产生电源复位:

1. 上电/掉电复位(POR/PDR复位)

2. 从待机模式中返回

备份区复位

备份区域拥有两个专门的复位,它们只影响备份区域

当以下事件中之一发生时,产生备份区域复位。

1. 软件复位,备份区域复位可由设置备份域控制寄存器 (RCC_BDCR)(见6.3.9节)中的 BDRST位产生。

2. 在VDD和VBAT两者掉电的前提下,VDD或VBAT上电将引发备份区域复位。

时钟控制

什么是时钟?时钟打开,相应的设备工作。

时钟来源?

三种不同的时钟源可被用来驱动系统时钟(SYSCLK)

1. HSI振荡器时钟(高速内部时钟)

2. HSE振荡器时钟(高速外部时钟)

3. PLL时钟(锁相环倍频时钟)

二级时钟源:

1. 40kHz低速内部RC(LSIRC)振荡器

2. 32.768kHz低速外部晶体(LSE晶体)

使用CubeMX来配置时钟:

1. 创建一个新的工程:

 2. 打开SYS,将Debug改成 Serial Wire:

3. 打开RCC配置时钟,将HSE振荡器时钟 配置成 “Crystal ....”:

 4. 打开上方的“Clock Configuration"大选项:

 

 4.1 按照下图,橙色圈中是需要修改的配置,橙色圈中修改完毕后按下回车其他会自动配置:

 4.2 配置完之后的时钟图:

 5. 点击上方的“Project Manager"大选项, 进行每个项目都需要的设置:

 

6. 生成代码:

7. Keil被自动打开,查看main函数中关于时钟部分的代码:

void SystemClock_Config(void)
{
  RCC_OscInitTypeDef RCC_OscInitStruct = {0};
  RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};

  /** Initializes the RCC Oscillators according to the specified parameters
  * in the RCC_OscInitTypeDef structure.
  */
  RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
  RCC_OscInitStruct.HSEState = RCC_HSE_ON;
  RCC_OscInitStruct.HSEPredivValue = RCC_HSE_PREDIV_DIV1;
  RCC_OscInitStruct.HSIState = RCC_HSI_ON;
  RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
  RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
  RCC_OscInitStruct.PLL.PLLMUL = RCC_PLL_MUL9;
  if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
  {
    Error_Handler();
  }

  /** Initializes the CPU, AHB and APB buses clocks
  */
  RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
                              |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
  RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
  RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
  RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV2;
  RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;

  if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_2) != HAL_OK)
  {
    Error_Handler();
  }
}

中断和事件

什么是中断?         

中断是指计算机运行过程中,出现某些意外情况需主机干预时,机器能自动停止正在运行的 程序并转入处理新情况的程序,处理完毕后又返回原被暂停的程序继续运行。

什么是EXTI?         

外部中断/事件控制器(EXTI)管理了控制器的 23 个中断/事件线。每个中断/事件线都对应有一 个边沿检测器,可以实现输入信号的上升沿检测和下降沿的检测。 EXTI 可以实现对每个中断/事 件线进行单独配置,可以单独配置为中断或者事件,以及触发事件的属性。

EXTI的结构体:

1.  EXTI_Line 就是中断/事件线,共23条

2. EXTIMode_TypeDef EXTI_Mode 就是EXTI模式

3. EXTITrigger_TypeDef EXTI_Trigger 就是触发的类型

4. FunctionalState EXTI_LineCmd 就是EXTI的控制

什么是优先级?         

抢占优先级响应优先级的区别:

高优先级的抢占优先级是可以打断正在进行的低抢占优先级中断的。

抢占优先级相同的中断,高响应优先级不可以打断低响应优先级的中断。

抢占优先级相同的中断,当两个中断同时发生的情况下,哪个响应优先级高,哪个先执行。

这两句也就是说,响应优先级再高也不能打断原有的中断,但是当抢占优先级相同时,响应优先级的高低可以决定中断执行的顺序

如果两个中断的抢占优先级和响应优先级都是一样的话,则看哪个中断先发生就先执行

什么是优先级分组?        

 Cortex-M3允许具有较少中断源时使用较少的寄存器位指定中断源的优先级,因此STM32把 指定中断优先级的寄存器位减少到4位,这4个寄存器位的分组方式如下:

第一种分组 第0组:所有4位用于指定响应优先级

第二种分组 第1组:最高1位用于指定抢占式优先级,最低3位用于指定响应优先级

第三种分组 第2组:最高2位用于指定抢占式优先级,最低2位用于指定响应优先级

第四种分组 第3组:最高3位用于指定抢占式优先级,最低1位用于指定响应优先级

第五种分组 第4组:所有4位用于指定抢占式优先级

什么是NVIC?        

STM32通过中断控制器NVIC(Nested Vectored Interrupt Controller)进行中断的管理 。 NVIC是属于Cortex内核的器件,不可屏蔽中断(NMI)和外部中断都由它来处理,但是SYSTICK 不是由NVIC控制的

NVIC的结构体:

1. NVIC_IRQChannel 就是选择中断中断/事件线,共23条

2/3. 分别配置抢占优先级和响应优先级

4. FunctionalState NVIC_IRQChannelCmd 就是NVIC的控制(ENABLE 代表 打开)

什么是中断向量表?         

每个中断源,都有对应的处理程序,这个处理程序称为中断服务程序,其入口地址称为中断向量。所有中断的中断服务程序入口地址构成一个表,称为中断向量表;也有的机器把中断服务程 序入口的跳转指令构成一张表,称为中断向量跳转表。

使用中断的方式点亮LED

之前使用的是轮询的方式,即不断WHILE(1)中查询按钮是否被按下,这样实现虽然看起来没什么问题,但是其实 实际会有一些小小的时间延迟,比如我按下按钮2,系统还是会先检测是否按下按钮1,如果代码一多,时间的滞后就会更加明显,所以使用中断的方式是一种更好的解决方法。

1. 在CubeMX进行时钟和GPIO口的配置:

1.1 

1.2 

1.3

1.4  

 

1.5(这步很重要,因为之前的轮询法此处配置的是GPIO_Input)

 

根据原理图可知,按键按下时对应GPIO口会被拉低,所以可以将PA0和PA1EXTI模式配置成下降沿触发

1.6 (打开中断)

 由于现在只有两个中断,所以抢占优先级和响应优先级可以先不用设置!

1.7

1.8

2. 在Keil5进行main函数的编写:

2.1 打开gpio.c 可以看到对于刚刚四个GPIO口的设置:

2.2 打开stm32f1xx_it.c 可以看到各种中断相关的函数(Handler),拉到最低,可以看到EXTI0和EXTI1的中断相关函数:

 可见,两个中断处理函数都跳转到了一个函数,不同的就是输入的参数,右键跳转这个HAL_GPIO_EXTI_IRQHandler():(跳转前先编译,否则识别不到)

 可见,这个函数又在调用这个HAL_GPIO_EXTI_Callback的函数,而这个函数的定义也就在下面,并附上了前缀“__weak”,这个意思是这个函数可以被重写,其实这就是中断处理函数,只需要在main函数中,重写这个函数达到想要的目的就可以:

2.3  编写中断处理函数

void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{
	switch(GPIO_Pin)
	{
		HAL_Delay(50); //在检测到按键被按下的低电平的时候,先延迟50ms,再进行判断
		case GPIO_PIN_0: //如果A0对应的按钮按下
			if(HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_0) == GPIO_PIN_RESET){ //如果延迟过后依然是低电平
				HAL_GPIO_TogglePin(GPIOB,GPIO_PIN_8); //反转LED1的状态
			}
		break;
		
		case GPIO_PIN_1: //如果A1对应的按钮按下
			if(HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_1) == GPIO_PIN_RESET){ //如果延迟过后依然是低电平
				HAL_GPIO_TogglePin(GPIOB,GPIO_PIN_9); //反转LED2的状态
			}
		break;
	}
	
}

2.4 编译并烧录 

3. 实现效果

用更好的方法实现了之前轮询实现的按键点灯!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值