搜索
bottom↓
回复: 48

寄存器操作,位与位或?你OUT啦~

[复制链接]

出0入0汤圆

发表于 2012-2-4 19:33:18 | 显示全部楼层 |阅读模式
呵呵,和大家分享几个我用了很久的宏,
菜鸟表示刚刚才用STM32点了个灯,看着例程代码还是有点辛苦,主要是我比较笨吧,什么位与又什么位或的,
还好在学习51的时候写了一些宏,改了一下,代码读起来才感觉舒服一些,心情也好了一点
心情好的时候我就分享~

第一个:
#define BIT(x)        (0x01L<<(x))
这个宏是后面使用的基础,很好理解,其实这个宏是抄的,我一开始的定义是
#define BIT0 0x01L
#define BIT1 0X02l
...

第二个:
#define BitFromTo(h, l)        ((h > l)? ((BIT(h) - BIT(l) + BIT(h))): (BIT(l) - BIT(h) + BIT(l)) )
打个比方,BitFromTo(3, 0) 的结果就是 0x0f
BitFromTo(7, 4)的结果是0xf0

第三个:
#define AssignBit(type ,flag , which_bit, val)        ((((type)which_bit)&((type)val)) | ((flag)&(~((type)which_bit))))
一开始写这个宏的时候是没有type这个参数的,type是从通用性和安全上考虑的,不过又要多打几个字,不爽,如果C/C++能够支持typeof操作符就好了(自己分析,这里不详细写,在帖子的最后我会提供我代码里的全部注释)
比如说我要把变量u8 a 的 6号位到4号位的值设置为 101,我就可以
a = AssignBit(u8, a, BitFromTo(6, 4), BIT(6) | BIT(4));
这样多直观呀,
本来是要这样写的,不仅不好懂,还容易出错
a &= 0x8f;
a |= 0x50;

第四个
#define SetBit(type, flag, which_bit)                        ((flag) | ((type)which_bit))
这个好理解,如果要把变量a的1号位转置1的话就
a = SetBit(u8, a, BIT(1));

第五个
#define ClearBit(type, flag, which_bit)                        ((flag) & (~((type)which_bit)))
呵呵,这个是用来把一个变量的某些位清零的
比如把变量u8 a = 0xf4;的2号位清零
a = ClearBit(u8, a, BIT(2));
现在 a == 0xf0 了

最后说一下优缺点,
最大的优点就是可读性好,
最大的缺点就是打的字会比较多,每次要加个类型作为参数,不过在我的眼里,可读性更重要

有网友可能会提到效率问题,
这几个宏没有效率问题!如果参数which_bit和val 是常数表达式(我用到的大部分场合都是这样的),编译器是会自动优化的,不信你可以反汇编看看。如果都是变量,编译器不能优化,但是就算是手动写代码效率也是一样的。




最后附上全部代码以及说明:
/*********************************************************************************
*        AssignBit / AssignFlag
*说明:
*        这个宏用来得到一个变量的某个或某几个位被赋值后的值
*参数:
*        type        参数flag的类型
*        flag        要赋值的变量
*        which_bit       
*                        标明flag的哪几个位要被赋值
*        val                表示要赋给flag的那几个位的值
*注意:
*        1. 对于宏,其参数不要用++i;之类的表达式!也不要直接使用调用函数得到的返回值!
*        2. 如果type是寄存器,那么它必须是可读的
*示例:
*        u8 a = 0xf0;
*        AssignBit(u8, a, BIT4 | BIT0, BIT0);
*        执行完后,a == 0xe1;
*备注:
*        1. 效率上, 如果参数(除flag外)都是常量, 编译器会自动优化, 如果参数是变量, 就算手动写代码也是这个样子的
*        2. (which_bit) 括号是为了保证 AssignBit(flag, BIT0 | BIT1, 0)之类的用法不会出错
*********************************************************************************/
#define AssignBit(type ,flag , which_bit, val)                                        \
                                                ((((type)which_bit)&((type)val)) | ((flag)&(~((type)which_bit))))               
#define AssignFlag                        AssignBit
#define AssignB                        AssignBit


/*********************************************************************************
//说明:
//        得到一个变量某几位位被置位后的值
//注意:
//        1. 如果flag是寄存器,必须是可读的
*********************************************************************************/
#define SetBit(type, flag, which_bit)                        ((flag) | ((type)which_bit))
#define SetB        SetBit



//说明:
//        清零位,flag变量中which_bit标明的位被清0
//注意:
//        1. flag必须是可以正常读写的
#define ClearBit(type, flag, which_bit)                        ((flag) & (~((type)which_bit)))
#define ClearB                ClearBit


//说明:
//        检查flag中的某一位是否被置位, 如果被置位, 则宏的值为非0(不一定是1), 如果没有被置位, 则宏的值为0
//注意:
//        1. flag必须是可以读的
#define CheckBit(type, flag, which_bit)                        ( (flag) & ((type)which_bit) )

#define BIT(x)        (0x01L<<(x))

//说明:
//        得到一个指定范围的BIT被置位的值
//        BitFromTo(3, 0)        会得到 0x0f
//备注:
//        1. 这个宏是为提高可读性才写的,对于常数参数是表达式的,编译器会自动优化。
#define BitFromTo(h, l)                                                        ((h > l)? ((BIT(h) - BIT(l) + BIT(h))): (BIT(l) - BIT(h) + BIT(l)) )
#define BitF2                BitFromTo
#define BitFT                BitFromTo

阿莫论坛20周年了!感谢大家的支持与爱护!!

曾经有一段真挚的爱情摆在我的面前,我没有珍惜,现在想起来,还好我没有珍惜……

出0入0汤圆

 楼主| 发表于 2012-2-4 19:39:08 | 显示全部楼层
回复【1楼】renpeng009
-----------------------------------------------------------------------

C语言的宏不是通用的么

都在用啊

我的51代码库里大量的用到这些宏,还没发现问题
http://www.ourdev.cn/bbs/bbs_content.jsp?bbs_sn=5380202&bbs_page_no=1&search_mode=3&search_text=Pony279&bbs_id=9999

出0入0汤圆

发表于 2012-2-4 20:15:52 | 显示全部楼层
mark

出0入0汤圆

发表于 2012-2-4 20:50:07 | 显示全部楼层
学习

出0入0汤圆

发表于 2012-2-4 21:01:06 | 显示全部楼层
噢,与或非out,宏就in,原来如此。

出0入0汤圆

发表于 2012-2-4 21:05:08 | 显示全部楼层
学习~

出0入0汤圆

发表于 2012-2-4 21:14:31 | 显示全部楼层
mark

出0入0汤圆

发表于 2012-2-4 21:32:59 | 显示全部楼层
学习

出0入0汤圆

发表于 2012-2-4 22:39:14 | 显示全部楼层
回复【楼主位】Pony279 霍斯
-----------------------------------------------------------------------

#define mask(i) (uc)(((i)&1l)|\
((((i)>>4)&1l)<<1)|\
((((i)>>8)&1l)<<2)|\
((((i)>>12)&1l)<<3)|\
((((i)>>16)&1l)<<4)|\
((((i)>>20)&1l)<<5)|\
((((i)>>24)&1l)<<6)|\
((((i)>>28)&1l)<<7))
这样是不是更直观呀
a=mask(0x01010000);

出0入0汤圆

发表于 2012-2-4 23:07:34 | 显示全部楼层
#define mask(i) (\
(i>> 0&1)<<0|\
(i>> 4&1)<<1|\
(i>> 8&1)<<2|\
(i>>12&1)<<3|\
(i>>16&1)<<4|\
(i>>20&1)<<5|\
(i>>24&1)<<6|\
(i>>28&1)<<7)
搞整齐点

出0入0汤圆

 楼主| 发表于 2012-2-4 23:14:42 | 显示全部楼层
回复【9楼】hefq 何访贤
-----------------------------------------------------------------------

有创意,确实很直观,
不过把16进制当2进制使用,感觉会有点混乱呀
主要问题是如果是16位的,32位的,写起来可能会比较辛苦了

BIT(x)
用这种宏定义的原因是看datasheet的时候总是有说一个寄存器的几号位有什么功能,几号位又有什么功能
所以就直接用BIT(x),边看datasheet边写代码
结合就SetBit, AssignBit, ClearBit ...

出0入0汤圆

 楼主| 发表于 2012-2-4 23:19:36 | 显示全部楼层
回复【10楼】hefq 何访贤
-----------------------------------------------------------------------
被你一提示,这样写也行 :)

#define mask(i) (\
(i)&1)<<0|\
(i/10)&1 | \
(i/100)&1 | \
...
)

出0入0汤圆

 楼主| 发表于 2012-2-4 23:22:53 | 显示全部楼层
回复【10楼】hefq 何访贤
-----------------------------------------------------------------------


怎么用就看个人喜欢了,自己用着爽就行

这种方式对于16位和32位的,写长了不知道编译器支不支持,

好像再写一个带两个参数的宏来支持16位也行。。。

出0入0汤圆

发表于 2012-2-4 23:33:28 | 显示全部楼层
回复【12楼】Pony279 霍斯
-----------------------------------------------------------------------

这样也行,但如果前导是0就变成8进制了,所以我干脆换成16进制了

出0入0汤圆

 楼主| 发表于 2012-2-4 23:33:57 | 显示全部楼层
回复【10楼】hefq 何访贤
#define mask(i) (\
(i&gt;&gt; 0&amp;1)&lt;&lt;0|\
(i&gt;&gt; 4&amp;1)&lt;&lt;1|\
(i&gt;&gt; 8&amp;1)&lt;&lt;2|\
(i&gt;&gt;12&amp;1)&lt;&lt;3|\
(i&gt;&gt;16&amp;1)&lt;&lt;4|\
(i&gt;&gt;20&amp;1)&lt;&lt;5|\
(i&gt;&gt;24&amp;1)&lt;&lt;6|\
(i&gt;&gt;28&amp;1)&lt;&lt;7)
搞整齐点
-----------------------------------------------------------------------
谢谢你的提示!这样也很不错,以后就拿来用了
#define mask8(i)        \
((i) & 1)  |            \
((i/10) & 1)  |         \
((i/100) & 1)  |        \
((i/1000) & 1)  |       \
((i/10000) & 1)  |      \
((i/100000) & 1)  |     \
((i/1000000) & 1)  |    \
((i/10000000) & 1)  |   \

#define mask16(h, l)    ((mask8(h) <<8) | mask8(l))

出0入0汤圆

 楼主| 发表于 2012-2-4 23:35:34 | 显示全部楼层
回复【14楼】hefq 何访贤
-----------------------------------------------------------------------

原来是这样,看来15楼的方式不行,还是改成16进制的好了

出0入0汤圆

 楼主| 发表于 2012-2-4 23:38:07 | 显示全部楼层
回复【14楼】hefq 何访贤
回复【12楼】pony279 霍斯
-----------------------------------------------------------------------
这样也行,但如果前导是0就变成8进制了,所以我干脆换成16进制了

-----------------------------------------------------------------------

可以利用 宏里面的 ## 在宏里面强制加个0x

出0入0汤圆

发表于 2012-2-4 23:38:18 | 显示全部楼层
mark.

出0入0汤圆

 楼主| 发表于 2012-2-4 23:46:21 | 显示全部楼层
回复【17楼】Pony279 霍斯
-----------------------------------------------------------------------

测试好像编译不通过

出0入0汤圆

发表于 2012-2-4 23:58:31 | 显示全部楼层
union abc{uc a ;struct{uc b0:1,b1:1,b2:1,b3:1,b4:1,b5:1,b6:1,b7:1;}b;};
#define X_len 1//max 2
#define Y_len 1//max 1
#define M_len 0//max 0
#define S_len 2//max 2
#define C_len 0//max 0
#define T_len 6//max 10
//XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
#if X_len>0
union abc data WX[X_len];
#define MX0 WX[0]
#define WX0 MX0.a
#define X0 MX0.b.b0
#define X1 MX0.b.b1
#define X2 MX0.b.b2
#define X3 MX0.b.b3
#define X4 MX0.b.b4
#define X5 MX0.b.b5
#define X6 MX0.b.b6
#define X7 MX0.b.b7
#endif
#if X_len>1
#define MX10 WX[1]

出0入0汤圆

发表于 2012-2-4 23:58:53 | 显示全部楼层
#define FOSC 6//MHz
#define CYCL 10L//MS
#define DTH0 (long)(65536-CYCL*FOSC*1000/12)/256
#define DTL0 (long)(65536-CYCL*FOSC*1000/12)%256+11
#define mask(i) (\
(i>> 0&1)<<0|\
(i>> 4&1)<<1|\
(i>> 8&1)<<2|\
(i>>12&1)<<3|\
(i>>16&1)<<4|\
(i>>20&1)<<5|\
(i>>24&1)<<6|\
(i>>28&1)<<7)
#define mask1(i) (1<<(i))
#define mask0(i) (~(1<<(i)))
#define set(i,j) ((i)|=mask1(j))
#define rst(i,j) ((i)&=mask0(j))
#define get(i,j) ((i)&mask1(j))
#define h8(i) (char)(i)
#define l8(i) (char)((i)>>8)
#define uc unsigned char
#define us unsigned short
#define ul unsigned long
#define sc signed char
#define ss signed short
#define sl signed long

出0入0汤圆

发表于 2012-2-5 00:02:59 | 显示全部楼层
//顺控程序
uc data PRES;
void rstps(){rst(*(uc*)((PRES/8)+WS),PRES%8);}
#define stls(i) PRES=i;if(get(*(uc*)(i/8+WS),i%8))
#define sets(i) do{set(*(uc*)(i/8+WS),i%8);rstps();}while(0)
//void sets(uc i){set(*(uc*)(i/8+WS),i%8);rst(*(uc*)((PRES/8)+WS),PRES%8);}
void stl_zone()
{
        stls(8)
        {
                Y0=0;Y1=0;Y2=1;Y4=0;Y5=1;//马达0,刹车0,松锁1,启动灯0,停止灯1
                D0=D1;
                if(X3||X4)Y3=0;//关报警
                if(XF3&&!X5){D0=0;sets(9);}
        }
        stls(9)
        {
                Y0=1;Y1=0;Y2=0;Y4=1;Y5=0;//马达1,刹车0,松锁0,启动灯1,停止灯0
                if(MP8013)D0++;
                if(X4||D0>=D1){sets(10);}
        }
        stls(10)
        {
                Y0=0;Y1=1;Y4=0;D0=D2;//马达0,刹车1,启动灯0,倒计时赋初值
                if(1){sets(11);}
        }
        stls(11)
        {
                if(MP8013)D0--;
                if(D0<=0){sets(12);}
                else if(XF3){D0=0;sets(9);}
        }
        stls(12)
        {
                Y3=1;//时间到报警
                if(1){sets(8);}
        }
        stls(0)//显示计时
        {
                HB1=HB2=HB3=0;
                if(X0||X3)disp(D1);//如果设置1,显示设定值
                else disp(D0);
//                if(X0)outt(0,30);       
                if(X1||X2){sets(1);}//如果设置1长3秒,跳到S1
        }
        stls(1)//设置
        {
                if(XP1)D1++;
                if(XP2)D1--;
                if(X1||X2)
                {
                        outt(2,3);
                        outt(3,10);
                        if(TG2&&MP8012)
                        {
                                if(TG3){if(X1)D1+=10;else D1-=10;}
                                else{if(X1)D1++;else D1--;}
                        }
                }
                else outt(1,5);
                HB1=HB2=HB3=0;
                if(TG1)HB1=HB2=HB3=1;
                if(D1>999)D1=999;
                if(D1<0)D1=0;
                disp(D1);
                if(!X0&&!X1&&!X2)outt(4,100);
                if(X0)outt(5,30);
                if(TG5){sets(2);}//如果SET键按下3秒,保存
                else if(TG4){sets(0);}//如果10秒内没有键按下跳到S0,不保存               
        }
        stls(2)//保存
        {
                iap(3,0x0000,0);
                iap(2,0x0000,DH1);
                iap(2,0x0001,DL1);
                if(1){sets(0);}
        }
}

出0入0汤圆

发表于 2012-2-5 00:18:31 | 显示全部楼层
mark 寄存器操作,位与位或?你OUT啦~ 宏操作

出0入0汤圆

 楼主| 发表于 2012-2-5 00:24:25 | 显示全部楼层
回复【14楼】hefq 何访贤
回复【12楼】pony279 霍斯
-----------------------------------------------------------------------
这样也行,但如果前导是0就变成8进制了,所以我干脆换成16进制了

-----------------------------------------------------------------------


编译通过测试通过啦~

#define mask(x)        (                                        \
(((( 0x##x )                        ) & 1 )<<0)        |        \
(((( 0x##x )        >>4                ) & 1 )<<1)        |        \
(((( 0x##x )        >>8                ) & 1 )<<2)        |        \
(((( 0x##x )        >>12                ) & 1 )<<3)        |        \
(((( 0x##x )        >>16                ) & 1 )<<4)        |        \
(((( 0x##x )        >>20                ) & 1 )<<5)        |        \
(((( 0x##x )        >>24                ) & 1 )<<6)        |        \
(((( 0x##x )        >>28                ) & 1 )<<7)                \
)

出0入0汤圆

发表于 2012-2-5 00:30:45 | 显示全部楼层
回复【11楼】Pony279  霍斯

bit(x)
用这种宏定义的原因是看datasheet的时候总是有说一个寄存器的几号位有什么功能,几号位又有什么功能
所以就直接用bit(x),边看datasheet边写代码
结合就setbit, assignbit, clearbit ...
-----------------------------------------------------------------------

如果是针对datasheet的寄存器,还是定义位结构体更直观.

出0入0汤圆

 楼主| 发表于 2012-2-5 00:31:15 | 显示全部楼层
回复【24楼】Pony279 霍斯
-----------------------------------------------------------------------

为啥从这里直接复制到编辑器里就会报错。。。

上文件好了。。。

点击此处下载 ourdev_716111XOJ00X.txt(文件大小:3K) (原文件名:macro_function.h.txt)

出0入0汤圆

 楼主| 发表于 2012-2-5 00:31:55 | 显示全部楼层
回复【25楼】xizi
-----------------------------------------------------------------------

不懂,能不能写一个看看

出0入0汤圆

 楼主| 发表于 2012-2-5 00:33:29 | 显示全部楼层
回复【25楼】xizi
-----------------------------------------------------------------------

有些寄存器是不能位寻址的,我不知道怎么实现呀

出0入0汤圆

发表于 2012-2-5 01:52:49 | 显示全部楼层
mark

出0入0汤圆

发表于 2012-2-5 06:18:21 | 显示全部楼层
不错的想法!

出0入0汤圆

发表于 2012-2-5 08:26:11 | 显示全部楼层
寄存器操作,位与

出0入0汤圆

发表于 2012-2-5 08:37:42 | 显示全部楼层
mark

出0入0汤圆

 楼主| 发表于 2012-2-5 10:50:43 | 显示全部楼层
经过9楼到26楼的讨论,
用mask宏来实现在C语言里写二进制是没有问题的,好像宏的名字叫_b()会有一种标准的感觉,哈哈

再说一个东东
在照着datasheet写程序的时候,经常会遇到的情况是说
一个寄存器的某连续的两位有什么功能,某连续的三位又能设置什么
这样搞起来还真麻烦,因为我设置的时候总是难免要进行一些移位呀什么的,那我是不是可以用一个宏,来得到这几个连续位的低地址,(叫一个位段的首地址怎么样)
比如一个8位寄存器r的6到7位是设置xxx的模式的,那么长度就是2,那么我定义
#define xxxmode BIT(6)
再想办法用一个宏来解决模式的设置
r = AssignBitSection( r, xxxmode, 2, mask(10))
名字写复杂了点,当然可以简化的了。。。
理论上这几个参数完全是可以的,至于实现。。。我先去刷牙先~

出0入0汤圆

发表于 2012-2-5 11:26:33 | 显示全部楼层
有创意,确实很直观,
不过把16进制当2进制使用,感觉会有点混乱呀
主要问题是如果是16位的,32位的,写起来可能会比较辛苦了

BIT(x)
用这种宏定义的原因是看datasheet的时候总是有说一个寄存器的几号位有什么功能,几号位又有什么功能
所以就直接用BIT(x),边看datasheet边写代码
结合就SetBit, AssignBit, ClearBit ...

出0入0汤圆

发表于 2012-2-5 11:47:36 | 显示全部楼层
mark  一下下

出0入0汤圆

发表于 2012-2-5 12:24:58 | 显示全部楼层
mark

出0入0汤圆

 楼主| 发表于 2012-2-5 13:10:18 | 显示全部楼层
回复【33楼】Pony279 霍斯
-----------------------------------------------------------------------

这种方式已经测试通过啦

这个是定义
//说明:
//        得到变量的一个位段被赋值后的值,这人宏不会改变变量的值
//参数:
//        type        变量var的类型
//        var                变量
//        LSB                该位段的最低位
//        len                位段的长度,最大值为8
//        val                位段的值
//注意:
//        如果var是一个寄存器,那么它必须是正常可读的
#define AssignBitSection(type, var, LSB, length, value)                AssignBit(type, var, ((1<<(length)) - 1)*LSB, (value)*LSB)
#define AssignBS        AssignBitSection

测试的代码截个图来吧,是STM32的寄存器设置的,单片机都差不多,都是一堆寄存器,看datasheet:
看看返汇编,其实我不太懂汇编,不过看简写,好像是两条从内存到通用寄存器指令,两条运算指令(位与位或,必须的),两条从通用寄存器到内存的指令(存储结果),这六条指令都是必须的
足以证明,宏展开来的代码是很长的,但是编译器是会自动优化的



出0入0汤圆

发表于 2012-2-5 13:21:19 | 显示全部楼层
mark

出0入0汤圆

发表于 2012-2-5 15:26:02 | 显示全部楼层
#define change(i,j,k) (j)=(i)|((j)&~(k))

change(WY0,P2,mask(0x00111111));//把WY0的0-5位刷新到P2口
change(mask(0x10000010),IE,mask(0x10000010));//总控位/ /T2/串口1/T1/INT1/T0/INT0/

出0入0汤圆

 楼主| 发表于 2012-2-5 15:49:08 | 显示全部楼层
回复【39楼】hefq 何访贤
-----------------------------------------------------------------------

嗯,有时是有这种需求,貌似i有些位没被mask呀,好像这个和上面的AssignBit的功能没多大区别

出10入10汤圆

发表于 2012-2-5 17:23:00 | 显示全部楼层
mark 宏

出0入0汤圆

 楼主| 发表于 2012-3-26 18:07:29 | 显示全部楼层
自己顶...
上面的部分宏改成用C++的模板实现的话就可以省去那个type参数,少打几个字,
具体的可以参考这里
http://www.ourdev.cn/thread-5401612-1-1.html
目前比较完善的代码在60楼

出0入0汤圆

发表于 2012-3-26 18:13:05 | 显示全部楼层
不错啊~第一个不是AVR和MSP430经常使用的嘛~呵呵~学习了~

出0入0汤圆

发表于 2012-3-26 18:31:40 | 显示全部楼层
辛苦了,楼主,学习了

出0入0汤圆

发表于 2012-3-26 20:35:16 | 显示全部楼层
学习了  mark!!

出0入0汤圆

 楼主| 发表于 2012-3-26 21:57:33 | 显示全部楼层
nongxiaoming 发表于 2012-3-26 18:13
不错啊~第一个不是AVR和MSP430经常使用的嘛~呵呵~学习了~

呵呵,这两个片子我都没玩过,AVR在我们这只有部分师兄在玩,跟我同年级的好像都没有使用过,


现在在玩STM32
因为现在还没有C++版的固件库,所以我一直都在边学习边积累自己的固件库,
有这些东西确实非常方便,以前问题要考虑移位啊,与啊或啊的。
现在用写好的内联函数+宏+几个模板,基本上就一劳永逸了
封装STM32的寄存器都比较舒服,直接照着参考手册定义寄存器的位,后面的操作都很方便,代码维护起来也比较舒服

其实这些宏STM32官方的库的头文件里面也有相似的,
都是用来方便寄存器操作的,因为参数固定是32位的,所以就不需要type这个参数了。

#define SET_BIT(REG, BIT)     ((REG) |= (BIT))

#define CLEAR_BIT(REG, BIT)   ((REG) &= ~(BIT))

#define READ_BIT(REG, BIT)    ((REG) & (BIT))

#define CLEAR_REG(REG)        ((REG) = (0x0))

#define WRITE_REG(REG, VAL)   ((REG) = (VAL))

#define READ_REG(REG)         ((REG))

#define MODIFY_REG(REG, CLEARMASK, SETMASK)  WRITE_REG((REG), (((READ_REG(REG)) & (~(CLEARMASK))) | (SETMASK)))

人家的库发布的时候我51都不怎么会...如有雷同,,,还得算是我抄他们的。。。

我以前的宏的实现差不多是那样的,后来把赋值的动作分离出来,通用性会强一点。

再后来到了STM32把一部分宏都改成内联函数去实现了,因为宏使用不当容易出问题

出0入0汤圆

发表于 2012-3-26 23:25:14 | 显示全部楼层
Pony279 发表于 2012-3-26 21:57
呵呵,这两个片子我都没玩过,AVR在我们这只有部分师兄在玩,跟我同年级的好像都没有使用过,

呵呵~~我玩过一点~~

出0入0汤圆

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

本版积分规则

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

GMT+8, 2024-8-27 01:12

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

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