前言:
这是第六个实验,实验五的博客我没有写,不是因为太简单了,而是因为太难了,当初给我直接干蒙圈了,其实实验五的代码很简单,就是深入底层配置寄存器原理,我就直接跪了,想要把实验五的博客写出来,至少又得几万字博客,光想想就害怕,还是之后有时间了再写吧。
这个实验,是一个很简单的实验。就是配置一下时钟,利用时钟来点亮LED灯,来,上实验。
一、创建工程。
创建工程,还是选择原来的F407的板子。剩下的就是配置管脚的操作了,这次仅仅只用到了4个管脚。
两个用于LED,两个用于RCC时钟。
LED电路图如图所示:
这次我们要用LED1和LED2所以,配置管脚的时候就用的PF9和PF10管脚,时钟的话,还是选择之前的时钟
配置时钟也和之前是一样的
其他的,就没什么了,因为我们这次用的是Cortex System timer,注意这里有一个DIV1的操作,这个选择可以改,但是会影响到之后的代码生成,稍后再说。
生成工程:
二、编辑工程,编译工程
生成功成之后,使用Keil5打开源代码工程,主要就是再main.c中添加两句话:
代码添加完毕之后,点击Build,成功后点击LOAD下载到板子上。
下载到板子上之后,点击复位键,可以看到LED1每隔500个tick亮或灭一次,LED2每隔1秒亮或灭一次。(实验结果照片我有,但我就不放上来,诶,就是玩…哈哈哈哈)
三、源代码分析
这个源代码分析其实就很简单了,主要是这两个LED的亮灭原理不太一样,分着说一下吧。
综述
首先说一下综合的时钟配置。之前再Cube上配置系统时钟的时候,我用紫圈画把/1
这里圈出来了,这个一共有两个选项,/1 /8
,他们的应用主要是在这里。
在main.c中初始化的时候,会有一个配置时钟的函数,在这个函数里面
有一个这个函数,可以看到这里面是/1000,这个对应的就是/1,如果当初选择了/8,那么这里就是/8000。
点开HAL_RCC_GetHCLKFreq()函数:
可以看到它返回的是系统核心时钟,点开这个变量。可以看到这个变量被初始化为16000000
好了对于这个SystemCoreClock,下面说一下我自己的看法。对于每个时钟都有一个倒计数定时器,每一个脉冲到来时,就会将定时器的数值减一,当减到0的时候,会产生一次异常中断。上面说的这个变量,就是每秒可以产生这么多个时钟脉冲,也就是在1秒内可以将16000000减到0,产生中断,转向中断服务函数。
具体的理解可以参照:SysTick
而在本例中,将系统时钟设置为SystemCoreClock的千分之一,也就是说,减到0产生异常中断的时间为1ms,也就是每1ms产生一次中断,进入一次中断服务函数。
时钟脉冲配置好后,它的脉冲频率就不变了,我们能做的是调整多少个脉冲后进入一次时钟中断处理函数。
HAL_SYSTICK_Config()函数的内容如下:
可以看到之前的SystemCoreClock/1000被加载进reload寄存器中,当被减到0的时钟自动重载。
LED1
对于LED1,它连的是PIN10管脚,代码如下:
可以明显的看到这是一个回调函数。那么我们就查看一下,中断处理函数叭。
中断处理函数里面有两个函数,现在我们已经知道了,每1ms调用一次中断处理函数。
函数一的内容如下:
可以看到这个uwTick是一个全局变量,在中断处理函数中,每1ms使其加一。
函数二的内容如下:
可以看到,这里就是系统中断调用回调函数的过程,也就是说,这个LED1的处理其实是在中断服务程序中被点亮或者被熄灭的,这样很不好,会影响中断服务程序的处理时间,影响系统的实时性。
LED2
可以看到LED2是通过系统延时来实现的点亮或者熄灭。查看延时函数的实现:
其中的HAL_GetTick()函数实现如下:
可以看到,延时函数,用到了中断服务程序中的函数一,用的是全局变量uwTick,这样的做法就比较欣赏,中断服务程序仅仅只是改变一个标志,并不会具体执行某一个具体行为。可以有效减少中断处理函数的执行时间。
在LED2的处理中,可以看到是通过一个while循环来实现延时的,其实这个做法,我觉得也不太好,while循环会一直占据CPU资源,在多任务环境中,它不会放弃CPU资源,会影响多任务的执行。
四、结语
好了,这个实验,到目前为止,就已经结束了,可以看到,这个实验还是很简单的实验。害,实验五我还是有时间补上来叭,太难了。。。