本帖最后由 ren0zhe 于 2013-9-25 14:10 编辑
第三章 点亮发光二极管
本章主要讲了三个方面的知识点
1、时钟配置
2、单步调试
3、GPIO口的配置
学习笔记的pdf版
3科星F107开发板学习笔记—点亮LED灯
3科星F107开发板学习笔记—点亮LED灯.pdf
(1.56 MB)
源码文件
3科星F107开发板学习笔记源码—点亮LED灯
3科星F107开发板学习笔记源码—点亮LED灯.rar
(2.34 MB)
视频教程(请点击下面的链接,进入百度网盘中下载)
3科星F107开发板学习笔记视频—点亮LED灯
http://pan.baidu.com/share/link?shareid=2507935589&uk=2886683799
部分内容如下,详细的请下载附件
时钟对单片机有多重要呢? 可以说单片机,没有了时钟将不能工作;单片机的时钟设置错误了,它将不能正常工作。单片机里面运行的是一条条的指令,运行一条指令的时间是由时钟决定的,可谓单片机之根本,所以时钟这里一定不能出错。 科星F107开发板,使用的是25M的外部晶振,因为一颗25M的外部晶振就可以给各个外设包括USB和以太网提供时钟了。 这里准备使用HSE(外部高速时钟)作为PLL时钟源,PLL时钟作为总线时钟,这里有比较多的专业词汇,刚开始接触的朋友可能比较难理解,后面我们将一一对这些专业术语进行生动的解释。 下面我就以在咱们科星F107开发板上配置72M总线时钟为例讲一下时钟的配置过程。 现在就打开上一节中新建的LED灯的闪烁的空工程,在main.c函数中调用配置时钟的函数SystemInit();如下图
之后点“Make”链接一下,如下图
然后右击SystemInit();点“Go to Definition of SystemInit”就可以进入到函数SystemInit()定义的位置,及函数内容,如下图
下面咱们就来研究ST公司给咱提供的函数,前面一堆设定RCC寄存器的东西,想知道详情的可查看寄存器手册中对RCC的定义,MCU寄存器中英文手册下载地址如下:
RCC在手册中的位置如下图:
CR、CFGR等都可以在这个手册中找到,其实暂时也没必要去细细研究这些,在函数中,每一行代码前面都有一行注释的,看一下注释就大概清楚该句话的作用的了,下面咱们着重研究“SetSysClock()”函数,如下图,它的意思就是设置系统时钟。
下面我们跟上面一样右击该函数,点“Go to Definition of SetSysClock”,进入之后如下图:
这个函数就写的很明白了,就是设置系统时钟为不同的频率数,最大72M,最小24M,还有使用HSE时钟的。很多人这时会有疑问了,这里选用哪个作为系统时钟是在哪设定的呢?下面我们看该函数所在的这个文件的前面几行代码,找到以下这段代码,找不到的请使用查找功能,“Ctrl+F”会弹出查找的对话框,搜一下就可以了 #if defined (STM32F10X_LD_VL) || (definedSTM32F10X_MD_VL) || (defined STM32F10X_HD_VL) /* #define SYSCLK_FREQ_HSE HSE_VALUE */ #defineSYSCLK_FREQ_24MHz 24000000 #else /* #define SYSCLK_FREQ_HSE HSE_VALUE */ /* #define SYSCLK_FREQ_24MHz 24000000 */ /* #define SYSCLK_FREQ_36MHz 36000000 */ /* #define SYSCLK_FREQ_48MHz 48000000 */ /* #define SYSCLK_FREQ_56MHz 56000000 */ #define SYSCLK_FREQ_72MHz 72000000 #endif 这里还有另外一种方法就是看代码所在的行数,如下图所示,红色标记部分会显示光标所在的行数,该行代码在106行,这样就很容易查找了。如下图
下面我们一起来看这段代码,这里是一个if…else结构的宏定义语句,其实跟普通的if…else…的作用是一样的,前面那句if的 #if defined (STM32F10X_LD_VL) || (definedSTM32F10X_MD_VL) || (defined STM32F10X_HD_VL) /* #define SYSCLK_FREQ_HSE HSE_VALUE */ #defineSYSCLK_FREQ_24MHz 24000000 这里的“STM32F10X_LD_VL”、“STM32F10X_MD_VL”和“STM32F10X_HD_VL”是所用单片机的类型,前面咱们提到过的,小存储容量,大存储容量等,咱开发板用的是互联型MCU,带有CL(Connectivity line)后缀的,之前咱们设定好的,这里就有用了,如下图
所以这里的if里面没有,所以就执行 else语句了 #else /* #define SYSCLK_FREQ_HSE HSE_VALUE */ /* #define SYSCLK_FREQ_24MHz 24000000 */ /* #define SYSCLK_FREQ_36MHz 36000000 */ /* #define SYSCLK_FREQ_48MHz 48000000 */ /* #define SYSCLK_FREQ_56MHz 56000000 */ #define SYSCLK_FREQ_72MHz 72000000 这里else语句里面其它时钟值默认是注释掉的,只宏定义了72M,所以,库中默认系统时钟是72M的,这里如果需要改为24M的,就把24M那一行去掉注释,将72M一行加上注释,效果如下: #else /* #define SYSCLK_FREQ_HSE HSE_VALUE */ #defineSYSCLK_FREQ_24MHz 24000000 /* #define SYSCLK_FREQ_36MHz 36000000 */ /* #define SYSCLK_FREQ_48MHz 48000000 */ /* #define SYSCLK_FREQ_56MHz 56000000 */ /*#define SYSCLK_FREQ_72MHz 72000000 */ 这里就定义了咱们的“SetSysClock()”函数执行的是 file:///C:/Users/ZM/AppData/Local/Temp/msohtmlclip1/01/clip_image016.png这条语句。同样,我们右击这个函数,看一下这个函数是如何实现的, 咱们的外部晶振用的是25M的,需不需要改动一些设置呢? 25M的外部晶振,是如何分频,倍频出来的72M呢? 下面我们进函数看看,着重看函数中的下面部分:
这里跟刚才的结构也是一样的,也是if…else…结构的,也是靠宏定义的, #ifdefSTM32F10X_CL /* Configure PLLs------------------------------------------------------*/ /* PLL2 configuration: PLL2CLK = (HSE / 5)* 8 = 40 MHz */ /* PREDIV1 configuration: PREDIV1CLK = PLL2 /5 = 8 MHz */ 刚才的设定这里也用到了
程序中的注释也写明了,计算的方法了,HSE是25M,然后一系列计算得到8M的预分频时钟,后面再9倍频,就得到了72M的系统时钟了。
但是这里有一个疑问,这里没有提到HSE是多少啊?看下图
在main函数包含的头文件“stm32f10x.h”中做出了定义,当类型是“STM32F10X_CL”,默认“HSE_VALUE”的值为25M,如果是其它类型的MCU,就默认为8M的外部晶振,因为科星F107开发板使用的是25M外部晶振,所以在这里咱们就使用默认值就可以了,不用做任何改动了。这个问题也解决了。
刚才计算总线时钟的地方,单纯看公式还是比较抽象的,芯片手册中有一个时钟树,大家可以看一下,下图中对时钟树做了一些标记,可以让我们更形象的了解,从25M的外部晶振是经过什么一系列的过程计算出72M的系统时钟的,看下图:
使用25M外部晶振配置72M总线时钟的流程为“3—19—20—5—7—21—8—9”
真正进行系统时钟计算的就是如下指令了: /* Configure PLLs------------------------------------------------------*/ /* PLL2 configuration: PLL2CLK = (HSE / 5)* 8 = 40 MHz */ /* PREDIV1 configuration: PREDIV1CLK = PLL2/ 5 = 8 MHz */ RCC->CFGR2 &= (uint32_t)~(RCC_CFGR2_PREDIV2 | RCC_CFGR2_PLL2MUL | RCC_CFGR2_PREDIV1| RCC_CFGR2_PREDIV1SRC); RCC->CFGR2 |= (uint32_t)(RCC_CFGR2_PREDIV2_DIV5 | RCC_CFGR2_PLL2MUL8 | RCC_CFGR2_PREDIV1SRC_PLL2 | RCC_CFGR2_PREDIV1_DIV5); ………………….. /* PLL configuration: PLLCLK =PREDIV1 * 9 = 72 MHz */ RCC->CFGR& =(uint32_t)~(RCC_CFGR_PLLXTPRE | RCC_CFGR_PLLSRC | RCC_CFGR_PLLMULL); RCC->CFGR |= (uint32_t)(RCC_CFGR_PLLXTPRE_PREDIV1 |RCC_CFGR_PLLSRC_PREDIV1 | RCC_CFGR_PLLMULL9); “RCC_CFGR2_PREDIV2_DIV5”、“RCC_CFGR2_PLL2MUL8”等都是宏定义的量,我们可以右击它,查看它的定义,如下图
其实宏定义后面的注释就写的很清楚了,是除以5,也就是5分频的意思,同理,下面的“RCC_CFGR2_PLL2MUL8”就是乘以8,也就是8倍频的意思了,下面的雷同,系统时钟就这样计算出来了。
|