打印
[AVR单片机]

GCC怎么单独定义IO中的一位

[复制链接]
13510|43
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
472666GAQ|  楼主 | 2010-9-13 11:12 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
来自 2楼
john_lee| | 2010-10-28 21:50 | 只看该作者
给你一个最强的宏定义,不仅可以定义变量(包括I/O)中的单独某一位,而且可以定义多位作为一个整体访问。
先把下面的代码保存为一个头文件:bitwise.h,以后都可以用的。

#ifndef __BITWISE_H
#define __BITWISE_H
#ifdef __cplusplus
extern "C" {
#endif
#define _BITFIELD_(_W)        \
    typedef union {           \
        struct {              \
            uint8_t used :_W; \
        };                    \
        uint8_t dummy;        \
    } _bit_0_ ## _W ## _t
#define _BITFIELD1_(_S, _W)   \
    typedef union {           \
        struct {              \
            uint8_t :_S;      \
            uint8_t used :_W; \
        };                    \
        uint8_t dummy;        \
    } _bit_ ## _S ## _ ## _W ## _t
_BITFIELD_(1);
_BITFIELD_(2);
_BITFIELD_(3);
_BITFIELD_(4);
_BITFIELD_(5);
_BITFIELD_(6);
_BITFIELD_(7);
_BITFIELD_(8);
_BITFIELD1_(1, 1);
_BITFIELD1_(1, 2);
_BITFIELD1_(1, 3);
_BITFIELD1_(1, 4);
_BITFIELD1_(1, 5);
_BITFIELD1_(1, 6);
_BITFIELD1_(1, 7);
_BITFIELD1_(2, 1);
_BITFIELD1_(2, 2);
_BITFIELD1_(2, 3);
_BITFIELD1_(2, 4);
_BITFIELD1_(2, 5);
_BITFIELD1_(2, 6);
_BITFIELD1_(3, 1);
_BITFIELD1_(3, 2);
_BITFIELD1_(3, 3);
_BITFIELD1_(3, 4);
_BITFIELD1_(3, 5);
_BITFIELD1_(4, 1);
_BITFIELD1_(4, 2);
_BITFIELD1_(4, 3);
_BITFIELD1_(4, 4);
_BITFIELD1_(5, 1);
_BITFIELD1_(5, 2);
_BITFIELD1_(5, 3);
_BITFIELD1_(6, 1);
_BITFIELD1_(6, 2);
_BITFIELD1_(7, 1);
#define SFR(_P, _S, _W) (*(_bit_ ## _S ## _ ## _W ## _t volatile*)(_SFR_ADDR(_P))).used
#ifdef __cplusplus
}
#endif
#endif

使用方法:

1、在你的程序中包含bitwise.h
#include "bitwise.h"

2、定义位变量
在你的程序中需要使用SFR宏定义一个位变量(如同keil c51中位变量首先需要使用sbit定义之后才能访问一样),语法如下:
#define BITFIELD_VARIABLE SFR(ADDRESS, START_BIT, FIELD_WIDTH)

BITFIELD_VARIABLE: 位变量名称。
ADDRESS: 包含该位变量的字节所在的地址。
START_BIT: 位变量开始的位置(LSB)。
FIELD_WIDTH: 位变量的宽度。

例如:你需要将PORTB0作为位变量访问,变量名为RELAY,由器件的头文件中可知PORTB0位于PORTB的第0位,那么就可得出ADDRESSPORTBSTART_BIT0,你只使用这一位,那么FIELD_WIDTH就为1,最后定义如下:
#define RELAY SFR(PORTB, 0, 1)

3、访问位变量
如同访问普通变量一样的语法。例如:
RELAY = 1;

使用特权

评论回复
评分
参与人数 2威望 +2 收起 理由
hz77776666 + 1
dong_abc + 1
板凳
宇宙飞船| | 2010-9-14 15:03 | 只看该作者
可以用宏定义呀。51的C个性太强了,单片机C初学者少接触为妙。
例如: C51中的 CODE 指明FLASH 。
但是一般单片机C中通用的做法是用关键字“const ” 指定。编译器会在头文件中作了另一种宏别名替换,以方便MCU编程人员**。

使用特权

评论回复
地板
472666GAQ|  楼主 | 2010-9-15 06:13 | 只看该作者
宏定义呀  那谢谢了  我看ICC中有人就自己定义了类似于51那种操作方式 可以单独使用IO的一位

使用特权

评论回复
5
ytfdhb| | 2010-9-21 15:49 | 只看该作者
#define BIT(N) (1<<N)
用这个就可以进行位操作,例如把PORTC 的第0位置1就可以写成PORTC |= BIT(0);若清零则可以写成PORTC  &= ~BIT(0); 如果取反则可以写成:PORTC ^= BIT(0);其实就是位操作,C语言上都是有的……

使用特权

评论回复
6
472666GAQ|  楼主 | 2010-9-22 06:07 | 只看该作者
我不是想要这样 我的意思是比如说  和CVAVR那样  PORTB.0=1这样形式的

使用特权

评论回复
7
zhangkef0904| | 2010-10-28 10:16 | 只看该作者
用结构体或者共用体加位数的方式呀,比如:
typdef union{
    char    Bit0 : 1;
    char    Bit1 : 1;
    char    Bit2 : 1;
    ...
}IO_PORT, *PIO_PORT;
然后定义一个PIO_PORT类型变量,并让它指向你想操作的IO端口就行了。

使用特权

评论回复
8
宇宙飞船| | 2010-10-28 23:13 | 只看该作者
强力贴,收藏研究。

使用特权

评论回复
9
472666GAQ|  楼主 | 2010-10-29 13:44 | 只看该作者
牛  我研究一下 不知道编译的效率如何   谢谢啦!!!

使用特权

评论回复
10
kgje| | 2010-10-30 16:28 | 只看该作者
强啊。学习了。

使用特权

评论回复
11
itelectron| | 2010-10-30 16:30 | 只看该作者
MARK

使用特权

评论回复
12
batsong| | 2010-10-30 18:02 | 只看该作者
## _W ##
这个井号包起来的可以被替换?
是ansi c的标准?
第一次看到

使用特权

评论回复
13
dong_abc| | 2010-11-1 19:47 | 只看该作者
强帖收藏

使用特权

评论回复
14
symbol6412| | 2010-11-4 14:24 | 只看该作者
mark

使用特权

评论回复
15
sdwys| | 2010-11-5 15:34 | 只看该作者
看一下C里边的位域,用结构定义每一位。

使用特权

评论回复
16
472666GAQ|  楼主 | 2010-11-5 16:17 | 只看该作者
那样的话效率极其低下

使用特权

评论回复
17
darkengine| | 2010-11-17 13:43 | 只看该作者
7楼的代码如果要用gcc编译的话确实得把宏定义里的##param##换成##param

使用特权

评论回复
18
darkengine| | 2010-11-17 13:49 | 只看该作者
刚才搞错了:
用GCC的话是得这样
前面的##_W是为了替换参数,后面的##是为了把后面的_t接上

使用特权

评论回复
19
老鱼探戈| | 2010-11-20 15:16 | 只看该作者
习惯了就好了

使用特权

评论回复
20
智多芯| | 2010-12-1 07:52 | 只看该作者
强帖!

使用特权

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

本版积分规则

102

主题

285

帖子

2

粉丝