B001-Atmega16-PORTA的定义-(ques=1)

来源:互联网 发布:java教务管理系统源码 编辑:程序博客网 时间:2024/04/28 18:34
iom16.h中定义了PORTA如下:
#define PORTA   _SFR_IO8(0x1B)

接着在sfr_defs.h中定义了_SFR_IO8()如下:

#if _SFR_ASM_COMPAT......#define _SFR_IO8(io_addr) ((io_addr) + __SFR_OFFSET)#define _SFR_IO16(io_addr) ((io_addr) + __SFR_OFFSET)......#else  /* !_SFR_ASM_COMPAT */......#define _SFR_IO8(io_addr) _MMIO_BYTE((io_addr) + __SFR_OFFSET)#define _SFR_IO16(io_addr) _MMIO_WORD((io_addr) + __SFR_OFFSET)......#endif /* !_SFR_ASM_COMPAT */
这个定义表示:
如果编译器(_SFR_ASM_COMPAT等于1)可以直接使用汇编、那么像PORTA这样的变量,就是一个地址值。

此时、__SFR_OFFSETIO寄存器基地址,其值等于0x00,所以PORTA展开如下:

#define PORTA   _SFR_IO8(0x1B)              = ((io_addr) + __SFR_OFFSET)              = ((0x1B) + 0x00)              =   0x1B

在汇编中操作PORTA时,就是直接操作PORTA的地址:

否则、如果只能使用C语言,那么操作PORTA这样的变量,就是一个指针操作的过程。
此时、PORTA的定义展开如下:
#define PORTA   _SFR_IO8(0x1B)              = _MMIO_BYTE((io_addr) + __SFR_OFFSET)
_MMIO_BYTE()的定义如下:
#define _MMIO_BYTE(mem_addr) (*(volatile uint8_t *)(mem_addr))
这就是用指针的方式去操作一个内存地址,此时__SFR_OFFSET等于0x20
到此、PORTA的定义进一步展开如下:

#define PORTA   _SFR_IO8(0x1B)              = _MMIO_BYTE((io_addr) + __SFR_OFFSET)              = (*(volatile uint8_t *)((io_addr) + __SFR_OFFSET))              = (*(volatile uint8_t *)((0x1B) + __SFR_OFFSET))              = (*(volatile uint8_t *)(0x3B))

__SFR_OFFSETIO寄存器基地址0x1BPORTA在寄存器文件中的偏移量,加在一起就是PORTA的真实的物理地址(端口地址)。 

所以我们对PORTA赋值的时候,就是将数值写入上面这个地址处的寄存器中。 

参考avr-libc的介绍:http://www.nongnu.org/avr-libc/user-manual/group__avr__sfr__notes.html

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

因此、我们可以将PORTA重命名如下:

    uint8_t *LED = (uint8_t *)(&PORTA);
然后就可以直接对LED进行操作,来点亮LED

    *LED = 0x55;
如果以后更换了LEDIO口,只需要修改LED这个变量的定义即可。
这样对代码的移植是很有好处的。
也可以进一步打包成这样来隐藏指针操作符:
#define LED  (*(volatile uint8_t *)(&PORTA))

最后、如果可以不用#define的定义来隐藏指针操作符就更好了,因为#define定义的部分阅读起来不方便

<还在继续...>

|<----question-001
.
0 0
原创粉丝点击