STM32寄存器的简介、地址查找,与直接操作寄存器 |
您所在的位置:网站首页 › si8621数据手册 › STM32寄存器的简介、地址查找,与直接操作寄存器 |
什么是寄存器
提到单片机,就不得不提到寄存器。根据百度百科介绍,寄存器是中央处理器内的组成部分。寄存器是有限存贮容量的高速存贮部件,它们可用来暂存指令、数据和地址。 手册中没有直接给出所有的寄存器的地址,需要读者稍加计算。STM32给不同的寄存器分配了不同的地址,有点像划分了片区。在《STM32中文参考手册_V10》的第28页,有不同寄存器的地址范围。 现在,假如我们想读取PB3引脚的电平,该怎么找到相关的寄存器?第一步,找到GPIOB的基地址 也就是找到GPIOB的小区。结论是,所有GPIOB相关的寄存器,都住在0x4001 0C00到0x4001 0FFF范围内。 直接访问的操作并不好用,每操作一个寄存器就必须去查看数据手册,然后找找这个寄存器的地址。 意法半导体公司为了方便大家使用,就把这些寄存器都起了一目了然的名字,把寄存器与地址映射关系放在他们提供的头文件里。这个文件就是stm32f10x.h。 直接操作寄存器来点亮LED。我的板子对应的LED是PB8。 首先要配置时钟使能。为什么配置时钟?为了省电,默认的时钟都是关闭的。配置STM32的任何资源前,都必须首先使能时钟。 配置哪个时钟? 时钟的信息在参考手册里边,参考手册十分巨大,不用通读,就像一个字典,需要什么查什么。 参考手册,搜索"时钟",在表1里可以看到。 时钟控制名字叫做RCC,属于AHB总线。GPIOB属于APB2。 既然叫做IO,那么肯定就是可以输入,可以输出,到底是输入还是输出呢? 控制LED需要输出高电平或是低电平,所以需要配置为输出。 由于STM32的每个IO都需要4个位来配置,所以一个32位的寄存器最大只能配置8个IO(32位的单片机的寄存器就是32位的)。STM32中,用端口配置低寄存器(GPIOx_CRL)来配置引脚Px0-Px7, 用端口配置高寄存器(GPIOx_CRH)来配置引脚Px8-Px15。 配置引脚PB8,使用的寄存器是GPIOB_CRH。下面我们来寻找这个寄存器的地址。 在单片机的编程中,要想做某件事,必须寻找相应的寄存器。在8.2.4小节,可以找到端口输出数据寄存器,就是我们需要的。我们需要输出0。但是中文手册有一个小小的BUG,0x0C写成了0Ch,可以参考英文原版。得知地址的偏移是0x0C,所以这个数据寄存器的地址就是0x4001 0C0C,把第8位写为0就行。默认就是0,但是也得学一下怎么写,万一是高电平点亮呢。 在搞清楚我们要用的几个寄存器的地址,以及寄存器中需要装填的数值以后,现在用一个简单粗暴的方法来操作这些寄存器——直接操作。(注意,这段代码不是实用的代码,只是为了写出一个最简单的LED,有些部分是不可取的。)将main函数修改为: int main(void) { unsigned int *pRCC_APB2ENR = (unsigned int *)0x40021018; unsigned int *pGPIOB_CRH = (unsigned int *)0x40010c04; unsigned int *pGPIOB_ODR = (unsigned int *)0x40010c0c; *pRCC_APB2ENR = 0x00000008; *pGPIOB_CRH = 0x44444443; *pGPIOB_ODR = 0x00000000; return 0; } 12345678910C语言总是从main函数开始执行。 定义几个指针,指向刚刚看到的地址。对于编译器来说,它并不知道0x40021018代表的是数据还是指针,所以用(unsigned int *)作强制的类型转换,告诉编译器0x40021018是个指针。指针可以理解为地址。操作指针,把这些地址存放的值修改。 最后的return,代表main函数结束。 总结我们写了一段另类的代码,直接操作寄存器的地址,就是想得到这么一个结论:不论代码怎么写,不论是寄存器,库函数,还是其他的操作系统,要在STM32F103这个单片机点亮LED灯,肯定需要把时钟和GPIO这几个相关的特殊地址,进行赋值或修改数值的操作。有点像打篮球,不论进攻时有怎样花哨的运球与传切配合,最后都要完成把球放入篮筐的动作,才能得分。 |
今日新闻 |
推荐新闻 |
CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3 |