搜索
bottom↓
回复: 47

再探讨PORTB|=(1

[复制链接]

出0入0汤圆

发表于 2004-10-23 00:03:27 | 显示全部楼层 |阅读模式
版主,我还是想不通这种定义从何而来,相同的有好几种:

#define Enable_Laser() PORTB|=(1<<PB0);将PORTB的第0位置1

#define Disable_Laser() PORTB&=~(1<<PB0));将PORTB的第0位置0

#define Check_Laser()  (PINB&(1<<PINB0)));检查PORTB的第0位的值



我查了很多资料,都有这样的使用,但到底在哪里才能找到它们的官方定义呢???

出0入0汤圆

发表于 2004-10-23 20:56:30 | 显示全部楼层
这个要看c语言的教程,都是很基础的东西

出0入0汤圆

发表于 2005-11-5 17:50:22 | 显示全部楼层
PORTB|=(1<<PB0) 的解释:

  1.在M8的头文件(iom8.h)中,PB0定义为0 (建议看看使用的单片机相应的头文件)

  2.1<<PB0 意思就是,将1左移PB0(即0)个位,得到0B00000001 (在这里设为A)

  3.PORTB|= A 也可以写为: PORTB = PORTB | A , 即 PORTB = PORTB | 0B00000001

  4.所以,得到的最终效果就是将 PORTB口的0脚设为高电平

#define 为预定义,一般看过C人都懂的

#define A B  意思就是说,用A来代替B,下面程序中只要出现A的地方,都会被编译器解释为B (注意:最后是没有分号;的)

#define Enable_Laser() PORTB|=(1<<PB0) 的意义就是:

  用 Enable_Laser() 这个表达式 来代替 PORTB|=(1<<PB0)

其他语句由此类推就知道了

不知道这样解释能让楼主清楚否? ^_^

出0入0汤圆

发表于 2005-11-14 15:57:40 | 显示全部楼层
不是太清楚的

出0入0汤圆

发表于 2005-11-14 16:32:08 | 显示全部楼层
获益匪浅!

再请问一下:如何将某一位置反?

出0入0汤圆

发表于 2005-11-14 17:13:53 | 显示全部楼层
假如是GCC 的话我会这样写:

#define Enable_Laser() PORTB |= _BV(PB0) //将PORTB的第0位置1

#define Disable_Laser() PORTB &=~ _BV(PB0) //将PORTB的第0位置0

#define Check_Laser() PINB & _BV(PINB0) //检查PORTB的第0位的值



汇编代码:

Enable_Laser(),Disable_Laser();

SBI     0x18,0           Set bit in I/O register

CBI     0x18,0           Clear bit in I/O register

if(Check_Laser)

SBIS    0x16,0           Skip if bit in I/O register set

RJMP    PC-0x000F        Relative jump

     PORTC = 0 ;

OUT     0x15,R1          Out to I/O location

else

     PORTC = 0xFF;

RJMP    PC-XXXXXX        Relative jump

出0入0汤圆

发表于 2005-11-14 21:29:01 | 显示全部楼层
汇编看不懂,大致明白,因为没有专门位操作,用判断语句

看下面对吗?

#define Enable_Laser() PORTB |= (1<<PB0) //将PORTB的第0位置1  

#define Disable_Laser() PORTB &=~ (1<<PB0) //将PORTB的第0位置0  

#define Check_Laser() PINB &(1<<PB0) //检查PORTB的第0位的值  



位置反:

if(check_laser())

{   disable_laser();

}else

{   enable_laser();

}

-----此内容被bg9fu于2005-11-14,21:32:29编辑过



-----此内容被bg9fu于2005-11-14,21:33:57编辑过


-----此内容被bg9fu于2005-11-14,21:34:59编辑过

出0入0汤圆

发表于 2005-11-27 02:49:15 | 显示全部楼层
我被主题勾引进来的。



“PORTB|=(1<< PIND0)”  ??



             “PIND0”  ??



主题与内容不符。

出0入0汤圆

发表于 2005-11-27 02:56:35 | 显示全部楼层
PIND0就是0,虽错可用.编译器是不管这个错误...

出0入0汤圆

发表于 2006-2-28 16:55:35 | 显示全部楼层
PORTB^=(1<<PB0);将PB0取反

出0入0汤圆

发表于 2006-2-28 17:49:21 | 显示全部楼层
#define Enable_Laser() PORTB |= _BV(PB0) //将PORTB的第0位置1  

#define Disable_Laser() PORTB &=~ _BV(PB0) //将PORTB的第0位置0  

#define Check_Laser() PINB & _BV(PINB0) //检查PORTB的第0位的值  



我比较赞同上面的这种操作方式,直接利用GCC里的这个功能,而且代码的效率高。



我以前有这样用过,当然仅是个人习惯,仅供参考:

先这样定义:

#define sbi(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit))

#define cbi(sfr, bit) (_SFR_BYTE(sfr) &= ~_BV(bit))



再定义实际要操作的端口:

#define LED_ON  cbi(PORTD,7) //在程序用LED_ON代替cbi(PORTD,7)

#define LED_OFF sbi(PORTD,7) //在程序用LED_OFF代替sbi(PORTD,7)

出0入0汤圆

发表于 2006-3-6 13:54:59 | 显示全部楼层
#define Check_Laser()  (PINB&(1<<PINB0)));检查PORTB的第0位的值

1<<PINB0的意思是1左移0位,就是00000001,用00000001和PINB与的话,是可以判断出PINB的0位是0,还是1,但是PINB的其他位不都被清成0了吗?

如果是PINB1,PINB2等都用的话,你读了一次,判断了一次后,其他的都被人为的清了啊?

有没有不改变其他位,但是还可以判断某一位值的方法呢?

出0入0汤圆

发表于 2006-6-10 16:16:03 | 显示全部楼层
PINB的其它位不会被清成0,因为1<<PINB0,仅仅是把00000001左移0位(值还是00000001).

PINB&(1<<PINB0)进行的操作是"与"操作,操作的目的是判断PINB的第0位是"1"还是"0".如果是"0","PINB&(1<<PINB0)"的结果是0;如果是"1",结果是1;



设PINB的值为  00001110

            & 00000001

     结果     00000000

PINB的值还是为00001110;



如果是这样PINB&=(1<<PINB0)就会改变PINB的值;

例:PINB&=(1<<PINB0)(等价PINB=PINB&(1<<PINB0))



设PINB的值为  00001110

           &= 00000001

结果 PINB=   00000000



还有PINX是只读的,不能对其写操作;

所以PINB&=(1<<PINB0)应该是非法的;



PINB0的值需要是宏定义中进行先设置;如

#define PINB0 0

#define PINB1 1

-----此内容被charlychan于2006-06-10,16:20:40编辑过


-----此内容被charlychan于2006-06-10,16:34:15编辑过

出0入0汤圆

发表于 2006-9-19 17:07:28 | 显示全部楼层
看了

出0入0汤圆

发表于 2006-9-23 10:48:28 | 显示全部楼层
PORTB&=0xfe;//PB0置0

PORTB|=0x01;//PB0置1

PORTB^=0x01;//PB0取反

这样可以吗?

出0入0汤圆

发表于 2006-9-24 16:08:38 | 显示全部楼层
楼上这样做是完全可以的

出0入0汤圆

发表于 2006-9-28 17:41:00 | 显示全部楼层
请问15楼:既然14楼的写法是可以的,那么为什么教材和前辈们都不用这种简单又明了的写法,而要把它那样呢?

出0入0汤圆

发表于 2006-9-28 20:21:36 | 显示全部楼层
这种语句在AVR 或者ARM中常用,但是你要用在51单片机,或者PIC的编译器里面,就不能正常工作,

PORTB|=(1<< PIND0)可以用PORTB|=0B00000001;//让第0位置1,想让那位置1就在那个位上写1,   这句话可以移植到大多数单片机,包括ARM 都可以

出0入0汤圆

发表于 2007-2-12 19:11:51 | 显示全部楼层
楼主真该恶补一下C语言了

出0入0汤圆

发表于 2007-2-13 11:08:11 | 显示全部楼层
//while((PINC&(1<<PC5))==1);

//while((PINC&(1<<PC5))==0);

loop_until_bit_is_clear(PINC,PC5);

loop_until_bit_is_set(PINC,PC5);



各位看看这两种写法有什么区别?

出0入0汤圆

发表于 2007-2-28 00:14:05 | 显示全部楼层
14楼的方法固然可用并更简单,但这只是在操作这些没有特殊功能意义的IO口位,

当你在操作特殊功能寄存器的位时你还这样做吗?

比如:  TIMSK |=0XFD; 这样容易看懂吗?恐怕过段时间你自己看起来都会觉得吃力.



同样比如:  TIMSK |=_BV(TOIE0);或TIMSK |=(1<<TOIE0);

这样自己或别人一看就知道是定时器/计数器0溢出中断使能.

在操作IO口时也一样,遵守规范是最好的习惯.



TIMSK和TOIE0的宏定义在<avr/ioXXX.h>中.

例如:  #define TIMSK _SFR_IO8(0x39)

       #define TOIE0  1
-----此内容被vlog_user于2007-02-28,00:31:24编辑过

出0入0汤圆

发表于 2007-4-10 20:06:54 | 显示全部楼层

出0入0汤圆

发表于 2007-4-25 08:10:07 | 显示全部楼层
不错·!

出0入0汤圆

发表于 2007-10-23 13:20:47 | 显示全部楼层
感谢楼主提出这样的问题,还有感谢各位大侠对此问题做出的解释,你们的讨论让我受益菲浅

出0入0汤圆

发表于 2007-11-15 21:57:18 | 显示全部楼层
仔细看看C语言的位运算

出0入0汤圆

发表于 2007-11-16 15:53:01 | 显示全部楼层
建议LZ耐心看C语言!

出0入0汤圆

发表于 2007-12-3 18:21:54 | 显示全部楼层
14L的移植不方便

出0入0汤圆

发表于 2007-12-3 18:44:20 | 显示全部楼层
IO口我都用位域读写,方便可移植。

出0入0汤圆

发表于 2009-6-14 08:17:27 | 显示全部楼层
dddddddddd

出0入0汤圆

发表于 2010-5-23 00:42:53 | 显示全部楼层
mark

出0入0汤圆

发表于 2010-5-23 00:50:51 | 显示全部楼层
哈,又见挖坟党。

出0入0汤圆

发表于 2010-5-23 02:10:51 | 显示全部楼层
mark

出0入0汤圆

发表于 2010-5-23 15:45:23 | 显示全部楼层
学习了

出0入0汤圆

发表于 2010-5-24 13:17:28 | 显示全部楼层
学习。。。

出0入0汤圆

发表于 2010-5-26 19:34:13 | 显示全部楼层
如果你用到了32位的MCU(如ARM)时,就能够理解这样写的原因和好处了

出0入0汤圆

发表于 2010-5-26 21:59:15 | 显示全部楼层
mark

出0入0汤圆

发表于 2010-5-27 23:18:34 | 显示全部楼层
MARK
   明天来看!!!

出0入0汤圆

发表于 2010-6-2 12:03:36 | 显示全部楼层
学习了

出0入0汤圆

发表于 2010-6-25 12:26:13 | 显示全部楼层
终于找到了!!!

出0入0汤圆

发表于 2010-6-25 14:00:22 | 显示全部楼层
算啦~~挖吧~~~~

出0入0汤圆

发表于 2010-9-9 22:30:02 | 显示全部楼层
非常感谢以上的高手的赐教。我刚学AVR,好多都不懂。非常感谢。

出0入0汤圆

发表于 2010-9-9 23:51:23 | 显示全部楼层
mark~再挖一下  呵呵

出0入0汤圆

发表于 2010-9-10 01:45:11 | 显示全部楼层
"但是你要用在51单片机,或者PIC的编译器里面,就不能正常工作, "

I used it all the time, actually on all of my code for mcus, including '51, pic, avr, and many varients of arms.

no problem whatsoever, and it is actually the preferred way of coding a mcu.

出0入0汤圆

发表于 2010-9-10 02:09:31 | 显示全部楼层
I use a set of macros to do all of my port related work.


#define IO_SET(port, bits)        port |= (bits)                //set bits on port
#define IO_CLR(port, bits)        port &=~(bits)                //clear bits on port
#define IO_FLP(port, bits)        port ^= (bits)                //flip bits on port

#define IO_GET(port, bits)        (port & (bits))                //return bits on port

#define IO_IN(ddr, bits)        ddr &=~(bits)                //set bits as input
#define IO_OUT(ddr, bits)        ddr |= (bits)                //set bits as output

and they are system independent so they are infinitely portable. all I do when I move my code to a different platform, is to check the corresponding datasheet to make sure that my IO_IN() and IO_OUT routines are correct.

when I need to use the routines, I do the following

#define LED_PORT PORTB
#define LED_DDR  DDRB
#define LED1     (1<<0)
#define LED2     (1<<5)

so I would do

IO_OUT(LED_PORT, LED1 | LED2); IO_SET(LED_PORT, LED1); IO_FLP(LED_PORT, LED2);

to turn on LED1 and flip LED2.

if I want to move pins, all I do is to change the definition and recompile.

infinitely portable and fool proof.

出0入0汤圆

发表于 2010-9-10 02:09:50 | 显示全部楼层
mark

出0入0汤圆

发表于 2010-9-10 08:16:13 | 显示全部楼层
11楼更要恶补C语言了。另外,位域的效率超级超级低。

出0入0汤圆

发表于 2010-9-10 11:28:44 | 显示全部楼层
回复【43楼】millwood0
i use a set of macros to do all of my port related work.
#define io_set(port, bits) port |= (bits) //set bits on port
#define io_clr(port, bits) port &amp;=~(bits) //clear bits on port
#define io_flp(port, bits) port ^= (bits) //flip bits on port
#define io_get(port, bits) (port &amp; (bits)) //return bits on port
#define io_in(ddr, bits) ddr &amp;=~(bits) //set bits as input
#define io_out(......
-----------------------------------------------------------------------

GOOD

出0入0汤圆

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

本版积分规则

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

GMT+8, 2024-5-7 17:13

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

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