OpenEdv-开源电子网

 找回密码
 立即注册
正点原子全套STM32/Linux/FPGA开发资料,上千讲STM32视频教程免费下载...
查看: 3011|回复: 9

变量定义前加 _IO什么意思

[复制链接]

11

主题

55

帖子

0

精华

初级会员

Rank: 2

积分
158
金钱
158
注册时间
2016-4-25
在线时间
31 小时
发表于 2016-8-16 17:35:28 | 显示全部楼层 |阅读模式
3金钱
#ifdef __cplusplus
  #define     __I     volatile                /*!< defines 'read only' permissions      */
#else
  #define     __I     volatile const          /*!< defines 'read only' permissions      */
#endif
#define     __O     volatile                  /*!< defines 'write only' permissions     */
#define     __IO    volatile                  /*!< defines 'read / write' permissions   */_IO、_O宏替换后都为volatile为什么一个为允许读写,一个为只写允许?
在百度上看到有人这样写的:
_I :输入口。既然是输入,那么寄存器的值就随时会外部修改,那就不能进行优化,每次都要重新从寄存器中读取。也不能写,即只读,不然就不是输入而是输出了。  
__O :输出口,也不能进行优化,不然你连续两次输出相同值,编译器认为没改变,就忽略了后面那一次输出,假如外部在两次输出中间修改了值,那就影响输出  
__IO:输入输出口,同上。
直接没看懂,请教大神来帮忙,谢谢


最佳答案

查看完整内容[请看2#楼]

防止被优化,__IO是volatile
正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

88

主题

7377

帖子

5

精华

资深版主

Rank: 8Rank: 8

积分
14980
金钱
14980
注册时间
2013-11-13
在线时间
1823 小时
发表于 2016-8-16 17:35:29 | 显示全部楼层
防止被优化,__IO是volatile
开往春天的手扶拖拉机
回复

使用道具 举报

11

主题

55

帖子

0

精华

初级会员

Rank: 2

积分
158
金钱
158
注册时间
2016-4-25
在线时间
31 小时
 楼主| 发表于 2016-8-16 17:47:28 | 显示全部楼层
不要沉啊,自己顶
回复

使用道具 举报

11

主题

55

帖子

0

精华

初级会员

Rank: 2

积分
158
金钱
158
注册时间
2016-4-25
在线时间
31 小时
 楼主| 发表于 2016-8-16 17:47:42 | 显示全部楼层
自己顶!自己顶!
回复

使用道具 举报

11

主题

55

帖子

0

精华

初级会员

Rank: 2

积分
158
金钱
158
注册时间
2016-4-25
在线时间
31 小时
 楼主| 发表于 2016-8-16 17:47:54 | 显示全部楼层
自己顶!
回复

使用道具 举报

30

主题

1170

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
1993
金钱
1993
注册时间
2016-2-16
在线时间
527 小时
发表于 2016-8-16 18:01:39 | 显示全部楼层
去百度都好过这里等啊,百度就有了
回复

使用道具 举报

6

主题

1097

帖子

0

精华

论坛元老

Rank: 8Rank: 8

积分
3571
金钱
3571
注册时间
2014-12-2
在线时间
365 小时
发表于 2016-8-16 19:02:11 | 显示全部楼层
本帖最后由 xkwy 于 2016-8-16 19:15 编辑

举个例子,
我们在PA7上产生100个1us的方波可能会这样写:

//somethings A......
GPIOA->ODR &= ~(1<<7);
for (i = 0; i < 100; i++)
{
    GPIOA->ODR ^= (1<<7);
    delay_us(1);
}
GPIOA->ODR &= ~(1<<7);
//somethings B......

GPIOA->ODR,这个寄存器是被volatile修饰过的,因此程序完美。

但是,如果没有volatile修饰,,
编译器就会想,你这循环前寄存器值是啥样循环后寄存器值还是啥样,
那干脆在循环里把寄存器的赋值拿掉吧(寄存器的读-改-写操作非常费时间),
所以代码直接变成了:

//somethings A......
GPIOA->ODR &= ~(1<<7);
for (i = 0; i < 100; i++)
{
    delay_us(1);
}
//somethings B......


然后又想,循环里啥事不干,就延时,那还等啥,直接跑啊,多聪明,又节省了100us的运行时间,
所以,代码就这样了:

//somethings A......
GPIOA->ODR &= ~(1<<7);
//somethings B......


看到这样的结果你傻眼了吧,虽然如今编译器更加智能话,可能不加volatile,它也能猜出来你在这延时究竟是想干啥,但是,使用volatile一来防止不太聪明的编译器不会出错,二来可以当做注释,给自己提醒也好。

诚然,volatile会强制禁止编译器优化,如果滥用的话也会使原本可以优化的没优化。

一般来说,有可能会被“别的东西”修改的变量,都应该用volatile修饰,
比如单片机寄存器,IO状态变化就会自动改变,
又比如会在中断里使用的外部变量(这很容易被忽视掉)。

坚决不用寄存器,拒绝重复造轮子。
回复

使用道具 举报

11

主题

55

帖子

0

精华

初级会员

Rank: 2

积分
158
金钱
158
注册时间
2016-4-25
在线时间
31 小时
 楼主| 发表于 2016-8-16 19:02:42 | 显示全部楼层
zuozhongkai 发表于 2016-8-16 18:35
防止被优化,__IO是volatile

大哥,这个优化我懂,您能解释一下_IO、_O后面都是替代的volatile为什么解释不一样,还有下面的那三个输入输出口吗,谢谢了
回复

使用道具 举报

11

主题

55

帖子

0

精华

初级会员

Rank: 2

积分
158
金钱
158
注册时间
2016-4-25
在线时间
31 小时
 楼主| 发表于 2016-8-16 19:56:39 | 显示全部楼层
xkwy 发表于 2016-8-16 19:02
举个例子,
我们在PA7上产生100个1us的方波可能会这样写:

可是,大哥,我怎么感觉,这一步的延时必须得跑呢。。。。
//somethings A......
GPIOA->ODR &= ~(1<<7);
for (i = 0; i < 100; i++)
{
    delay_us(1);
}
//somethings B......
回复

使用道具 举报

6

主题

1097

帖子

0

精华

论坛元老

Rank: 8Rank: 8

积分
3571
金钱
3571
注册时间
2014-12-2
在线时间
365 小时
发表于 2016-8-16 20:03:45 | 显示全部楼层
小牛试大刀 发表于 2016-8-16 19:56
可是,大哥,我怎么感觉,这一步的延时必须得跑呢。。。。
//somethings A......
GPIOA->ODR &= ~(1

我只是举个例子,具体看编译器、优化等级以及delay_us()函数内的内容。


事实上,据说早期的编译器经常会把直接用for延时的代码给优化掉,所以那里也会加volatile。

unsigned int volatile i;
for (i = 0; i < 1000; i++);
坚决不用寄存器,拒绝重复造轮子。
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则



关闭

原子哥极力推荐上一条 /2 下一条

正点原子公众号

QQ|手机版|OpenEdv-开源电子网 ( 粤ICP备12000418号-1 )

GMT+8, 2025-5-13 13:22

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

快速回复 返回顶部 返回列表