2019-11-05-STM32时钟设置

了解一下SystemInit()函数

这个函数是我们进行系统初始化时会使用到的一个函数。它出现在main函数的第一行。可见其重要性。

库函数的工程初始化过程中调用的函数及其顺序为:startup_stm32f10x_hd.s->SystemInit()->SetSysClock()->SetSysClockTo72()

那么SystemInit()函数进行了什么操作呢?——答案是初始化内部Flash以及系统时钟。在我们默认使用该函数时系统时钟被定为72MHz。系统时钟是整个单片机时钟的核心,各种外设的时钟都依托这个系统时钟,我们可以通过一张图看到系统时钟的来源和去向:

image.png

系统时钟的来源为外部晶振,一个是频率为8MHz的椭圆形晶振,还有一个频率为12MHz的小圆柱形晶振,还有内部的两个震荡源。我们可以看到决定系统时钟的几个时钟都连接到PLL,左半边是各个时钟源经过各种分频之后连接到PLL,右边是各种外设时钟使用不同的分频比例。其中AHB有1-512等多种分频方式(2的倍数),APB1频率是系统时钟的一半,APB2频率是系统时钟。

平时使用时只需要了解这个时钟的频率,我们通常情况下会直接调用该函数,将系统时钟频率设置成72MHz,APB1的频率为36MHz,需要修改工作频率的时候,可以通过使用HSE和HSI来配置系统时钟,相关代码可见野火的书P143。

32的位带操作

32有一个很特别的东西——位带操作。我们知道在51的使用中,关于某个特定端口的输出输入我们有时会这么写:用P0.7专门指定一个引脚,输出高就setb,输出低就clr。这种使用方法在32里就不通用了,我们在IO操作那一节就可以看到,我们想要指定一个引脚,必须设置好一个完整的GPIO的结构体指明引脚号啊输入还是输出啊之类的相关信息,非常繁琐。想要更方便操作,可以使用32的位带操作。

位带操作可以简单理解成扩展位或者膨胀

我们知道,单片机的一切外设都由在它片内的某个特殊寄存器设置及控制,想要控制某个外设只需要将相关的寄存器配置好就可以了。32提供了大小为1M的外设位带区,包含了片上外设的全部寄存器,全部寄存器都可以通过访问位带别名区的方式来达到访问原始寄存器的效果(膨胀后映射等效直接连接,大大降低代码的繁琐程度)。

通过这一原理我们可以将“位带地址+位序号”转换成别名地址定义成一个宏。

// 把一个地址转换成一个指针 #define MEM_ADDR(addr) *((volatile unsigned long *)(addr))

// 把位带别名区地址转换成指针 #define BIT_ADDR(addr, bitnum) MEM_ADDR(BITBAND(addr, bitnum))

GPIO位带操作,实现两个寄存器的地址映射后,

1 // GPIO ODR 和 IDR 寄存器地址映射 2 #define GPIOA_ODR_Addr (GPIOA_BASE+12) //0x4001080C 3 #define GPIOB_ODR_Addr (GPIOB_BASE+12) //0x40010C0C 4 #define GPIOC_ODR_Addr (GPIOC_BASE+12) //0x4001100C 5 #define GPIOD_ODR_Addr (GPIOD_BASE+12) //0x4001140C 6 #define GPIOE_ODR_Addr (GPIOE_BASE+12) //0x4001180C 7 #define GPIOF_ODR_Addr (GPIOF_BASE+12) //0x40011A0C 8 #define GPIOG_ODR_Addr (GPIOG_BASE+12) //0x40011E0C 9 10 #define GPIOA_IDR_Addr (GPIOA_BASE+8) //0x40010808 11 #define GPIOB_IDR_Addr (GPIOB_BASE+8) //0x40010C08 12 #define GPIOC_IDR_Addr (GPIOC_BASE+8) //0x40011008 13 #define GPIOD_IDR_Addr (GPIOD_BASE+8) //0x40011408 14 #define GPIOE_IDR_Addr (GPIOE_BASE+8) //0x40011808 15 #define GPIOF_IDR_Addr (GPIOF_BASE+8) //0x40011A08 16 #define GPIOG_IDR_Addr (GPIOG_BASE+8) //0x40011E08

就可以通过位操作的方法来控制GPIO的输入和输出了,宏参数n表示某个IO端口。

在通过宏定义置位函数,可以将输入输出变成更加简单易懂的写法。

1 // 单独操作 GPIO 的某一个IO 口,n(0,1,2...16),n 表示具体是哪一个IO 口 2 #define PAout(n) BIT_ADDR(GPIOA_ODR_Addr,n) //输出 3 #define PAin(n) BIT_ADDR(GPIOA_IDR_Addr,n) //输入 4 5 #define PBout(n) BIT_ADDR(GPIOB_ODR_Addr,n) //输出 6 #define PBin(n) BIT_ADDR(GPIOB_IDR_Addr,n) //输入 7 8 #define PCout(n) BIT_ADDR(GPIOC_ODR_Addr,n) //输出 9 #define PCin(n) BIT_ADDR(GPIOC_IDR_Addr,n) //输入 10 11 #define PDout(n) BIT_ADDR(GPIOD_ODR_Addr,n) //输出 12 #define PDin(n) BIT_ADDR(GPIOD_IDR_Addr,n) //输入 13 14 #define PEout(n) BIT_ADDR(GPIOE_ODR_Addr,n) //输出 15 #define PEin(n) BIT_ADDR(GPIOE_IDR_Addr,n) //输入 16 17 #define PFout(n) BIT_ADDR(GPIOF_ODR_Addr,n) //输出 18 #define PFin(n) BIT_ADDR(GPIOF_IDR_Addr,n) //输入 19 20 #define PGout(n) BIT_ADDR(GPIOG_ODR_Addr,n) //输出 21 #define PGin(n) BIT_ADDR(GPIOG_IDR_Addr,n) //输入

位带操作是一个很有意义的操作,它大大降低了代码编写的难度,使得原先冗长的代码块可以用更加简单易懂的方式替代,使用方法也很简单,在写好头文件后添加即可,头文件有现成的代码集我们这里可以直接用,之后的代码可能都会用位带操作来减少工作量。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 219,539评论 6 508
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 93,594评论 3 396
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 165,871评论 0 356
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,963评论 1 295
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,984评论 6 393
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,763评论 1 307
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,468评论 3 420
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,357评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,850评论 1 317
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 38,002评论 3 338
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 40,144评论 1 351
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,823评论 5 346
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,483评论 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 32,026评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,150评论 1 272
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,415评论 3 373
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 45,092评论 2 355

推荐阅读更多精彩内容

  • 支持了位带操作后,可以使用普通的加载/存储指令来对单一的比特进行读写。在 CM3 中,有两个区中实现了位带。其中一...
    酝锦阅读 678评论 0 0
  • 此文用于记录学习STM32中所学习或者巩固的知识,主要围绕但并不局限于STM32。 本次学习并非为了深入了解使用S...
    yhhk阅读 2,107评论 0 11
  • 计算机系统漫游 代码从文本到可执行文件的过程(c语言示例):预处理阶段,处理 #inlcude , #defin...
    willdimagine阅读 3,586评论 0 5
  • 其实这篇文章主要是介绍自己为其写的GPIO库,自己借鉴了原子写的STM32,野火写的K60,还有LPC官方库,然后...
    杨奉武阅读 768评论 0 0
  • 敬爱的李老师,智慧的班主任,亲爱的跃友们: 大家好!我是来自临沂安地地板的黄从伟。 今天是我的日精...
    黄从伟阅读 125评论 0 0