为了顺利过渡到库开发,在STM32编程的开始,我们对照51点亮一个LED的方法,给大家演示一下STM32如何用操作寄存器的方法点亮一个LED,然后再慢慢讲解到底什么是库,让大家知道库跟寄存器的关系。
1. 用51点亮一个LED
在用STM32点亮一个LED之前,我们先来复习下用51如何点亮一个LED。
硬件上我们假设51单片机的P0口的第0位接了一个LED,负逻辑亮。如果我们要点亮这个LED,代码上我们会这么写:
P0 = 0XFE;//总线操作点亮 LED
这时候我们就把LED点亮了,如果要关掉LED ,则是:
P0 = 0XFF;//总线操作关闭 LED
这里面我们用的是总线操作的方法,即是对P0口的8个IO同时操作,但起作用的只是P0^0。
除了这种总线操作的方法,我们还学习过位操作,利用51编译器的关键字sbit,我们可以定义一个位变量:
sbit LED = P0^0;
那么LED = 0,就点亮了LED;
LED = 1,就关闭了 LED。
为了让程序看起来见名知义,我们定义两个宏:
#define ON 0 #define OFF 1
点亮和关闭LED的代码就变成了:
LED = ON;//位操作点亮LED LED = OFF;//位操作关闭LED
稍微整理一下代码,整体效果就是:
//假设51单片机的PO~0口接LED,负逻辑点亮 #define ON 0 #define OFF 1 sbit LED = P0^0; void main(void) { P0 = 0XFE;//总线操作点亮LED P0 = 0XEF;//总线操作关闭LED LED = ON;//位操作点亮LED LED = OFF;//位操作关闭LED }
上面总线和位操作的的方法,学过51的朋友是非常熟悉的,也很容易理解。那么我们再说一下大家容易忽略的几个知识点。
1. 什么是寄存器
在点亮 LED 的时候,我们都是用操作寄存器的方法来实现的,那大家是否想过,这个寄存器到底是什么?为什么我们可以直接操作P0口?
解答上面的问题之前,我们先简单介绍下51单片机的主要组成部分,这对我们学习其他单片机也有好处。
我们以国内的STC89C51为例,该单片机主要由51内核、外设IP、和总线这三大部分组成。内核是由 Intel 公司生产的,外设 IP 就是 STC 公司在内核的基础上添加的诸如定时器、串口、IO 口等这些东西,总线就是用来连接内核和外设的接口单元。Intel 在这里属于IP核设计公司,STC 属于 IC 设计公司。世界上能设计 IP 核的公司屈指可数。我们非常熟悉的ARM公司就属于IP核设计公司,ARM 给其他公司授权,其他IC公司就在ARM内核上设计出各具特色的MCU,我们后面要学习的STM32就是属于一中基于ARM内核的MCU。
寄存器则是内置于各个 IP 外设中,是一种用于配置外设功能的存储器,就是一种内存,并且有想对应的地址。学过C语言我们就知道,要操作这些内存就可以使用C语言中的指针,通过寻址的方式来操作这些具有特殊功能的内存一寄存器。比如 P0 口对应的地址是0X80,那么我们要修改 0X80 这个地址对应的内存的内容的话,按照常理可以这样操作:
*(*0X80) = 0XFE;//点亮LED
可当我们编译的时候,编译器会报错,在51里面只能通过sfr和sbit这两个关键字来实现寄存器映象,不能直接操作寄存器对应的地址,这是51相较于STM32不同的地方。
51单片机的这些寄存器位于地址80H~FFH中,对应着128个地址,但不是每个地址都是有效的,51系列的单片机有21个,52系列的则有26个,其他的都是保留区。
寄存器映射
2. 寄存器映射
实际上我们在编程的时候并不是通过指针来操作寄存器的,而是直接给P0、P1这些端口寄存器赋值。那么这些外设资源是如何与地址建立一一对应的关系(寄存器映射定义),这得益与51特有的两个关键字:sfr和sbit,其他单片机没有,只能用其他的方式来实现寄存器映射。这两个关键字帮我们实现了所有寄存器的定义,所以我们才可以像操作普通变量一样来操作寄存器。其实我们一开始提到的点亮LED的代码,全貌应该是这样的:
sfr P0 = 0x80;//寄存器定义 P0 = 0XFE;//总线操作点亮LED
为了方