[AVR单片机] GCC怎么单独定义IO中的一位

[复制链接]
15345|43
 楼主| 472666GAQ 发表于 2010-9-13 11:12 | 显示全部楼层 |阅读模式
GCC, IO, AVR, vr, rio
在GCC中怎么定义后单独使用avrIO中的一位 类似于51  sbit  要求效率高点谢谢
john_lee 发表于 2010-10-28 21:50 | 显示全部楼层
给你一个最强的宏定义,不仅可以定义变量(包括I/O)中的单独某一位,而且可以定义多位作为一个整体访问。
先把下面的代码保存为一个头文件:bitwise.h,以后都可以用的。

  1. #ifndef __BITWISE_H
  2. #define __BITWISE_H
  3. #ifdef __cplusplus
  4. extern "C" {
  5. #endif
  6. #define _BITFIELD_(_W)        \
  7.     typedef union {           \
  8.         struct {              \
  9.             uint8_t used :_W; \
  10.         };                    \
  11.         uint8_t dummy;        \
  12.     } _bit_0_ ## _W ## _t
  13. #define _BITFIELD1_(_S, _W)   \
  14.     typedef union {           \
  15.         struct {              \
  16.             uint8_t :_S;      \
  17.             uint8_t used :_W; \
  18.         };                    \
  19.         uint8_t dummy;        \
  20.     } _bit_ ## _S ## _ ## _W ## _t
  21. _BITFIELD_(1);
  22. _BITFIELD_(2);
  23. _BITFIELD_(3);
  24. _BITFIELD_(4);
  25. _BITFIELD_(5);
  26. _BITFIELD_(6);
  27. _BITFIELD_(7);
  28. _BITFIELD_(8);
  29. _BITFIELD1_(1, 1);
  30. _BITFIELD1_(1, 2);
  31. _BITFIELD1_(1, 3);
  32. _BITFIELD1_(1, 4);
  33. _BITFIELD1_(1, 5);
  34. _BITFIELD1_(1, 6);
  35. _BITFIELD1_(1, 7);
  36. _BITFIELD1_(2, 1);
  37. _BITFIELD1_(2, 2);
  38. _BITFIELD1_(2, 3);
  39. _BITFIELD1_(2, 4);
  40. _BITFIELD1_(2, 5);
  41. _BITFIELD1_(2, 6);
  42. _BITFIELD1_(3, 1);
  43. _BITFIELD1_(3, 2);
  44. _BITFIELD1_(3, 3);
  45. _BITFIELD1_(3, 4);
  46. _BITFIELD1_(3, 5);
  47. _BITFIELD1_(4, 1);
  48. _BITFIELD1_(4, 2);
  49. _BITFIELD1_(4, 3);
  50. _BITFIELD1_(4, 4);
  51. _BITFIELD1_(5, 1);
  52. _BITFIELD1_(5, 2);
  53. _BITFIELD1_(5, 3);
  54. _BITFIELD1_(6, 1);
  55. _BITFIELD1_(6, 2);
  56. _BITFIELD1_(7, 1);
  57. #define SFR(_P, _S, _W) (*(_bit_ ## _S ## _ ## _W ## _t volatile*)(_SFR_ADDR(_P))).used
  58. #ifdef __cplusplus
  59. }
  60. #endif
  61. #endif

使用方法:

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

2、定义位变量
在你的程序中需要使用SFR宏定义一个位变量(如同keil c51中位变量首先需要使用sbit定义之后才能访问一样),语法如下:
  1. #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,最后定义如下:
  1. #define RELAY SFR(PORTB, 0, 1)

3、访问位变量
如同访问普通变量一样的语法。例如:
  1. 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的一位
ytfdhb 发表于 2010-9-21 15:49 | 显示全部楼层
#define BIT(N) (1<<N)
用这个就可以进行位操作,例如把PORTC 的第0位置1就可以写成PORTC |= BIT(0);若清零则可以写成PORTC  &= ~BIT(0); 如果取反则可以写成:PORTC ^= BIT(0);其实就是位操作,C语言上都是有的……
 楼主| 472666GAQ 发表于 2010-9-22 06:07 | 显示全部楼层
我不是想要这样 我的意思是比如说  和CVAVR那样  PORTB.0=1这样形式的
zhangkef0904 发表于 2010-10-28 10:16 | 显示全部楼层
用结构体或者共用体加位数的方式呀,比如:
typdef union{
    char    Bit0 : 1;
    char    Bit1 : 1;
    char    Bit2 : 1;
    ...
}IO_PORT, *PIO_PORT;
然后定义一个PIO_PORT类型变量,并让它指向你想操作的IO端口就行了。
宇宙飞船 发表于 2010-10-28 23:13 | 显示全部楼层
强力贴,收藏研究。
 楼主| 472666GAQ 发表于 2010-10-29 13:44 | 显示全部楼层
牛  我研究一下 不知道编译的效率如何   谢谢啦!!!
kgje 发表于 2010-10-30 16:28 | 显示全部楼层
强啊。学习了。
itelectron 发表于 2010-10-30 16:30 | 显示全部楼层
batsong 发表于 2010-10-30 18:02 | 显示全部楼层
## _W ##
这个井号包起来的可以被替换?
是ansi c的标准?
第一次看到
dong_abc 发表于 2010-11-1 19:47 | 显示全部楼层
强帖收藏
symbol6412 发表于 2010-11-4 14:24 | 显示全部楼层
sdwys 发表于 2010-11-5 15:34 | 显示全部楼层
看一下C里边的位域,用结构定义每一位。
 楼主| 472666GAQ 发表于 2010-11-5 16:17 | 显示全部楼层
那样的话效率极其低下
darkengine 发表于 2010-11-17 13:43 | 显示全部楼层
7楼的代码如果要用gcc编译的话确实得把宏定义里的##param##换成##param
darkengine 发表于 2010-11-17 13:49 | 显示全部楼层
刚才搞错了:
用GCC的话是得这样
前面的##_W是为了替换参数,后面的##是为了把后面的_t接上
老鱼探戈 发表于 2010-11-20 15:16 | 显示全部楼层
习惯了就好了
智多芯 发表于 2010-12-1 07:52 | 显示全部楼层
强帖!
您需要登录后才可以回帖 登录 | 注册

本版积分规则

102

主题

285

帖子

2

粉丝
快速回复 在线客服 返回列表 返回顶部