搜索
bottom↓
回复: 91

终于搞明白了 IAR C 的位操作了,很方便!

[复制链接]

出0入0汤圆

发表于 2007-11-2 22:54:53 | 显示全部楼层 |阅读模式
在IAR的iomacro.h里面有这样一段说明:
#define SFR_B_N(_ADDR, _NAME, _B7, _B6, _B5, _B4, _B3, _B2, _B1, _B0) \
                 SFR_B_BITS_N(_NAME, _ADDR, \
                              Bit0,Bit1,Bit2,Bit3,Bit4,Bit5,Bit6,Bit7, \
                              _B0,_B1,_B2,_B3,_B4,_B5,_B6,_B7)
/*
  SFR_B_N(0x3F,SREG,I,T,H,S,V,N,Z,C) Expands to:
  __io union {
              unsigned char   SREG;          // The sfrb as 1 byte
              struct {                        // The sfrb as 8 bits
                      unsigned char SREG_Bit0:1,
                                    SREG_Bit1:1,
                                    SREG_Bit2:1,
                                    SREG_Bit3:1,
                                    SREG_Bit4:1,
                                    SREG_Bit5:1,
                                    SREG_Bit6:1,
                                    SREG_Bit7:1;
                     };
              struct {                        // The sfrb as 8 bits
                      unsigned char SREG_C:1,
                                    SREG_Z:1,
                                    SREG_N:1,
                                    SREG_V:1,
                                    SREG_S:1,
                                    SREG_H:1,
                                    SREG_T:1,
                                    SREG_I:1;
                     };
             } @ 0x3F;
*/
然后在iom162.h里面引用这个定义:(我用的是M162)
。。。
SFR_B_N(0x07,PORTE,Dummy7,Dummy6,Dummy5,Dummy4,Dummy3,PORTE2,PORTE1,PORTE0)
SFR_B_N(0x06,DDRE,Dummy7,Dummy6,Dummy5,Dummy4,Dummy3,DDE2,DDE1,DDE0)
SFR_B_N(0x05,PINE,Dummy7,Dummy6,Dummy5,Dummy4,Dummy3,PINE2,PINE1,PINE0)
。。。
在程序里面的用法是:
。。。
        if(PINE_PINE2)
        {
            PORTE_PORTE2 = 0;
        }
        else
        {
            PORTE_PORTE2 = 1;
        }
。。。
或者:
。。。

        if(PINE_Bit2)
        {
            PORTE_Bit2 = 0;
        }
        else
        {
            PORTE_Bit2 = 1;
        }
。。。
希望对大家有帮助。

出0入0汤圆

发表于 2007-11-3 11:43:44 | 显示全部楼层
谢谢楼主的分享

出0入0汤圆

发表于 2007-11-3 13:06:04 | 显示全部楼层
谢谢分享

出0入0汤圆

发表于 2007-11-4 12:10:59 | 显示全部楼层
谢谢楼主

出0入0汤圆

发表于 2007-11-7 17:04:46 | 显示全部楼层
太好啦。谢

出0入0汤圆

发表于 2007-11-7 18:06:05 | 显示全部楼层
SETBIT(PORTD, B1)  //PD1=1
CLEARBIT(PORTD, B1) // PD1 = 0

呵呵 在IAR里  我是这样用的   没问题!爽

出0入0汤圆

发表于 2007-11-7 19:23:41 | 显示全部楼层
我看见别人是PORTB_1=1;这样用的,恐怕要爽上天了

出0入0汤圆

发表于 2007-11-7 20:01:54 | 显示全部楼层
感谢分享.如果把位定义在RAM单元中的某一字节又是如何操作呢?

出0入0汤圆

发表于 2007-11-9 14:02:46 | 显示全部楼层
把bit0,bit1....bit7改成0,1。。。7就能写成PORTB_1=1;这样了

出0入0汤圆

发表于 2007-11-9 21:34:14 | 显示全部楼层
楼主不如直接给个例子,这样更好理解一些!

出0入0汤圆

 楼主| 发表于 2007-11-9 22:01:14 | 显示全部楼层
应 “steven 独钓一江秋”的要求,发一个M16驱动1602字符液晶的例子,写的不好,多提意见!
注!IAR AVR 4.20下调试成功。
点击此处下载ourdev_180389.rar(文件大小:36K)

出0入0汤圆

发表于 2007-11-9 22:48:20 | 显示全部楼层
【9楼】 steven 独钓一江秋:
楼主位不是已经给出列子了吗?

比如,
PORTC_Bit0  = 1;    等效:PORTC |= 0x01; 或 PORTC |=  (1 << PC0); 或 PORTC |=  BIT(PC0)
PORTC_Bit1 ^= 1;        :PORTC ^= 0x02; 或 PORTC ^=  (1 << PC1); 或 PORTC ^=  BIT(PC1)
PORTC_Bit2  = 0;        :PORTC &= 0xfb; 或 PORTC &= ~(1 << PC2); 或 PORTC &= ~BIT(PC2)

爽吧?

出0入0汤圆

 楼主| 发表于 2007-11-9 23:03:51 | 显示全部楼层
To: steven 独钓一江秋“如果把位定义在RAM单元中的某一字节又是如何操作呢? ”
著名的“傻孩子”曾经有一段代码演示了RAM中位操作:
例如:先定义如下结构
struct
{
        unsigned char         F_AD:1,
                        IO:1,
                        ON:1,
                        OFF:1,
                        LMP:1,
                        TMP:1,
                        HI:1,
                        LW:1;
} testbit;

然后对testbit操作使用下面方法:
testbit.F_AD = 0;
...
testbit.HI = 1;
就可以了,虽不如C51里的bit类型爽,但是也不太复杂。

出0入0汤圆

发表于 2007-11-10 08:42:59 | 显示全部楼层
谢楼上的各位,但我好像还没有找到答案,注意到定义的时候用了关键字SFR_B_N,所以楼主和11楼的方法只适合特别功能寄存器,并非一般的用户寄存器.12楼的方法是用结构体的方法,虽然不复杂,但是不能字节操作,还不如用联合体.知情的请再赐教!

出0入0汤圆

发表于 2007-11-10 10:35:28 | 显示全部楼层
回楼上两位,AVR对于用户布尔变量是非常不划算的,某些编译器定义到寄存器里面另当别论.请参考相关书籍.

一般就是用byte代替它了.

我觉得,特殊寄存器(其实主要只PORT端口)用位的方式很直观.位变量没意义,直接用char就可以了

出0入0汤圆

发表于 2007-11-10 13:17:32 | 显示全部楼层
如果这样使用,失去的是空间和时间。但是时间和空间都不要求时,这样用看起来很直观。分时而异

出0入0汤圆

 楼主| 发表于 2007-11-10 14:45:25 | 显示全部楼层
个人感觉在一般的51单片机里,256Byte的RAM,用起来还是比较紧张的,所以C51的bit类型是一种非常节约的数据类型,优化起来效果很好。反观AVR系列,典型的M16,1K的RAM,16K的Flash,用起来底气足了很多。PORT位操作的实现,方便之余,其实也是C51的习惯使然。C51的bit类型多半是用作标志,在AVR M16的条件下char作标志也不浪费。

出0入0汤圆

发表于 2007-11-10 15:02:56 | 显示全部楼层
【15楼】 tanyang :
IAR用位操作端口不会浪费时间和空间

出0入0汤圆

发表于 2007-11-10 15:20:51 | 显示全部楼层
比较赞同16楼的说法,在RAM足够用的情况下,AVR的对SRAM位操作和字节操作所占的空间和时间应该是一样的.

出0入0汤圆

发表于 2008-3-11 15:09:09 | 显示全部楼层
学习了!

出0入0汤圆

发表于 2009-3-27 10:21:17 | 显示全部楼层
没有picc的操作方便

出0入0汤圆

发表于 2009-3-30 15:06:44 | 显示全部楼层
哈哈支持一个

出0入0汤圆

发表于 2009-7-26 11:50:26 | 显示全部楼层
感谢分享

出0入0汤圆

发表于 2009-7-26 12:32:24 | 显示全部楼层
我想问一下,采用这个方式的伪造做
struct
{
        unsigned char         F_AD:1,
                        IO:1,
                        ON:1,
                        OFF:1,
                        LMP:1,
                        TMP:1,
                        HI:1,
                        LW:1;
} testbit;
产生的这八个位,能赋值给一个 unsigned char 吗 ?有没有试过?

出0入0汤圆

发表于 2009-7-26 14:11:24 | 显示全部楼层
mark

出0入0汤圆

发表于 2009-7-26 14:39:22 | 显示全部楼层
学习一下

出0入0汤圆

发表于 2009-7-26 19:05:56 | 显示全部楼层
总感觉这样写不利于代码的移置, 换个编译器就玩不转了, 到时候还得挨个改.

出0入0汤圆

发表于 2009-7-26 19:06:39 | 显示全部楼层
【20楼】 jishanlaike 阿泰
积分:210
派别:
等级:------
来自:MyMCU_Kingdom南京
没有picc的操作方便  
__________________________
我被PICC搞死了(PIC16)。后换ATMEGA16 编GCC爽_死了。

我一般是这样用的 SBI(PORTn,m),CLI(PORTn,m),
更勤快一点再定义一下
#define PORTnm_H SBI(PORTn,m)
#define PORTnm_L CLI(PORTn,m)
或者
#define MOTORA_ON SBI(PORTn,m)
#define MOTORA_OFF CLI(PORTn,m)

不见比得51的sfr 有多多少麻烦。就是多一些宏定义。

出0入0汤圆

发表于 2009-7-26 19:30:30 | 显示全部楼层
MARK

出0入0汤圆

发表于 2009-7-27 06:55:03 | 显示全部楼层
mark

出0入0汤圆

发表于 2009-7-27 09:18:58 | 显示全部楼层
其实只要在开头定义#define PORTA.0  ...... 那什么都可以的

出0入0汤圆

发表于 2009-8-18 01:00:02 | 显示全部楼层

出0入0汤圆

发表于 2010-2-1 23:18:39 | 显示全部楼层
留下脚印

出0入0汤圆

发表于 2010-2-2 09:02:09 | 显示全部楼层
Mark

出0入0汤圆

发表于 2010-2-26 21:39:53 | 显示全部楼层
mark

出0入0汤圆

发表于 2010-2-27 13:20:44 | 显示全部楼层
mark

出0入0汤圆

发表于 2010-2-27 13:46:17 | 显示全部楼层
ao

出0入0汤圆

发表于 2010-2-28 13:48:49 | 显示全部楼层
学习了

出0入0汤圆

发表于 2010-2-28 15:09:12 | 显示全部楼层
没用上IAR

出0入0汤圆

发表于 2010-2-28 15:47:40 | 显示全部楼层
Mark,刚开始用IAR不久,学习了。

出0入0汤圆

发表于 2010-3-12 13:08:51 | 显示全部楼层
mark

出0入0汤圆

发表于 2010-3-27 23:56:20 | 显示全部楼层
呵呵

出0入0汤圆

发表于 2010-5-8 12:56:16 | 显示全部楼层
mark tou

出0入0汤圆

发表于 2010-5-10 11:10:50 | 显示全部楼层
还是不明白  怎么用if(PINB_PB0)  或者if(PINB.0)操作

出0入0汤圆

发表于 2010-10-25 21:08:17 | 显示全部楼层
我在IAR for STM8里这样写,结果编译时提示这样的错误:Error[Pe065]: expected a ";"
union {
        unsigned char Flg=0x2C;
        struct {
                  unsigned char flg0:1;
                  unsigned char flg1:1;
                unsigned char flg2:1;
                unsigned char flg3:1;       
               
                unsigned char flg4:1;       
                unsigned char flg5:1;
                unsigned char flg6:1;
                  unsigned char flg7:1;       
        };
};
改为
union {
        unsigned char Flg;
        struct {
                  unsigned char flg0:1;
                  unsigned char flg1:1;
                unsigned char flg2:1;
                unsigned char flg3:1;       
               
                unsigned char flg4:1;       
                unsigned char flg5:1;
                unsigned char flg6:1;
                  unsigned char flg7:1;       
        };
};
Flg=0x2C;

则出现如下错误:
Error[Pe077]: this declaration has no storage class or type specifier

Error[Pe101]: "Flg" has already been declared in the current scope (at line 43)

出0入0汤圆

发表于 2010-10-25 21:29:29 | 显示全部楼层
如果仅
union {
unsigned char Flg;
struct {
   unsigned char flg0:1;
   unsigned char flg1:1;
unsigned char flg2:1;
unsigned char flg3:1;

unsigned char flg4:1;
unsigned char flg5:1;
unsigned char flg6:1;
                  unsigned char flg7:1;
};
};
则编译通过

出0入0汤圆

发表于 2010-10-26 15:55:04 | 显示全部楼层
新手来学习

出0入0汤圆

发表于 2010-11-13 12:06:44 | 显示全部楼层
很不错的方法。

出0入0汤圆

发表于 2010-11-13 12:09:43 | 显示全部楼层
mark

出0入0汤圆

发表于 2010-11-19 10:16:13 | 显示全部楼层
mark

出0入0汤圆

发表于 2010-11-22 21:43:50 | 显示全部楼层
直接按标准的移位写多好,移植性也强

出0入0汤圆

发表于 2010-12-29 21:50:43 | 显示全部楼层
Do not understang!

出0入0汤圆

发表于 2010-12-30 00:28:48 | 显示全部楼层
学习

出0入0汤圆

发表于 2011-2-9 16:38:48 | 显示全部楼层
不用定义什么,直接使用。如PORTD4控制一灯,写作:#define     DBG_LED_CONVERT     (PORTD^=PORTD4) 即可,我一直这样用的,没觉得有多爽呀...

出0入0汤圆

发表于 2011-2-10 14:17:10 | 显示全部楼层
mark

出0入0汤圆

发表于 2011-2-10 19:38:40 | 显示全部楼层
感谢分享

出0入0汤圆

发表于 2011-4-27 10:07:28 | 显示全部楼层
mark

出0入0汤圆

发表于 2011-4-27 22:36:37 | 显示全部楼层
MARK

出0入0汤圆

发表于 2011-4-27 23:01:56 | 显示全部楼层
"SETBIT(PORTD, B1)  //PD1=1"

it would have been better if the macro is written using masks.

#define SETBIT(port, pins) port |= (pins)

this allows you to operate on multiple bits/pins:

SETBIT(PORTA, (1<<0) | ((1<<2)); for example sets bit 0 and 2.

and this is entirely portable.

出0入0汤圆

发表于 2011-6-26 08:10:22 | 显示全部楼层
mark too

出0入0汤圆

发表于 2011-6-26 12:20:24 | 显示全部楼层
mark

出0入0汤圆

发表于 2011-6-26 16:47:15 | 显示全部楼层
只要#include <ioavr.h>就可以了,在这个头文件里会根据型号调用相关型号的IO库。
我用的是IAR FOR ATMEL AVR 4.20。
可以直接 PORTB_Bit0=1;一直这样用的。

出0入0汤圆

发表于 2011-6-26 18:17:17 | 显示全部楼层
马克思主义

出0入0汤圆

发表于 2011-7-20 14:59:51 | 显示全部楼层
拿来主义

出0入0汤圆

发表于 2011-8-8 23:18:28 | 显示全部楼层
好东西。我一直用的是 ^=  |=

出0入0汤圆

发表于 2011-8-9 10:07:37 | 显示全部楼层
mark

出0入0汤圆

发表于 2011-8-9 13:05:27 | 显示全部楼层
谢谢楼主

出0入0汤圆

发表于 2011-8-9 21:43:20 | 显示全部楼层
mark

出0入0汤圆

发表于 2011-8-10 10:01:52 | 显示全部楼层
挺方便的

出0入0汤圆

发表于 2011-8-10 11:40:07 | 显示全部楼层
哈哈,看回复

出0入0汤圆

发表于 2011-8-10 22:14:04 | 显示全部楼层
haoa

出0入0汤圆

发表于 2011-8-10 23:34:36 | 显示全部楼层
不错

出0入0汤圆

发表于 2011-8-17 18:39:59 | 显示全部楼层
mark

出0入0汤圆

发表于 2011-8-19 15:41:02 | 显示全部楼层
个人感觉大家还是适应不用位操作吧

出0入0汤圆

发表于 2011-10-16 22:25:42 | 显示全部楼层
位操作是必须用的,例如把 ASCII 码转换成 8字LED显示。
不同的 CPU 或 不同的编译 都有不同的位操作方法,用起来发头晕。
C 语言的标准就是不规范位的操作,无语........................

出0入0汤圆

发表于 2011-10-20 00:39:21 | 显示全部楼层
union
{
    unsigned char HEAT_STATUS;
        struct {
                unsigned char  Flag_Out_0  :1;
                unsigned char  Flag_Out_1  :1;
                unsigned char  Flag_Out_2        :1;
                unsigned char  Flag_Out_3  :1;
                unsigned char  Flag_Out_4  :1;
                unsigned char  Flag_Out_5  :1;
                unsigned char  Flag_Out_6  :1;
                unsigned char  Flag_Out_7  :1;

    };
};

以上定义
Flag_Out_0 = 0;
if(Flag_Out_0){xxx;}
都是可以的
HEAT_STATUS = 0;
HEAT_STATUS = 0xFF;
一样都可以,这个方法仅限IAR里用,可以完全兼容51的程序。我一直这样用的,IAR For SAM8 430 AVR都是可以的。

出0入0汤圆

发表于 2012-1-5 16:17:44 | 显示全部楼层
回复【77楼】Heavin 小文子
-----------------------------------------------------------------------
mark

出0入0汤圆

发表于 2012-3-30 12:41:07 | 显示全部楼层
学习了!!!

出0入0汤圆

发表于 2013-3-4 21:35:29 | 显示全部楼层
keep post for referance

出0入0汤圆

发表于 2013-3-6 20:12:04 来自手机 | 显示全部楼层
和楼主的操作方法一样。一直这样用的

出0入0汤圆

发表于 2013-3-6 21:40:41 来自手机 | 显示全部楼层
不错,学习学习

出0入0汤圆

发表于 2013-3-7 12:47:02 | 显示全部楼层
呵呵,很在就知道了,不错哦

出255入0汤圆

发表于 2013-3-9 10:20:33 | 显示全部楼层
明白了,谢谢你的提示

出0入0汤圆

发表于 2013-3-9 15:52:56 | 显示全部楼层
很好的  不错 学习了

出0入0汤圆

发表于 2013-9-6 17:17:50 | 显示全部楼层
谢谢了分享!

出0入0汤圆

发表于 2014-4-18 11:40:05 | 显示全部楼层
有时遇到问题总能在论坛中找到,感谢论坛!

谢谢LZ分享,受教了。。。

出0入0汤圆

发表于 2014-4-21 12:12:59 | 显示全部楼层
学习,不错,学习一下

出0入0汤圆

发表于 2014-8-6 20:37:36 | 显示全部楼层
mark,谢谢分享!

出0入0汤圆

发表于 2014-8-8 21:22:02 来自手机 | 显示全部楼层
mark  感谢分享

出0入0汤圆

发表于 2015-6-1 11:01:57 | 显示全部楼层
谢谢了,正要这个呢
回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

手机版|Archiver|amobbs.com 阿莫电子技术论坛 ( 粤ICP备2022115958号, 版权所有:东莞阿莫电子贸易商行 创办于2004年 (公安交互式论坛备案:44190002001997 ) )

GMT+8, 2024-5-9 05:41

© Since 2004 www.amobbs.com, 原www.ourdev.cn, 原www.ouravr.com

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