打印

KEIL C51中如何利用 联合定义位变量进行操作?

[复制链接]
15888|26
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
xyr19|  楼主 | 2011-10-11 10:47 | 只看该作者 |只看大图 回帖奖励 |倒序浏览 |阅读模式
本帖最后由 xyr19 于 2011-10-11 10:49 编辑

union {
struct {
       unsigned Wind: 1; //
       unsigned JCQ: 1;
       unsigned Pump: 1;
       unsigned Intel: 1;
       unsigned Drain: 1;
       unsigned CCW_Flag: 1;////////////////////////////////
       unsigned Swing: 1;
       unsigned : 1;
}Bit;
       unsigned char All;
}QDP_State;
这是我在AVR中用到的程序定义,以方便单独对某一位进行判断和赋值,
但移植到89LPC934上,使用KEIL C51时,编译没有提示错误,但实际运行错误,
原因是编译器识别不了
if(QDP_State.Bit.Pump!=0) 这样的语句,
如果改成if((QDP_State.All&0X04)!=0) 程序运行就正确,请问这是怎么回事,
在C51中如何进行类似的定义?
谢谢

相关帖子

沙发
baiyunfei.k.f| | 2011-10-11 11:28 | 只看该作者
你得定义到bdata区

使用特权

评论回复
板凳
ayb_ice| | 2011-10-11 11:41 | 只看该作者
有图有真相 KEIL完全正确

未命名.JPG (136.45 KB )

未命名.JPG

使用特权

评论回复
地板
airwill| | 2011-10-11 12:28 | 只看该作者
虽然可以实现, 但是, 不是用位指令操作的.

使用特权

评论回复
5
xyr19|  楼主 | 2011-10-11 13:35 | 只看该作者
2# baiyunfei.k.f

我试了一下,加了定义bdata定义,编译器虽然变动了对寄存器的地址分配,但分配的地址是00H,没有定义到20H以后。(记得51是20H开始位可寻址),我使用P89LPC934.

程序运行依然不正确。

请问如何赋予其绝对地址呢,想分配到20H以后的单元。

使用特权

评论回复
6
xyr19|  楼主 | 2011-10-11 13:39 | 只看该作者
有图有真相 KEIL完全正确
ayb_ice 发表于 2011-10-11 11:41


之所以能判断IF正确,那是因为你在其前面同样使用了位赋值,编译器对两者的编译
可能都是错误的,只不过错误的方式机理一致,合在一起的最后结果就对了。如果前面那句不是单独位PUMP赋值,而是整个寄存器赋值,结果就很可能不对。

除非编译器已经把那个寄存器地址赋在了位可寻址的区域里。

使用特权

评论回复
7
xyr19|  楼主 | 2011-10-11 13:40 | 只看该作者
有图有真相 KEIL完全正确
ayb_ice 发表于 2011-10-11 11:41


之所以能判断IF正确,那是因为你在其前面同样使用了位赋值,编译器对两者的编译
可能都是错误的,只不过错误的方式机理一致,合在一起的最后结果就对了。如果前面那句不是单独位PUMP赋值,而是整个寄存器赋值,结果就很可能不对。

除非编译器已经把那个寄存器地址赋在了位可寻址的区域里。

使用特权

评论回复
8
ayb_ice| | 2011-10-11 14:27 | 只看该作者
之所以能判断IF正确,那是因为你在其前面同样使用了位赋值,编译器对两者的编译
可能都是错误的,只不过错误的方式机理一致,合在一起的最后结果就对了。如果前面那句不是单独位PUMP赋值,而是整个寄存器赋值,结 ...
xyr19 发表于 2011-10-11 13:40

真的是无语了
测试结果都已经显示对了

不正确的是你的想法,编译器没有按你的思路去处理,错的是你

使用特权

评论回复
9
ayb_ice| | 2011-10-11 14:34 | 只看该作者
本帖最后由 ayb_ice 于 2011-10-11 14:35 编辑

不懂不要乱下结论
请问你知道KEIL是怎么为这个位域分配空间的吗,分配多大空间,各标志位与字节怎样对应的吗
不知道这些的话就不要乱下结论

位域本身就不具备完全可移植性

使用特权

评论回复
10
sdwangjianlong| | 2011-10-12 15:03 | 只看该作者
学习

使用特权

评论回复
11
andrew.xu| | 2011-10-12 15:50 | 只看该作者
很多没有位域的芯片,也是可以用这种方式的,就是说实际他不一定是直接位操作,而是通过与或等操作实现的
C51不是很清楚,keil下碰到的arm都是可以采用这种定义方式的.

使用特权

评论回复
12
刘前辈| | 2011-10-12 19:38 | 只看该作者
C51 很简单。

使用特权

评论回复
13
ayb_ice| | 2011-10-12 20:09 | 只看该作者
本帖最后由 ayb_ice 于 2011-10-12 20:19 编辑

本质是位怎么分配在字节中,怎么分配在多字节中
类似大小端的问题
比如
unsigned Wind: 1; //
这其实是相当于
unsigned int Wind: 1; //
那么就是两个字节
这个Wind是分配在高字节,还是低字节中呢
在分配在高字节的BIT0还是分配在低字节中的BIT0呢
C没有明确规定,所以意味着不可移植性
KEIL的分配规则可能与程序预想的不一样,虽然编译可以通过,但结果可能不一样

有些编译器对分配方式可以选择,比如FSL的CW IDE就是可选的

KEIL的分配规则请看图

未命名.JPG (118.19 KB )

未命名.JPG

使用特权

评论回复
14
刘前辈| | 2011-10-13 10:18 | 只看该作者
修改一下即可。基本可移植了。

使用特权

评论回复
15
ayb_ice| | 2011-10-13 11:24 | 只看该作者
这样应该更好,节省空间

union {
struct {
       unsigned char  Wind: 1; //
       unsigned char  JCQ: 1;
       unsigned char  Pump: 1;
       unsigned char  Intel: 1;
       unsigned char  Drain: 1;
       unsigned char  CCW_Flag: 1;////////////////////////////////
       unsigned char  Swing: 1;
       unsigned char  : 1;
}Bit;
       unsigned char  All;
}QDP_State

使用特权

评论回复
16
刘前辈| | 2011-10-13 12:27 | 只看该作者
本帖最后由 刘前辈 于 2011-10-13 12:28 编辑

15# 还是和LZ程序完全一样?那问题还是没解决:

All 和 Bit 分配在int 高、低(08,09)不同的字节,怎么联合使用?










、、

使用特权

评论回复
17
刘前辈| | 2011-10-13 12:37 | 只看该作者
仔细看12楼图,int All=4;是分配在09单元的,和Bit一致;
而char All=4;分配在08 单元,和Bit 单元不匹配,所以程序不通。


、、

使用特权

评论回复
18
ayb_ice| | 2011-10-13 13:14 | 只看该作者
15L测试结果

未命名.JPG (36.52 KB )

未命名.JPG

未命名1.JPG (99.55 KB )

未命名1.JPG

使用特权

评论回复
19
DownCloud| | 2011-10-13 13:48 | 只看该作者
LS正解!

使用特权

评论回复
20
DownCloud| | 2011-10-13 13:52 | 只看该作者
18# ayb_ice
奇怪的是,位段声明不是不能出现char int 吗? 编译还可通过。。 搞不懂呀 , 可能其他编译器就不行了吧 。。。

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

46

主题

103

帖子

0

粉丝