AVR

出自 ArchWiki

AVR 是由 Microchip Technology(前身为 AVR)开发的微控制器 (MCU) 系列。AVR 在业余爱好者和教育嵌入式应用中尤其常见,因 Arduino 项目而普及。本页介绍这些 MCU 的 8 位系列。

工具链

安装 avr-gcc 以获取工具链和 GNU 编译器。

编程器

要将编译后的固件刷写到 AVR 芯片,您需要编程器和控制它的软件。最流行的编程器是 USBaspAVRISP mkIIAtmel-ICESTK500。 还有一种使用 LPT 端口的简单 DIY 编程器。 avrdude 完美支持所有这些编程器。

udev 规则

为了能够在没有超级用户权限的情况下运行 avrdude,需要创建一个 Udev 规则来更改 usb 设备的属组(常用的组是 uucp)。

/etc/udev/rules.d/99-avrprogrammer.rules
# Set group for a programmer matching with vendor and product IDs
 SUBSYSTEM=="usb", ATTRS{idVendor}=="your Vendor ID", ATTRS{idProduct}=="your Product ID", GROUP="uucp", MODE="0666"

将斜体部分替换为您的编程器的供应商和产品 ID(这些可以在 usbutils 的 lsusb 命令中找到 usbutils),并将 uucp 组添加到您用户的附加组中。

用法

要为 AVR 芯片编译 C 程序(让我们以运行在 8 MHz 的 ATmega8A 为例),您可以直接使用 avr-gcc。您只需指定目标 MCU(支持的 MCU 的完整列表可以在 avr-gcc(1) § mmcu= 中找到)及其工作频率。

$ avr-gcc -DF_CPU=8000000UL -mmcu=atmega8a -std=gnu99 main.c -o main.elf

avrdude 足够智能,可以处理生成的 ELF 文件,但您可以将其显式转换为 Intel HEX。

$ avr-objcopy -O ihex -j .text -j .data main.elf main.hex

然后运行 avrdude 并指定 flash ROM 作为固件烧录的目标(在本例中使用了 AVRISP mkII,并将时钟速度降低到 125 kHz 以确保安全)。

$ avrdude -p atmega8 -c avrispmkII -B 125kHz -U flash:w:main.hex

就是这样。除此之外,avrdude 还可以处理 EEPROM 内存、熔丝位和锁定位。例如,要将低熔丝位和高熔丝位分别设置为 0x9F 和 0xD1,请使用以下咒语。

$ avrdude -p atmega8 -c avrispmkII -B 125kHz -U lfuse:w:0x9F:m -U hfuse:w:0xD1:m

请记住,ISP 编程速度不应超过 MCU 工作频率的 1/8。许多新芯片都带有 1 MHz 的速度设置,因此使用 125 kHz 作为起始值应该足够好。

技巧与诀窍

优化

由于 AVR 的 flash ROM 尺寸有限且 CPU 相对较弱,您可以考虑一些优化来提高空间利用率和设备的整体性能。常见的做法是启用 GCC 优化级别 -Os 并启用一些额外的功能:-funsigned-char -funsigned-bitfields -fpack-struct -fshort-enums。要排除不必要的库引用,请执行垃圾回收:-ffunction-sections -fdata-sections -Wl,--gc-sections

示例 Makefile

管理大型项目可能很乏味,而 Makefile 工作流程是处理它的最有效方式。这是基于 AVRfreaks 版本的示例 Makefile。

CC = avr-gcc
OBJCOPY = avr-objcopy
SIZE = avr-size
NM = avr-nm
AVRDUDE = avrdude
REMOVE = rm -f

MCU = atmega8a
F_CPU = 8000000

LFUSE = 0x9f
HFUSE = 0xd1

TARGET = firmware
SRC = main.c lcd.c twi.c
OBJ = $(SRC:.c=.o)
LST = $(SRC:.c=.lst)

FORMAT = ihex

OPTLEVEL = s

CDEFS = 

CFLAGS = -DF_CPU=$(F_CPU)UL
CFLAGS += $(CDEFS)
CFLAGS += -O$(OPTLEVEL)
CFLAGS += -mmcu=$(MCU)
CFLAGS += -std=gnu99
CFLAGS += -funsigned-char -funsigned-bitfields -fpack-struct -fshort-enums
CFLAGS += -ffunction-sections -fdata-sections
CFLAGS += -Wall -Wstrict-prototypes
CFLAGS += -Wa,-adhlns=$(<:.c=.lst)

LDFLAGS = -Wl,--gc-sections
LDFLAGS += -Wl,--print-gc-sections

AVRDUDE_MCU = atmega8
AVRDUDE_PROGRAMMER = avrispmkII
AVRDUDE_SPEED = -B 1MHz

AVRDUDE_FLAGS = -p $(AVRDUDE_MCU)
AVRDUDE_FLAGS += -c $(AVRDUDE_PROGRAMMER)
AVRDUDE_FLAGS += $(AVRDUDE_SPEED)

MSG_LINKING = Linking:
MSG_COMPILING = Compiling:
MSG_FLASH = Preparing HEX file:

all: gccversion $(TARGET).elf $(TARGET).hex size

.SECONDARY: $(TARGET).elf
.PRECIOUS: $(OBJ)

%.hex: %.elf
        @echo
        @echo $(MSG_FLASH) $@
        $(OBJCOPY) -O $(FORMAT) -j .text -j .data $< $@

%.elf: $(OBJ)
        @echo
        @echo $(MSG_LINKING) $@
        $(CC) -mmcu=$(MCU) $(LDFLAGS) $^ --output $(@F)

%.o : %.c
        @echo $(MSG_COMPILING) $<
        $(CC) $(CFLAGS) -c $< -o $(@F)

gccversion:
        @$(CC) --version

size: $(TARGET).elf
        @echo
        $(SIZE) -C --mcu=$(AVRDUDE_MCU) $(TARGET).elf

analyze: $(TARGET).elf
        $(NM) -S --size-sort -t decimal $(TARGET).elf

isp: $(TARGET).hex
        $(AVRDUDE) $(AVRDUDE_FLAGS) -U flash:w:$(TARGET).hex

fuses:
        $(AVRDUDE) $(AVRDUDE_FLAGS) -U lfuse:w:$(LFUSE):m -U hfuse:w:$(HFUSE):m

release: fuses isp

clean:
        $(REMOVE) $(TARGET).hex $(TARGET).elf $(OBJ) $(LST) *~

计算控制寄存器值

为了加快项目开发速度,您可以使用 avrcalcAUR 实用程序,该实用程序有助于计算关于定时器、频率等的控制寄存器的不同参数。

参见