ARM单片机的头文件如何用结构体定义地址
下面我们以ARM Cortex-M0内核单片机LPC1114的头文件lpc11xx.h文件进行说明。
1.先说两句
lpc11xx.h文件是lpc11xx系列单片机包含的头文件。这个文件的作用和51单片机中的reg51.h头文件是一个性质,都是用来定义寄存器在单片机中的地址的。
你现在就可以打开reg51.h文件和lpc11xx.h文件看看,对比后你会发现两个主要的区别,首先是lpc11xx.h文件的寄存器定义是用结构体的形式,而reg51.h文件中,寄存器的定义都是一条一条的很直接的地址定义。然后是reg51.h文件中有sfr这样的“伪c语言”,而lpc11xx.h中用的是标准的c语言。C语言的最大用武之地就是单片机,要想学c,就在单片机上学,要想学单片机,就先入门c语言。两者相辅相成的学,效果最好。学以致用,才是学习的最终目标。
2.lpc11xx.h文件中如何定义寄存器地址?
在文件中,定义寄存器地址用到了一下几方面的c语言基础知识:
- 结构体;
- 结构体指针;
- 宏定义#define
- 关键字typedef
- 关键字volatile
- 关键字const
lpc11xx.h文件中,把每个模块都定义了一个结构体,这些模块有SYSCON、IOCON、UART、GPIO、SSP、I2C、WDT、ADC等。
例如,下面是ADC模块的结构体定义:
typedef struct { __IO uint32_t CR; __IO uint32_t GDR; uint32_t RESERVED0; __IO uint32_t INTEN; __IO uint32_t DR[]; __I uint32_t STAT; } LPC_ADC_TypeDef;
结构体的定义有三种形式,我们这里使用的是“直接说明变量”的形式。
lpc11xx.h文件的第566~584行,给每个模块的结构体变量定义了结构体指针,并加了宏定义#define,为的是以后写程序时书写方便。
把鼠标放到uint32_t上面,单击鼠标右键,在弹出的菜单中选择“Go To Definition Of ‘uint32_t’”,如下图所示:
选择后,就会跳到它的定义之处,如下图所示:
typedef是类型重定义关键字,所以实际上,CR寄存器的定义是这样的:
__IO unsigned int CR;
按照同样的方法,可以找到__IO的定义为:
所以,CR寄存器定义实际上是:
volatile unsigned int CR;
volatile关键字的作用是为了让编译器不要优化这个变量。
unsigned int关键字,用来定义无符号的整形变量。
这时候,有人会问,为什么不直接写成这样呢?答:为了阅读方便。
__IO uint32_t CR;
看到这条语句,我们就会知道,CR寄存器是一个“32位的可读可写寄存器”。
volatile unsigned int CR;
同样的这句话,我们对它的了解就不是那么一目了然了。
3.如何查看每个寄存器的地址?
上面讲到,寄存器的地址是由结构体和结构体指针定义的。现在我们来验证一下它的正确性。
我们随便找个寄存器,比如ADC模块的INTEN寄存器(ADC中断允许寄存器),打开LPC1114的用户手册,找到第25章ADC模块部分,如下图所示:
从上面图中,可以看到INTEN的寄存器的地址是0x4001C00C,接下来,我们打开lpc11xx.c文件来验证一下吧。
打开lpc11xx.c文件,找到ADC模块的结构体,如下图所示:
然后再找到LPC_ADC_TypeDef的结构体指针,如下所示:
结构体指针就是用来指向一个地址的,我们来看看上面语句中的LPC_ADC_BASE是什么:
再看看上条语句中的LPC_APB0_BASE是什么:
现在终于挖到底了,原来LPC_ADC_TypeDef指针指向的地址为:
0x40000000+0x1C000=0x4001C000
c语言基础知识:结构体的第一个变量的地址=结构体指针的地址。
所以结构体的第一个变量地址就是0x4001C000,INTEN前面有3个4字节的变量,所以INTEN的地址就是0x4001C00C。
验证完毕。
4.程序中,如何操作寄存器?
C语言基础知识:用结构体变量指针访问结构体中的变量,形式有两种:
- *结构体指针变量.变量名
- 结构体指针变量->变量名
还是拿INTEN寄存器为例,假设我们要给这个寄存器写0x837,可以这样写:
- *LPC_ADC.INTEN=0x837;
- LPC_ADC->INTEN=0X837;
以上两种形式,在写程序的时候,都可以用。人们习惯用第二种形式。
ARM单片机的头文件如何用结构体定义地址的更多相关文章
- c语言_文件操作_FILE结构体解释_涉及对操作系统文件FCB操作的解释_
1. 文件和流的关系 C将每个文件简单地作为顺序字节流(如下图).每个文件用文件结束符结束,或者在特定字节数的地方结束,这个特定的字节数可以存储在系统维护的管理数据结构中.当打开文件时,就建立了和文件 ...
- C语言文件操作 FILE结构体
内存中的数据都是暂时的,当程序结束时,它们都将丢失.为了永久性的保存大量的数据,C语言提供了对文件的操作. 1.文件和流 C将每个文件简单地作为顺序字节流(如下图).每个文件用文件结束符结束,或者在特 ...
- 结构体:探析C#文件方式读写结构体
最近直在研究Net Micro Framework字体文件(tinyfnt)由于tinyfnt文件头部有段描述数据所以很想 定义个结构体像VC样直接从文件中读出来省得用流个个解析很是麻烦 没有想到在中 ...
- Golang Json文件解析为结构体工具-json2go
代码地址如下:http://www.demodashi.com/demo/14946.html 概述 json2go是一个基于Golang开发的轻量json文件解析.转换命令行工具,目前支持转换输出到 ...
- #pragma pack 在BITMAP结构体定义中的使用
BITMAP位图文件主要分为如下3个部分: 块名称 对应Windows结构体定义 大小(Byte) 文件信息头 BITMAPFILEHEADER 14 位图信息头 BITMAPINFOHEADER 4 ...
- C语言根据结构体成员变量的地址,得到结构体的地址
看nginx代码时发现双链表使用的是这种方法,记录一下 给出一个实例来说明 struct father_t { int a; char *b; double c;}f;char *p ...
- Swift类和结构体定义-备
Swift中的类和结构体定义的语法是非常相似的.类使用class关键词定义类,使用struct关键词定义结构体,它们的语法格式如下: class 类名 { 定义类的成员 } struct 结构体名 { ...
- 《从零开始学Swift》学习笔记(Day 25)——类和结构体定义
原创文章,欢迎转载.转载请注明:关东升的博客 Swift中的类和结构体定义的语法是非常相似的.类使用class关键词定义类,使用struct关键词定义结构体,它们的语法格式如下: class 类名 { ...
- Linux中的两个经典宏定义:获取结构体成员地址,根据成员地址获得结构体地址;Linux中双向链表的经典实现。
倘若你查看过Linux Kernel的源码,那么你对 offsetof 和 container_of 这两个宏应该不陌生.这两个宏最初是极客写出的,后来在Linux内核中被推广使用. 1. offse ...
随机推荐
- android 50 进程优先级
程序在磁盘叫程序,程序加载到内存运行起来叫进程,优先级5个级别,内存不足的时候会杀掉低级别进程. Active Process:最上面用户可以操作的. Visible Process:可见进程,部分可 ...
- android 14 进度条和拖动条
进度条: <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:l ...
- 使用blktrace统计磁盘块I/O访问频率 + IO调度CFQ
http://blog.chinaunix.net/uid-24774106-id-4096470.html http://blog.csdn.net/wyzxg/article/details/74 ...
- 关于SqlServer修改数据库常用信息的方法
--系统表里存放各个数据库属性信息的表之一SELECT name AS [Logical Name], physical_name AS [DB File Path],type_desc AS [Fi ...
- Android 5.0以上手机出现找不到so文件
问题描述 最近做项目出了一个bug项目中用到so文件,在5.0以上的手机上会报一个初始化异常错误,并提示找不到so文件.lib里目录结构类似如下 在Android5以下都没有问题,在5.0以上会报错 ...
- Web::Scraper 页面提取分析
一组用来提取HTML文档中元素内容的工具集,它能够理解HTML和CSS选择器以及XPath表达式. 语法 use URI; use Web::Scraper; # First, create your ...
- 『重构--改善既有代码的设计』读书笔记----Self Encapsulate Field
如果你直接访问一个字段,你就会和这个字段直接的耦合关系变得笨拙.也就是说当这个字段权限更改,或者名称更改之后你的客户端代码都需要做相应的改变,此时你可以为这个字段建立设值和取值函数并且只以这些函数来访 ...
- linux 获取cpu百分比
vmstat 1 |head -n 4 |tail -n 1 |awk '{print $13}'
- 原生js实现回到顶部
网页可见区域宽: document.body.clientWidth;网页可见区域高: document.body.clientHeight;网页可见区域宽: document.body.offset ...
- dedecms 文章排列方式
orderby='sortrank' 文档排序方式orderby='hot' 或 orderby='click' 表示按点击数排列orderby='sortrank' 或 orderby='pubda ...