|
发表于 2008-6-11 22:33:16
|
显示全部楼层
仿真测试了一下,38楼JohnLee的可用:
#ifndef __MYBIT_H__
#define __MYBIT_H__
#ifdef __cplusplus
extern "C" {
#endif
// AVR 位操作宏
// Compiler: WinAVR
#include <avr/io.h>
/***********************************************************************************/
// Set, Clear and Reverse a bit in a byte
#define SBI__(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit))
#define CBI__(sfr, bit) (_SFR_BYTE(sfr) &= ~_BV(bit))
#define RBI__(sfr, bit) (_SFR_BYTE(sfr) ^= _BV(bit))
/***********************************************************************************
使用方法:
要使用的位域变量或寄存器,只需按下面的规则定义一下就可以了:
#define <BITFIELD_VAL> SFR__(<BYTE_ADDR>,<START_BIT>,<BIT_WIDTH>)
BITFIELD_VAL: 要使用的位域变量名。
BYTE_ADDR: 所需的位域变量所在的字节地址。
START_BIT: 所需的位域变量在该字节的起始位置。
BIT_WIDTH: 位域变量的宽度。
比如:我要定义PORTF3-PORTF6作为一个整体变量使用,变量名为PAGE_REG,我只需定义:
#define PAGE_REG SFR__ (PORTF, 3, 4)
在使用时就直接读写 PAGE_REG 就可以了,决不会影响 PORTF0, PORTF1, PORTF2, PORTF7的值。
再举例:定时器预分频设置:
#define T0_CK SFR__ (TCCR0, 0, 3)
使用时:
T0_CK = 0; // stop
T0_CK = 1; // OSC
T0_CK = 2; // OSC/8
T0_CK = 3; // OSC/64
T0_CK = 4; // OSC/256
等等。
***********************************************************************************/
#define _BITFIELD0_(_S, _W) \
typedef union { \
struct { \
uint8_t used :_W; \
}; \
uint8_t dummy; \
} _bit_##_S##_##_W##_t;
#define _BITFIELD1_(_S, _W) \
typedef union { \
struct { \
uint8_t res :_S; \
uint8_t used :_W; \
}; \
uint8_t dummy; \
} _bit_##_S##_##_W##_t;
_BITFIELD0_ (0, 1);
_BITFIELD0_ (0, 2);
_BITFIELD0_ (0, 3);
_BITFIELD0_ (0, 4);
_BITFIELD0_ (0, 5);
_BITFIELD0_ (0, 6);
_BITFIELD0_ (0, 7);
_BITFIELD0_ (0, 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);
// P: the port; S: start bit; W: bits width
#define SFR__(_P, _S, _W) (* (_bit_##_S##_##_W##_t volatile *) (_SFR_ADDR (_P))).used
/***********************************************************************************/
#ifdef __TEST_MYBIT_H__
#include <avr/io.h>
#include "mybit.h"
#define LED6_ON PORTD |= _BV(6) //位置高
#define LED6_OFF PORTD &= ~_BV(6) //位置低
#define LED6_ALT PORTD ^= _BV(6) //位取反
#define LED6_READ PIND & _BV(6) //位读
#define LED6 SFR__ (PORTD, 6, 1)
#define LED67 SFR__ (PORTD, 6, 2)
int main(void)
{
DDRD = 0xFF;
LED6_ON;
LED6_OFF;
LED6_ALT;
SBI__(PORTD, 6);
CBI__(PORTD, 6);
RBI__(PORTD, 6);
LED6 = 0b0;
LED67 = 0b10;
LED6 = LED6_READ;
return 0;
}
/***********************************************************************************
@00000049: main
---- mybit.h --------------------------------------------------------------------------------------
13: {
+00000049: EF8F SER R24 Set Register
+0000004A: BB81 OUT 0x11,R24 Out to I/O location
16: LED6_ON;
+0000004B: 9A96 SBI 0x12,6 Set bit in I/O register
17: LED6_OFF;
+0000004C: 9896 CBI 0x12,6 Clear bit in I/O register
18: LED6_ALT;
+0000004D: B382 IN R24,0x12 In from I/O location
+0000004E: E490 LDI R25,0x40 Load immediate
+0000004F: 2789 EOR R24,R25 Exclusive OR
+00000050: BB82 OUT 0x12,R24 Out to I/O location
20: SBI__(PORTD, 6);
+00000051: 9A96 SBI 0x12,6 Set bit in I/O register
21: CBI__(PORTD, 6);
+00000052: 9896 CBI 0x12,6 Clear bit in I/O register
22: RBI__(PORTD, 6);
+00000053: B382 IN R24,0x12 In from I/O location
+00000054: 2789 EOR R24,R25 Exclusive OR
+00000055: BB82 OUT 0x12,R24 Out to I/O location
24: LED6 = 0b0;
+00000056: 9896 CBI 0x12,6 Clear bit in I/O register
25: LED67 = 0b10;
+00000057: B382 IN R24,0x12 In from I/O location
+00000058: 738F ANDI R24,0x3F Logical AND with immediate
+00000059: 6880 ORI R24,0x80 Logical OR with immediate
+0000005A: BB82 OUT 0x12,R24 Out to I/O location
26: LED6 = LED6_READ;
+0000005B: B380 IN R24,0x10 In from I/O location
+0000005C: 9896 CBI 0x12,6 Clear bit in I/O register
29: }
***********************************************************************************/
#endif
/***********************************************************************************/
#ifdef __cplusplus
}
#endif
#endif //define __MYBIT_H__
/* ---------------------------------- end of file ------------------------------------- */ |
|