美文网首页
时钟问题

时钟问题

作者: BIGHAI | 来源:发表于2017-12-16 22:12 被阅读0次

open这个系统调用会建立一条到文件或者设备的访问路径,如果open调用成功的话,那么它将返回一个可以被read系统调用,write系统调用等方法使用的文件描述符。文件描述符是唯一的,他不会与任何其它运行中的进程共享。如果两个进程同时打开一个文件的话,那么它们将会得到两个不同的文件描述符,如果这两个进程都对文件进行写操作的话,那么它们会各写各的,这就造成了一个问题,谁也搞不清哪部分数据将会被覆盖。对此,我们要利用文件锁来防止这种问题的出现。


STM32时钟树

当芯片开始复位的时候,代码的执行顺序是先调用SystemInit函数,接着在进入_main函数(注意这个函数与main函数的区别,_main是一个c标准库的初始化函数),执行完_main函数后,最终才会执行用户文件里面所定义的main函数。

至于为什么会是这样,我们可以看看芯片的启动文件。对于我们的STM32芯片来说,ST已经提供了启动文件startup_stm32f10x_hd.s启动文件,我们截取相关的部分代码如下:

Reset_Handler PROC
  EXPORT Reset_Handler
  IMPORT __main ;从外部导入__main方法
  IMPORT SystemInit ;同理
  LDR R0, = SystemInit ;方法地址存储在了r0寄存器
  BLX R0;跳转执行SystemInit
  LDR R0, =__main
  BX R0
 ENDP

从启动代码我们可以看出,先是SystemInit,接着是__main,最后才是main。

回到时钟问题上。如果我们想要使用某个外设的话,那么必须先配置好系统时钟SYSCLK,接着在开启外设时钟。为了配置好系统时钟SYSCLK,我们需要设置好一系列的时钟来源,倍频,分频等参数,这些工作都是由system_stm32f10x.c文件定义的SystemInit所完成。对于SystemInit函数来说,它的工作流程是这样的:首先将与配置时钟相关的寄存器都复位为默认值,复位寄存器后,接着调用SetSysClock函数,而对于SetSysClock来说,它又是根据条件编译宏来调用最底层的设置系统时钟的函数,这里指的这些函数都已经是相当底层了,都是直接更寄存器打交道。下面我们可以看看SetSysClock函数。

static void SetSysClock(void){
  #ifdef SYSCLK_FREQ_HSE
    SetSysClockToHSE();
  #elif defined SYSCLK_FREQ_24MHz
    SetSysClockTo24();
  #elif defined SYSCLK_FREQ_36MHz
    SetSysClockTo36();
  #elif defined SYSCLK_FREQ_48MHz
    SetSysClockTo48();
  #elif defined SYSCLK_FREQ_56MHz
    SetSysClockTo56();  
  #elif defined SYSCLK_FREQ_72MHz
    SetSysClockTo72();
  #endif
}

接着看看ST库定义的条件编译宏,根据这些宏我们可以看出对于我们的stm32f103ze开发板来说,它的系统时钟SYSCLK默认是72mhz的。

#if defined (STM32F10X_LD_VL) || (defined STM32F10X_MD_VL) || (defined STM32F10X_HD_VL)
/* #define SYSCLK_FREQ_HSE    HSE_VALUE */
 #define SYSCLK_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

重要的事情多说一遍,对于我们的STM32F10XZE开发板来说,它的系统时钟SYSCLK默认是72mhz。

言归正传,既然配置系统时钟的问题已经让system_stm32f10x.c文件定义的SystemInit函数给完成了,那么我们接下来要做的工作就是开启外设时钟,对于外设时钟来说,我们知道外设挂载在两条总线上,分别为APB1低速外设总线以及APB2高速外设总线。歪个题,在开发板中有AHB总线,APB1,APB2。其中高速外设总线APB2使用的时钟是PCLK2时钟,它的默认值就是SYSCLK也就是说挂载在高速外设总线的外设使用的时钟频率都是72mhz。对于低速外设总线APB1来说,它所使用的时钟就是PCLK1时钟。对于APB1外设以及APB2外设来说,开启外设时钟所使用的库函数是不同的,分别为RCC_APB1PeriphClockCmd()以及RCC_APB2PeriphClockCmd()。

一个问题为什么在配置好了系统时钟SYSCLK之后还得费力开启外设时钟?答案就是为了减少功耗。

关于开启时钟需要注意的问题,如果我们使用了IO引脚的复用功能的话,那么我们还得开启复用功能对应外设的时钟。比如我们如果想利用GPIOX的某个引脚为ADC采集引脚的话,那么就得像下面这样做:

RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOX, ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADCX, ENABLE);

关于控制I/O引脚输出高低电平的问题,很简单就是通过控制GPIOX_BSRR寄存器上相应的值,前16位是set,后16位是reset。对于ST库来说,它提供了GPIO_SetBits(GPIOX,GPIO_Pin_x)来set以及GPIO_ResetBits(GPIOX,GPIO_Pin_x)来reset。


c语言编写头文件小技巧,形如下面这样:

#ifndef __LED_H
#define __LED_H
...
#endif

为什么需要这样做呢?答案是为了防止头文件重复包含。为什么还要两条下划线?也没什么,因为很少有这样命名变量的习惯,因此这样做可以避免重名。


END

相关文章

  • 时钟问题

    open这个系统调用会建立一条到文件或者设备的访问路径,如果open调用成功的话,那么它将返回一个可以被read系...

  • 时钟问题

    在开发过程中有些产品经理会提出自己写一个时钟的有控件,来显示时间,下面就做一些简单的介绍 首先简单介绍一下弧度和角...

  • 奥数 | 时钟问题

  • 复盘 | 时钟问题

  • Tick or Tick 时钟问题

    一个很绕的计算题 hdu~[Tick and Tick]http://acm.hdu.edu.cn/showpro...

  • CentOS7时钟同步问题

    CentOS7时钟同步问题 最近项目中遇到个比较棘手的问题,虽然配置了时钟同步,但有些主机(虚拟机)时钟偏移量有些...

  • DDIA-分布式系统的麻烦

    综述 本章讨论了分布式系统面临的麻烦事,网络问题(无法完全保障的网络)、时钟和时序问题(不可靠时钟),以及面对这些...

  • 分布式系统中逻辑时钟和向量时钟

    为什么在分布式系统中时钟是个问题? 软件应用依赖计算机的时钟 (Clocks) 来解决多种问题,如判断多个请求到来...

  • Linux时钟命令用法及演示

    linux时钟 linux时钟分为系统时钟和硬件时钟。系统时钟是指当前linux kernel中的时钟,而硬件时钟...

  • 豆豆上小学之时钟问题

    今天妈妈老师给豆豆拓展了时钟问题。 时针是长的还是短的? 分针是粗的还是细的? 时针走一格是几小时? 分针走一格是...

网友评论

      本文标题:时钟问题

      本文链接:https://www.haomeiwen.com/subject/fujewxtx.html