__I、 __O 、__IO是什么意思?

发布者:悠闲之旅最新更新时间:2021-03-30 来源: eefocus关键字:STM32 手机看文章 扫描二维码
随时随地手机看文章

这是ST库里面的宏定义,定义如下:

#define __I volatile const /*!< defines 'read only' permissions */

#define __O volatile /*!< defines 'write only' permissions */

#define __IO volatile /*!< defines 'read / write' permissions */


显然,这三个宏定义都是用来替换成volatile 和 const 的,所以我们先要了解 这两个关键字的作用:


volatile

简单的说,就是不让编译器进行优化,即每次读取或者修改值的时候,都必须重新从内存或者寄存器中读取或者修改。


一般说来,volatile用在如下的几个地方:

1、中断服务程序中修改的供其它程序检测的变量需要加volatile;

2、多任务环境下各任务间共享的标志应该加volatile;

3、存储器映射的硬件寄存器通常也要加volatile说明,因为每次对它的读写都可能由不同意义;


我认为这是区分C程序员和嵌入式系统程序员的最基本的问题。搞嵌入式的家伙们经常同硬件、中断、RTOS等等打交道,所有这些都要求用到volatile变量。不懂得volatile的内容将会带来灾难。假设被面试者正确地回答了这是问题(嗯,怀疑是否会是这样),我将稍微深究一下,看一下这家伙是不是直正懂得volatile完全的重要性。

1)一个参数既可以是const还可以是volatile吗?解释为什么。

2);一个指针可以是volatile吗?解释为什么。

3);下面的函数有什么错误:

intsquare(volatileint*ptr)

{

return*ptr * *ptr;

}


1)是的。一个例子是只读的状态寄存器。它是volatile因为它可能被意想不到地改变。它是const因为程序不应该试图去修改它。

2);是的。尽管这并不很常见。一个例子是当一个中服务子程序修该一个指向一个buffer的指针时。

3)这段代码有点变态。这段代码的目的是用来返指针*ptr指向值的平方,但是,由于*ptr指向一个volatile型参数,编译器将产生类似下面的代码:

intsquare(volatileint*ptr)

{

inta,b;

a = *ptr;

b = *ptr;

returna * b;

}

由于*ptr的值可能被意想不到地该变,因此a和b可能是不同的。结果,这段代码可能返不是你所期望的平方值!正确的代码如下:

longsquare(volatileint*ptr)

{

inta;

a = *ptr;

returna * a;

}




const

只读变量,即变量保存在只读静态存储区。编译时,如何尝试修改只读变量,则编译器提示出错,就能防止误修改。

const与define

两者都可以用来定义常量,但是const定义时,定义了常量的类型,所以更精确一些(其实const定义的是只读变量,而不是常量)。#define只是简单的文本替换,除了可以定义常量外,还可以用来定义一些简单的函数,有点类似内置函数。const和define定义的常量可以放在头文件里面。(小注:可以多次声明,但只能定义一次)


const与指针

intme;

constint* p1=&me; //p1可变,*p1不可变 const 修饰的是 *p1,即*p1不可变

int*constp2=&me; //p2不可变,*p2可变 const 修饰的是 p2,即p2不可变

constint*constp3=&me;//p3不可变,*p3也不可变 前一个const 修饰的是*p3,后一个const 修饰的是p3,两者都不可变



前面介绍了volatile和 const 的用法,不知道大家了解了没?了解了后,下面的讲解就更加容易了:

__I:输入口。既然是输入,那么寄存器的值就随时会外部修改,那就不能进行优化,每次都要重新从寄存器中读取。也不能写,即只读,不然就不是输入而是输出了。

__O:输出口,也不能进行优化,不然你连续两次输出相同值,编译器认为没改变,就忽略了后面那一次输出,假如外部在两次输出中间修改了值,那就影响输出

__IO:输入输出口,同上


为什么加下划线?


原因是:避免命名冲突

一般宏定义都是大写,但因为这里的字母比较少,所以再添加下划线来区分。这样一般都可以避免命名冲突问题,因为很少人这样命名,这样命名的人肯定知道这些是有什么用的。


经常写大工程时,都会发现老是命名冲突,要不是全局变量冲突,要不就是宏定义冲突,所以我们要尽量避免这些问题,不然出问题了都不知道问题在哪里。


关键字:STM32 引用地址:__I、 __O 、__IO是什么意思?

上一篇:STM32 BIT_BAND 位带别名区使用入门
下一篇:STM32的代码,跑在RAM里快?还是跑在Flash里快?

推荐阅读最新更新时间:2024-11-13 12:13

STM32中FLASH_Status的5个状态各表示的含义详解
获取状态:FLASH_Status FLASH_GetStatus(void); 返回值是通过枚举类型定义的。 typedef enum { FLASH_BUSY = 1, //忙 FLASH_ERROR_PG, //编程错误 FLASH_ERROR_WRP, //写保护错误 FLASH_COMPLETE, //操作完成 FLASH_TIMEOUT //操作超时 }FLASH_Status;
[单片机]
STM32复习笔记(六)看门狗
一、为什么要看门狗? 在由单片机构成的微型计算机系统中,由于单片机的工作常常会受到来自外界电磁场的干扰,造成程序的跑飞,而陷入死循环,程序的正常运行被打断,由单片机控制的系统无法继续工作,会造成整个系统的陷入停滞状态,发生不可预料的后果,所以出于对单片机运行状态进行实时监测的考虑,便产生了一种专门用于监测单片机程序运行状态的模块或者芯片,俗称“看门狗”(watchdog) 。 二、看门狗解决的问题是什么? 在启动正常运行的时候,系统不能复位。 在系统跑飞(程序异常执行)的情况,系统复位,程序重新执行。 三、独立看门狗概述: 1、STM32内置两个看门狗,提供了更高的安全性,时间的精确性和使用 的灵活性。两个看门狗
[单片机]
<font color='red'>STM32</font>复习笔记(六)看门狗
英特尔傲持久内存DAOS创造新纪录,跃居I/O IO-500榜首
近日,英特尔®傲腾™持久内存与英特尔开源分布式异步对象存储(DAOS)解决方案相结合,一举创造新的世界纪录,并成功跃居Virtual Institute I/O IO-500榜单首位。仅凭30台配备英特尔®傲腾™持久内存的服务器,英特尔DAOS解决方案便成为全球文件系统性能排名之首,成功超越目前全球最顶尖的超级计算机。 这一结果验证了该解决方案所带来的目前全球最为卓越的分布式存储性能,并同时证明通过英特尔®傲腾™持久内存产品所提供的细粒度的、低延迟内存数据访问,英特尔能够为客户带来磁盘存储般的持久性,并藉此彻底改变存储模式。 阿贡领先计算设施(Argonne Leadership Computing Facility)高性
[嵌入式]
在Mac OS X中搭建STM32开发环境(3)
在上两篇文章中,我们先后编译和安装了ST-Link2和交叉编译工具,在大家确认安装成功以后,可以做一个小Demo来测试一下是否成功。 (三)Demo (1)首先下载我做好的工程文件 http://pan.baidu.com/s/1hq9jU9e (如果分享链接失效,请联系我QQ:291402127),下载完成后,解压到你的用户文件夹(~/)中,目录结构如下: 在这里,我已经给大家编译好了,main.bin就是已经编译好的文件,大家可以直接烧写。 (2)手动编译 cd到stm32f4-discovery文件夹中,运行 make clean 清理编译成功的文件。 然后运行 make 编译过程中应该会出现以下信息: 完成
[单片机]
在Mac OS X中搭建<font color='red'>STM32</font>开发环境(3)
AVR--I/O端口寄存器
ATmega16的4个8位的端口都有各自对应的3个I/O端口寄存器,它们占用了I/O空间的12个地址 下面是PA口寄存器—PORTA、DDRA、PINA各个位的具体定义,以及其是否可以通过指令读写操作和RESET复位后的初始值。其它3个口的寄存器的情况与PA口相同,只是地址不一样。 1 ) 正确使用AVR的I/O口要注意:先正确设置DDRx方向寄存器,再进行I/O口的读写操作。 2) AVR的I/O口复位后的初始状态全部为输入工作方式,内部上拉电阻无效。所以,外部引脚呈现三态高阻输入状态。 3) 因此,用户程序需要首先对要使用的I/O口进行初始化设置,根据实际需要设定使用I/O口的工作方式(输出还是输入),当设定为
[单片机]
AVR--<font color='red'>I</font>/<font color='red'>O</font>端口寄存器
STM32 HSE LSE晶振官方推荐
我打算选择 HSE : HC-49S-8 MHz贴片 LSE : DMX-26S 32768HZ贴片
[单片机]
<font color='red'>STM32</font> HSE LSE晶振官方推荐
基于泓格I-7188的分布式塑胶机监控系统的设计与实施
开发背景以及使用I-7188的理由   随着现代工厂信息自动化进程的加快,企业急需要将管理、决策、市场信息和现场控制信息结合起来,实现ERP、MES、PCS三层信息一体化的解决方案。同时,企业内、外部交换信息的需求也在不断扩大,现代工业企业对生产的管理要求不断提高,这种要求已不局限于通常意义上的对生产现场状态的监视和控制,同时还要求把现场信息和管理信息结合起来,建立一套全集成的、开放的、全厂综合自动化的信息平台,通过对经营决策、管理、计划、调度、过程优化、故障诊断、现场控制等信息的综合处理,形成一个意义更广泛的综合管理系统。在PCS层中,只有具有Web功能的SCADA系统,才能满足企业信息自动化信息平台的要求,它使采集和监控的数据得
[嵌入式]
STM32学习之路(五)——RTC系统时钟
在STM32的CPU有一个RTC引脚,用于连接电池。当系统掉电后,自动由电池给RTC供电,完成时间计数。 对RTC的访问是通过APB1接口进行的。APB1刚被开启的时候,从APB1读来的RTC寄存器的第一个值可能是被破坏了的。因此在程序中,先等待RTC_CRL寄存器中的RSF位被硬件置1,然后才开始读操作。对于写操作,在每一次写操作必须保证前一次写操作完成,即通过查询RTC_CR寄存器中的RTOFF状态位,判断RTC寄存器是否处于更新状态中。只有当RTOFF状态位是1,才可以写RTC寄存器。 RTC模块的寄存器实际上只有5个:控制寄存器RTC_CR,预分频装在寄存器RTC_PRL,预分频余数寄存器RTC
[单片机]
小广播
设计资源 培训 开发板 精华推荐

最新单片机文章
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

换一换 更多 相关热搜器件
随便看看

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved