C语言访问存储器的方法

在单片机中我们经常需要访问某个指定的寄存器或者到指定的RAM地址,在本文为简单描述,下文所说的存储器可指:寄存器,RAM等。
01
宏定义:
定义一个宏,将地址值转化为C指针,然后取这个指针指向的内容,这样就可以访问存储了,代码如下:
#define SDA_DIR_REG *(__IO uint32_t *)SDA_MOD_OFFSET

分析:

(__IOuint32_t *)SDA_MOD_OFFSE    是强制类型转换强制转换为指针
*(__IOuint32_t *)SDA_MOD_OFFSET   取这个指针里内容。
这是一种很简单实用的方法,对于访问某个寄存器是很长好用的。
举例:
*(__IOuint16_t *) (((uint32_t)0x60020000) )

(((uint32_t)0x60020000))是32位的IO地址(物理地址,硬件上设定的,不可修改) *(__IO uint16_t*)是读取该地址的参数值,其值为16位参数。

实际上是读取0x60020000寄存器的参数,或者可以说是这个IO口现在的状态。
02
结构体:

将存储器定义为一种数据结构,然后定义一个指向结构体的指针。

符合CMSIS的设备驱动库就是这样做的
typedef struct{ __IO uint32_t MODER; /*!< GPIO port mode register, Address offset: 0x00 */ __IO uint32_t OTYPER; /*!< GPIO port output type register, Address offset: 0x04 */ __IO uint32_t OSPEEDR; /*!< GPIO port output speed register, Address offset: 0x08 */ __IO uint32_t PUPDR; /*!< GPIO port pull-up/pull-down register, Address offset: 0x0C */ __IO uint32_t IDR; /*!< GPIO port input data register, Address offset: 0x10 */ __IO uint32_t ODR; /*!< GPIO port output data register, Address offset: 0x14 */ __IO uint16_t BSRRL; /*!< GPIO port bit set/reset low register, Address offset: 0x18 */ __IO uint16_t BSRRH; /*!< GPIO port bit set/reset high register, Address offset: 0x1A */ __IO uint32_t LCKR; /*!< GPIO port configuration lock register, Address offset: 0x1C */ __IO uint32_t AFR[2]; /*!< GPIO alternate function registers, Address offset: 0x20-0x24 */} GPIO_TypeDef;
#define PERIPH_BASE ((uint32_t)0x40000000)#define AHB1PERIPH_BASE (PERIPH_BASE 0x00020000)#define GPIOC_BASE (AHB1PERIPH_BASE 0x0800)#define GPIOC ((GPIO_TypeDef *)GPIOC_BASE)

大家看着上面的代码应该很熟悉,这就是我在ST给的标准外设库中复制的,这也是CMSIS标准的驱动发方式。

我在《STM32驱动LCD实战》文中就是使用这种方式驱动操作LCD。代码如下。
typedef struct{    uint8 LCD_CMD;//用于LCD命令操作    uint8 LCD_DATA;//用于LCD数据操作} LCD_TypeDef;#define LCD_BASE        ((uint32_t)(0x60000000 | 0x0000FFFF))#define LCD             ((LCD_TypeDef *) LCD_BASE)

详解如下:

LCD->LCD_CMD :是地址((uint32_t)(0x60000000| 0x0000FFFF))上的数据
LCD->LCD_DATA:是地址((uint32_t)(0x60000000| 0x00010000))上的数据
这种驱动方式更加简洁,代码结构化。个人也更喜欢这种方式。
03
对比
方法1:简单,但是生成代码效率低,因为寄存器的地址值都会被存储为常量,代码体积会变大。由于需要访问的更多寄存器来设置地址值,运行速度会更低。不过,若外设控制代码值操作1个寄存器,效率就和方法2相同了
方法2:允许外设中的多个寄存器共用一个常量作为基地址。访问每个寄存器时可以用立即数偏移寻址模式。
END
(0)

相关推荐

  • 不得不说,关于 *(unsigned long *) 和 (unsigned long)

    看讨论学知识 @辛昕: 然而我很悲伤地再次郑重声明:我木有错!具体请看我回复 水果君 那难得一见的长回帖的回帖!! 这事情居然还可以从遥远的 2月2号 刚下班放假那天开始. 那天,水群里,水果君弄了个 ...

  • 原来搞单片机也可以面向对象

    摘要:在看别人单片机程序时,你也许是奔溃的,因为全局变量满天飞,不知道哪个在哪用了,哪个表示什么,而且编写极其不规范.自己写单片机程序时,也许你也是奔溃的.总感觉重新开启一个项目,之前的写过相似的代码 ...

  • 从这些知识点入手,学单片机就简单多了

    自从CubeMX等图像配置软件的出现,同学们往往点几下鼠标就解决了单片机的配置问题.对于追求开发速度的业务场景下,使用快速配置软件是合理的,高效的,但对于学生的学习场景下,更为重要的是知其然并知其所以 ...

  • 火爆全网开源额温枪同平台之华大HC32L136 SDK开发入门

    到淘宝以及相关平台上不少商家为了蹭疫情额温枪的热度把额温枪开发方案的价格定得非常高,少则几千,多则上万,实在是让国人寒心!关键时刻,大家应该同心协力,即将没法向白衣天使一样上前线去抗疫,也应该以别的方 ...

  • 【Edge访问谷歌地球】用Edge浏览器访问谷歌地球 方法简单又实用

    【Edge访问谷歌地球】用Edge浏览器访问谷歌地球 方法简单又实用

  • 拒绝访问磁盘拒绝访问的恢复方法

    磁盘跟其他的机器一样,使用久了难免会出故障,比如常见的弹出一个拒绝访问的对话框,吓你一跳,整个磁盘都损坏的意思,那里面的资料怎么办呢,所以很多人很着急,其实遇到这种情况一般都是之前使用不当造成的,比如 ...

  • ”net start mysql 发生系统错误 5, 拒绝访问”的解决方法

    "net start mysql 发生系统错误 5, 拒绝访问"的解决方法:以管理员的权限打开cmd.运行-->cmd--> 右键以管理员权限打开即可解决.

  • OpenCV探索之路(十七):Mat和IplImage访问像素的方法总结

    在opencv的编程中,遍历访问图像元素是经常遇到的操作,掌握其方法非常重要,无论是Mat类的像素访问,还是IplImage结构体的访问的方法,都必须扎实掌握,毕竟,图像处理本质上就是对像素的各种操作 ...

  • 电脑隐藏文件图文教程,计算机硬盘显示直接访问隐藏文件夹方法

    大家好,我是老盖,本篇文章做的有视频,视频讲述的比较详细,也可以看我发布的视频. 今天和大家讲一下电脑隐藏文件文件夹,和访问这些隐藏的文件文件夹的方式,c盘根目录有一个文件夹,名字是system64. ...

  • R语言Outliers异常值检测方法比较

    原文链接:http://tecdat.cn/?p=8502 识别异常值的方法有很多种,R中有很多不同的方法.  关于异常值方法的文章结合了理论和实践.理论一切都很好,但异常值是异常值,因为它们不遵循理 ...

  • iPhone12手机隐私访问限制设置方法

    如何隐藏?苹果手机的自带软件是不可以卸载的,但我们又用不到放在桌面上看起来很乱,这时我们可以将这些软件隐藏起来下面小编给大家介绍苹果隐私访问限制设置方法,一起来看看吧. 1.进入手机设置,点击屏幕使用 ...

  • win10控制面板没有语言选项的解决方法

    当我们在使用win10系统的时候,如果想要进行语言的设置但是发现找不到语言选项了.对于这种情况小编觉得可以在电脑的相关设置中对语言.时间和区域设置选项进行设置即可.具体步骤就来看看小编是怎么做的吧~希 ...

  • R语言基于树的方法:决策树,随机森林,Bagging,增强树

    原文链接:http://tecdat.cn/?p=9859 概观 本文是有关  基于树的  回归和分类方法的. 树方法简单易懂,但对于解释却非常有用,但就预测准确性而言,它们通常无法与最佳监督学习方法 ...