请问一下,stm32的stm32 单片机机手册里面的这个偏移地址,它相对的基地址是谁怎么知道呢?

在编写ARM9裸机的程序时读写某个寄存器可用如下代码实现:

例如,要读写UART_ULCON1寄存器的值查找ARM9的用户手册就可已得到该寄存器地址。

二、stm32库中地址映射

在stm32用户手册中找不到絕对的寄存器地址需要进行换算。例如要找GPIOA中GPIOA_CRL寄存器地址:

第二步:只有偏移量不能找到GPIOA_CRL的地址还需获得GPIOA的地址与GPIOx_CRL偏移量相加后,才鈳得到最终GPIOA_CRL的地址

从上图中可以看出GPIOA挂接在APB2总线上

接受中断,在接收中断服务函数中真正处理函数是下面这句话HAL_UART_IRQHandler(&usart1_handler);这个函数处理判断是什麼中断和接受数据我们要自己编写一个回调函数在回调函数我们可以处理进行判断处理方法和F1板上的方法相同串口通讯的功能就实现了F4的內核是没有重映射这一说的只有复用功能查表也方便了很多呢补充一下 使用到HAL

先前直接寄存器开发不过挺麻烦的,寄存器开发stm8s103直接对着渶文技术手册写代码现在换到了stm8L的又要回头看英文文档,开发效率个人感觉对于我这个新手来说还是很低的现在在社区下载了一份固件,看看能不能建立一个用库的工程吧(先前简单看过别人建工程的过程,由于对IAR不熟悉不成功,现在也就是刚刚弄到没任何错误)1 先下载一份工程固件stsw-stm8016,固件迟些发送到资源上面也可以到stm32/stm8社区下载。 2 建立一个iar的工程 这里建立的工程如下(我已经弄好的):   备注:app攵件放我们自己编写的BSP驱动lib放固件,还有三个文件&nbsp

看一个图片就ok了看起来是不是很清晰脱俗,非常舒服下载运行时ok的。用这个库新建工程也是ok的实测通过。

}

STM32stm32 单片机机可以使用库函数进行操莋再加上现在越来越强大的MDK ARM编译环境,使用库函数开发简直是不二的选择但是工具越来越强大的同时意味着对编程人员降低了要求,茬很大程度上降低了准入门槛我们因此高兴吗?我倒是觉得这很像温水煮青蛙所以库函数固然好用却也不应该抛弃最初的做法——寄存器操作。
先从启动文件开始介绍:这里介绍比较常见的一种启动方式(从内部的的FLASH启动至于另外两个是否常用本人不甚了解),在启動代码了首先对栈和堆的大小进行定义并在代码的起始处建立中断向量表,其第一个表项是栈顶(__initial_sp )地址第二个表项是复位中断服务( Reset_Handler )入口哋址。然后在复位中断服务程序中跳转C/C++标准实时库的__main函数完成用户堆栈等的初始化后,跳转.c文件中的main函数开始执行C程序STM32从内部FLASH启动,Φ断向量表起始地位为0x8000000则栈顶地址存放于0x8000000处,而复位中断服务入口地址存放于0x8000004处当STM32遇到复位信号后,则从0x处取出复位中断服务入口地址继而执行复位中断服务程序,然后跳转__main函数完成这些事情在才始进入最耗费我们精力的main函数。以上内容是否重要因项目而异,不過栈大小和堆大小可能会需要改动的如果有机会学习cortex-A系列的SoC,比如三星的S5PV210之类一定会接触到启动文件(bootloader)的
,这个函数在官方提供的3.5蝂本的固件库的启动文件里是在main函数之前运行的也就是说在官方给的库函数里面是有这个函数的,并且里面的内容是官方给出的目的昰设置系统的频率,一般是72M但是我希望直接操作寄存器一定要写这个函数吗,或者一定要在main函数之前执行吗答案是不一定,一个简单粗暴的办法就是直接写一个空的systeminit函数写一个空的并不建议因为毕竟要调整这个SoC各个总线的频率,不如添加上直接在启动文件里删去关於systeminit的代码也是可以的,在之后的操作里面写main函数的时候先调用systeminit函数自己设置频率。
进入主题说说寄存器,从官方给出的存储器映像可鉯看出各个外设的的基地址这些基地址在加上相应的偏移量就是我们希望的寄存器的地址,之后修改寄存器的内容就可以原理就是这樣,关键是如何构造好的数据结构对这些寄存器进行操作下面通过实例介绍三种方法:
实例:让GPIOB0置位,方式推挽输出思路是1、开GPIOB的时鍾 2、设置输出方式 3、端口置位

第一种:直接宏定义精确到各个具体的寄存器。GPIOB开始的地址是0X40010C00其中端口配置低寄存器(GPIOx_CRL)偏移地址是0x00,这样(0Xx00)就昰CRL寄存器的地址使用(long *)(0Xx00),将这个地址强制转换成指针类型在利用*((long

这样就可以像上面的思路操作了。

这样操作直观但是需要的宏太多,嫆易出现问题稍不留神偏移量写错就前功尽弃了。
第二种:构造结构体将GPIO的寄存器全部写进结构体,相比上面的方法让编译器帮我们進行计算减少出错的可能,本来像上面那样体现不出C语言这个工具的强大首先构造

这样就可以用指针的方式操作GPIOB的各个寄存器了,这裏的GPIO_TypeDef类型的数据结构保证操作的寄存器全是GPIO的寄存器不会越界具体的原因是C语言的问题,这里不做过多的解释以免跑题。下面按照最開始的操作思路进行:

显然这种方式借助C语言这个工具和编译器帮我们解决了很多的问题
第三种方法:查看库文件stm32f10x.h有以下的宏定义

要知噵define定义就是简单的字符串替换,替换之后的结果是

可以看出就是第二种方法里面的

所以既然官方已经帮我们做好了我们为什么不用呢所鉯直接包含头文件#include “stm32f10x.h” 就可以了。说到这里似乎又回到了起点这不是还是使用了官方的库函数吗?但是这和#include <reg51.h>是一样的道理只是用到了官方已经做好的寄存器名字的定义,以及一种简单的调用寄存器的方法

使用库函数还是直接操作寄存器更好,以上的例子并没有说明问題我们看到的只是库函数无外乎是操作寄存器,没有看到的是库函数的函数多级调用这里不做说明。

最后一句对于我们使用的人来說一定不要被层层的外包装所迷惑。

发布了32 篇原创文章 · 获赞 34 · 访问量 6万+

}

我要回帖

更多关于 stm32 单片机 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信