首页 > 解决方案 > AVR I/O 宏定义如何工作以允许访问寄存器?

问题描述

我正在查看 ATmega2560 寄存器映射 ( iom2560.h) 的标头,其中包含所有寄存器的定义。例如:

#define PINA    _SFR_IO8(0X00)
//Macro definition:
#define _SFR_IO8(io_addr) ((io_addr) + 0X20)

所以 PINA 是一个 8 位十六进制值,对应 8 位单片机寄存器的地址。当我编写代码时,只需键入以下代码即可更改寄存器内的值:

PINA |= (1 << 3); // Setting the third bit.

这是一个问题:为什么我可以_SFR_IO8(0X00)通过将值分配给 PINA 来写入寄存器值(“由他的地址指向”)?不是指向寄存器的地址吗?编译器是如何工作的?

非常感谢您提前

标签: ccpu-registersatmegaatmelavr-gcc

解决方案


简短的回答 - 隐藏在 Atmel 包含的标头中的是一组宏,它们创建指向寄存器位置的指针。以下是该过程的简要概述:

您的 Makefile 定义要使用的设备,然后将定义传递给编译器。

DEVICE = atmega2560
...
-D__$(DEVICE)__

然后包含 io.h,它会根据您的设备自动包含必要的标头:

// In main source file
#include <io.h>    

// In io.h
#include <avr/sfr_defs.h>
// ...
#elif defined (__AVR_ATmega2560__)
    #  include <avr/iom2560.h>

// In sfr_defs.h
#define _MMIO_BYTE(mem_addr) (*(volatile uint8_t *)(mem_addr))
#define __SFR_OFFSET 0x20
#define _SFR_IO8(io_addr) _MMIO_BYTE((io_addr) + __SFR_OFFSET)

// In iom2560.h
#include <avr/iomxx0_1.h>
// Other device specific definitions

// Om iomxx0_1.h
#define PINA    _SFR_IO8(0X00)
// Other device family shared definitions

所以如果你展开所有这些,你得到的是一个指向寄存器地址的易失性指针。当您在代码中使用 PINA 时,预编译器会将其替换为所有扩展宏:

PINA
_SFR_IO8(0X00)
_MMIO_BYTE((0X00) + __SFR_OFFSET)
(*(volatile uint8_t *)((0X00) + 0x20))

它指定 PINA 是指向 0x20 的易失性 8 位内存地址的指针。然后,每当访问该地址时,内部芯片架构就会将该地址映射到适当的外设寄存器。


推荐阅读