AVR单片机指南

参考:

Atmel AVR

Atmel AVR系列是一种基于改进的哈佛结构、8位~32位精简指令集(Reduced Instruction Set Computing,RISC)的微控制器,由Atmel公司于1996年研发.AVR系列是首次采用闪存(Flash Memory)作为数据存储介质的单芯片微控制器之一,同时代的其它微控制器多采用一次写入可编程ROM、EPROM或是EEPROM.目前AVR处理器发展了六个系列,分别是:tinyAVR,ATtiny系列;megaAVR,ATmega系列;XMEGA,ATxmega系列;Application-specific AVR,面向特殊应用的AVR系列,增加LCD控制器、USB控制器、PWM等特性;FPSLIC,FPGA上的AVR核;AVR32,32位AVR系列,包含SIMD和DSP以及音视频处理特性,与ARM架构形成争.

ATmega32U4(Arduino pro micro)

sparkfun/Arduino_Boards

atmega-asm

MiniCore

Arduino-Based (ATmega32U4) Mouse and Keyboard Controller

The Lost Art of Structure Packing

连接ICSP烧写bootloader.

12345678910111213141516171819202122232425262728 (2232HIO) FT232H ATmega32U4 pin13 ADBUS0 <------> SCK pin15 pin14 ADBUS1 <------> MOSI pin16 pin15 ADBUS2 <------> MISO pin14 pin16 ADBUS3 <------> Reset RST GND <------> GND +3.3V <------> +3.3V~$ avrdude -C /etc/avrdude.conf -c UM232H -P /dev/ttyUSB0 -b 19200 -p atmega32u4 -U lfuse:r:-:iavrdude: AVR device initialized and ready to accept instructionsReading | ################################################## | 100% 0.01savrdude: Device signature = 0x1e9587 (probably m32u4)avrdude: reading lfuse memory:Reading | ################################################## | 100% 0.00savrdude: writing output file "":01000000FF00:00000001FFavrdude: safemode: Fuses OK (E:CB, H:D8, L:FF)avrdude done. Thank you.

some of valid programmers for FTDI

1234562232HIO = FT2232H based generic programmer4232h = FT4232H based generic programmerft232r = FT232R Synchronous BitBangft245r = FT245R Synchronous BitBangttl232r = FTDI TTL232R-5V with ICSP adapterUM232H = FT232H based module from FTDI and Glyn.com.au

添加sparkfun/Arduino_Boards,让Arduino IDE支持更多的种类的板子,添加URL后,通过Tools -> Boards Manager 安装SparkFun AVR Boards.烧写SparkFun bootloader.

1234567891011121314151617181920212223242526272829303132~$ avrdude -C /etc/avrdude.conf -c UM232H -P /dev/ttyUSB0 -b 19200 -p m32u4 -U flash:w:.arduino15/packages/SparkFun/hardware/avr/1.1.13/bootloaders/caterina/Caterina-promicro16.hexavrdude: AVR device initialized and ready to accept instructionsReading | ################################################## | 100% 0.01savrdude: Device signature = 0x1e9587 (probably m32u4)avrdude: NOTE: "flash" memory has been specified, an erase cycle will be performed To disable this feature, specify the -D option.avrdude: erasing chipavrdude: reading input file ".arduino15/packages/SparkFun/hardware/avr/1.1.13/bootloaders/caterina/Caterina-promicro16.hex"avrdude: input file .arduino15/packages/SparkFun/hardware/avr/1.1.13/bootloaders/caterina/Caterina-promicro16.hex auto detected as Intel Hexavrdude: writing flash (32762 bytes):Writing | ################################################## | 100% 0.00savrdude: 32762 bytes of flash writtenavrdude: verifying flash memory against .arduino15/packages/SparkFun/hardware/avr/1.1.13/bootloaders/caterina/Caterina-promicro16.hex:avrdude: load data flash data from input file .arduino15/packages/SparkFun/hardware/avr/1.1.13/bootloaders/caterina/Caterina-promicro16.hex:avrdude: input file .arduino15/packages/SparkFun/hardware/avr/1.1.13/bootloaders/caterina/Caterina-promicro16.hex auto detected as Intel Hexavrdude: input file .arduino15/packages/SparkFun/hardware/avr/1.1.13/bootloaders/caterina/Caterina-promicro16.hex contains 32762 bytesavrdude: reading on-chip flash data:Reading | ################################################## | 100% 0.00savrdude: verifying ...avrdude: 32762 bytes of flash verifiedavrdude: safemode: Fuses OK (E:CB, H:D8, L:FF)avrdude done. Thank you.

ATmega328p (Arduino Pro mini with CH340)

烧写好bootloader就可以使用USB在Arduino IDE上进行开发.

选择Tools -> Board -> Arduino Pro or Pro Mini, 烧写器AVRISP mkii.

UART通信的要点

不像其他的通讯协议,UART沒有clock信号可供参考,所以双方需要事先知道彼此的baud rate,才知道双方是以多快的速度传送数据,必须条件:

两个硬件设备必须要共地(GND)

Baud rate必须相同。

Baud rate为9600,每个bit的时间应该是1/9600秒,对于CPU来说是几个cycle呢?如果CPU频率是9600Hz,这样刚好就是1 cycle传输一个bit.

ATtiny85(CJMCU)

Links:

ATTiny10IDE

[Tutorial : How to program the CJMCU ATTiny85 (LilyTiny / LilyPad)](https://diyprojects.io/ tutorial-program-cjmcu-attiny85-lilytiny-lilypad/)

Digispark DIY: the Smallest USB Arduino

Tiny AVR Programmer Hookup Guide

Arduino / AVR #

Little Wire

ATtiny85 I2C protocol tutorial

ATtiny85 Snake Game Handheld

MiniCore

Bootloader

ATtiny85 USB Boot Loader: Details

micronucleus是一个可以支持跨平台的USB上传烧写的bootloader,体积在2kb以内.

1234567891011 FT232H ATTiny85 pin13 ADBUS0 <------> SCK PB2 pin14 ADBUS1 <------> MOSI PB0 pin15 ADBUS2 <------> MISO PB1 pin16 ADBUS3 <------> Reset PB5 GND <------> GND +5V <------> +5V~ micronucleus/firmware/releases$ avrdude -C /etc/avrdude.conf -c UM232H -P /dev/ttyUSB1 -b 19200 -p attiny85 -U flash:w:t85_default.hex -U lfuse:w:0xe2:m -U hfuse:w:0xdd:m -U efuse:w:0xfe:m

接入USB会发现如下的设备:

1234~$ lsusb[...]Bus 004 Device 007: ID 16d0:0753 MCS Digistump DigiSpark[...]

复制micronucleus/commandline/49-micronucleus.rules到系统的/etc/udev/rules.d/目录内.

系统控制与复位

这里要讲到关于熔丝位(fuse)的技术.具体的技术细节需要查看Datasheet的20. Memory Programming.可以根据文档去配置编程使能相应的字节的位.也可以通过这个https://www.engbedded.com/fusecalc/配置得出三个字节去配置熔丝位.lfuse表示低位,hfuse表示高位,efuse表示扩展位.

在配置编程熔丝位时有几个问题要注意,比如:把SPIEN,JTAGEN的位设定为未编程状态,这将使芯片失去了JTAG与SPI接口的功能,不能重新烧写,从而以致单片机锁死,出现这种情况时就需要高压(12v)并行编程方式才能将单片机的功能恢复.另一个问题是要启动地址的错误,如果没有开启单片机的BOOTLOADER功能,就不要设置BOOTRST的编程位为0(已编程),否则单片机在上电时不是从Flash的0x0000开始运行的,而是转到BOOT区执行,从而导致单片机无法正确运行.

使用Arduino IDE支持(ATTinyCore)

ATTinyCore是让最新的Arduino IDE支持ATTiny系列的单片机,安装流程当然也就是按照https://github.com/SpenceKonde/ATTinyCore/blob/master/Installation.md操作,在Arduino IDE -> File->Preferences加入http://drazzy.com/package_drazzy.com_index.json,并且更新安装ATTinyCore的库.之后在``Arduino IDE -> Tools -> Board -> ATTinyCore`里面可以选择目标的单片机.

有可能ATTinyCore自带的micronucleus版本太低与Attiny85内烧写版本的不匹配,就会出现下面的错误,具体的版本可以查看~/.arduino15/packages/ATTinyCore/tools/micronucleus/2.0a4/.关于ATTinyCore所支持的硬件与固件配置可以查看~/.arduino15/packages/ATTinyCore/hardware/avr/1.4.1/bootloaders.

123Warning: device with unknown new version of Micronucleus detected.This tool doesn\'t know how to upload to this new device. Updates may be available.Device reports version as: 2.4

关于上面的警告提示,需要更新micronucleus版本.12~$ cd micronucleus/commandline && make~$ cp micronucleus ~/.arduino15/packages/ATTinyCore/tools/micronucleus/2.0a4/

使用Arduino上传第一个程序(blink).

选择主板:Tools -> Board -> ATTinyCore -> ATtiny85(Micronucleus/DigiSpark)

烧写方式:Tools -> Burn Bootloader Method: "Upgrade (via USB)"

基本上选择了正确的主板,其它参数默认就可以了,测试图如下:

测式程序是:File -> Examples -> Built-in examples -> 01.Basics -> Blink. 只是重定义了LED_BUILTIN的IO口,如下:

123456789101112131415#define LED_BUILTIN 1// the setup function runs once when you press reset or power the boardvoid setup() { // initialize digital pin LED_BUILTIN as an output. pinMode(LED_BUILTIN, OUTPUT);}// the loop function runs over and over again forevervoid loop() { digitalWrite(LED_BUILTIN, HIGH); // turn the LED on (HIGH is the voltage level) delay(1000); // wait for a second digitalWrite(LED_BUILTIN, LOW); // turn the LED off by making the voltage LOW delay(1000); // wait for a second}

烧写提示如下:

1234567891011121314151617181920212223242526Plug in device now... (will timeout in 60 seconds)> Please plug in the device ...> Press CTRL+C to terminate the program.> Device is found!connecting: 16% completeconnecting: 22% completeconnecting: 28% completeconnecting: 33% complete> Device has firmware version 2.4> Device signature: 0x1e930b> Available space for user applications: 6522 bytes> Suggested sleep time between sending pages: 7ms> Whole page count: 102 page size: 64> Erase function sleep duration: 714msparsing: 50% complete> Erasing the memory ...erasing: 55% completeerasing: 60% completeerasing: 65% complete> Starting to upload ...writing: 70% completewriting: 75% completewriting: 80% complete> Starting the user app ...running: 100% complete>> Micronucleus done. Thank you!

新增烧写器(UM232H为例)

Platform specification

123456789101112131415161718~$ tree -L 2 ~/.arduino15/packages//home/michael/.arduino15/packages/├── arduino│ ├── hardware│ └── tools├── atmel-avr-xminis│ └── hardware├── ATTinyCore│ ├── hardware│ └── tools├── esp32│ ├── hardware│ └── tools├── SparkFun│ └── hardware└── STM32 ├── hardware └── tools

在~/.arduino15/packages/内的各种包内结构如下,基本每一个包(package: i.e: ardunion,ATTinyCore )下面的hardware\\

而在包下面的hardware\tools\内包内,包含这个包所支持的工具链,如:编译器,烧写器,还有一些特定的工具等.这里以avrdude为例,在Arduino IDE烧写AVR的板子时候,它会调用包内的avrdude与配置文件,如:

12.arduino15/packages/arduino/tools/avrdude/6.3.0-arduino17/bin/avrdude \-c .arduino15/packages/arduino/tools/avrdude/6.3.0-arduino17/etc/avrdude.conf

下面是让ATTinyCore包内的Attiny85通过使用UM232H烧写器,在Arduino IDE内烧写,无需其它的bootloader支持.

首先在~/.arduino15/packages/ATTinyCore/hardware/avr/1.4.1/programmers.txt内,加入以下内容:

12345678um232h.name=UM232H as ISPum232h.communication=serialum232h.protocol=UM232Hum232h.speed=19200um232h.program.protocol=UM232Hum232h.program.speed=19200um232h.program.tool=avrdudeum232h.program.extra_params=-P{serial.port} -b{program.speed}

重启Arduino IDE会发现,选择ATTinyCore包类的板子,在烧写器一栏,会看到UM232H as ISP. 如果在某个包类没有在定义programmers.txt,它就会使用目标板子在arduino体系内所对应~/.arduino15/packages/arduino/hardware///programmers.txt

如:

1~$ .arduino15/packages/arduino/tools/avrdude/6.3.0-arduino17/bin/avrdude -C .arduino15/packages/ATTinyCore/hardware/avr/1.4.1/avrdude.conf

如果这里的.arduino15/packages/ATTinyCore/hardware/avr/1.4.1/avrdude.conf文件内没有支持UM232H配置,需要在avrdude.conf加入下面内容:

123456789101112131415161718192021222324252627282930# UM232H module from FTDI and Glyn.com.au.# See helix.air.net.au for detailed usage information.# J1: Connect pin 2 and 3 for USB power.# J2: Connect pin 2 and 3 for USB power.# J2: Pin 7 is SCK# : Pin 8 is MOSI# : Pin 9 is MISO# : Pin 11 is RST# : Pin 6 is ground# Use the -b flag to set the SPI clock rate eg -b 3750000 is the fastest I could get# a 16MHz Atmega1280 to program reliably. The 232H is conveniently 5V tolerant.programmer id = "UM232H"; desc = "FT232H based module from FTDI and Glyn.com.au"; type = "avrftdi"; usbvid = 0x0403;# Note: This PID is reserved for generic 232H devices and# should be programmed into the EEPROM usbpid = 0x6014; usbdev = "A"; usbvendor = ""; usbproduct = ""; usbsn = "";#ISP-signals sck = 0; mosi = 1; miso = 2; reset = 3;;

如在运行烧写时出现在下面错误,也就是在一些avrdude.conf内没有支持UM232H的原因之一.

1avrdude: Error: no libftdi or libusb support. Install libftdi1/libusb-1.0 or libftdi/libusb and run configure/make again.

这里比较简单解决办法是,使用系统的/usr/bin/avrdude来替换.arduino15/packages/arduino/tools/avrdude/6.3.0-arduino17/bin/avrdude

为什么Arduino IDE为会调用包内的工具(avrdude),因为它的路径定义如下:

12345~$ grep "avrdude.path" ~/.arduino15/packages/arduino/hardware/avr/1.8.3/platform.txttools.avrdude.path={runtime.tools.avrdude.path}~$ grep "avrdude.path" ~/.arduino15/packages/ATTinyCore/hardware/avr/1.4.1/platform.txttools.avrdude.path={runtime.tools.avrdude.path}

最后,新增其它的种类的烧写器也是类似,如:FT2232HL等.这种方式,就是可以使用Arduino IDE生态内的软件库,所带来快速开发与测试硬件的优势.也可使用Makefile的方式使用avrdude来烧写.

添加2232HL

打开/etc/avrdude.conf文件发现,里面默认定义了FT2232H,FT4232H的配置如下:

12345678910111213141516171819202122232425262728293031323334353637~$ cat /etc/avrdude.conf[...]programmer id = "2232HIO"; desc = "FT2232H based generic programmer"; type = "avrftdi"; connection_type = usb; usbvid = 0x0403; # Note: This PID is reserved for generic H devices and # should be programmed into the EEPROM # usbpid = 0x8A48; usbpid = 0x6010; usbdev = "A"; usbvendor = ""; usbproduct = ""; usbsn = ""; #ISP-signals reset = 3; sck = 0; mosi = 1; miso = 2; buff = ~4; #LED SIGNALs errled = ~ 11; rdyled = ~ 14; pgmled = ~ 13; vfyled = ~ 12; ; #The FT4232H can be treated as FT2232H, but it has a different USB #device ID of 0x6011. programmer parent "avrftdi" id = "4232h"; desc = "FT4232H based generic programmer"; usbpid = 0x6011; ;[...]

如上所示,在系统级的avrdude已经支持FT2232H,这里只需要硬件库里programmers.txt添加一个对应到FT2232H的项就可以了。但是一般在硬件库里,还有一份avrdude.conf,按顺序会先是检查硬件库里的相关配置。这里还是以ATTinyCore的硬件库为例:

123456789101112~$ tail -n 10 ~/.arduino15/packages/ATTinyCore/hardware/avr/1.5.2/programmers.txtft2232h.name=2232HIO as ISPft2232h.communication=serialft2232h.protocol=avrftdift2232h.speed=19200ft2232h.program.protocol=avrftdift2232h.program.speed=19200ft2232h.program.tool=avrdudeft2232h.program.extra_params=-P{serial.port} -b{program.speed}

ft2232h连接attiny85

12345678 FT2232H ATTiny85ADBUS0 <------> SCK PB2ADBUS1 <------> MOSI PB0ADBUS2 <------> MISO PB1ADBUS3 <------> Reset PB5 GND <------> GND +5V <------> +5V (VIN)

AVRDude烧写

前面是在ATTiny85Flash里烧写一个bootloader开启SELFPRGEN Self-Programming Enable与SPIEN Enable Serial Program and Data Downloading的功能,优点就是让它能通过USB(D-: PB3/AD3,D+: PB4/AD2)可以烧写程序,可以简单与Arduino IDE集成使用,不需要外接烧写器.缺点就是要消耗2kb的存储空间,但是Attiny85就只有8kb的Flash空间.

下面就是通过使用UM232H像烧写bootloader的方法去开发编程,可以完全使用8kb的空间.下面是一个简单blink示例.

123456789101112131415161718192021222324252627282930313233343536~ blink$ cat main.c// main.c//// A simple blinky program for ATtiny85// Connect red LED at pin 2 (PB1)//// electronut.in#include #include int main (void){ // set PB1 to be output DDRB = 0b00000010; while (1) { // flash# 1: // set PB1 high PORTB = 0b00000010; _delay_ms(20); // set PB1 low PORTB = 0b00000000; _delay_ms(20); // flash# 2: // set PB1 high PORTB = 0b00000010; _delay_ms(200); // set PB1 low PORTB = 0b00000000; _delay_ms(200); } return 1;}

Makefile

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960# Makefile for programming the ATtiny85# modified the one generated by CrossPackDEVICE = attiny85CLOCK = 8000000PROGRAMMER = -c UM232HOBJECTS = main.o# for ATTiny85# see http://www.engbedded.com/fusecalc/FUSES = -U lfuse:w:0x62:m -U hfuse:w:0xdf:m -U efuse:w:0xff:m# Tune the lines below only if you know what you are doing:AVRDUDE = avrdude $(PROGRAMMER) -p $(DEVICE)COMPILE = avr-gcc -Wall -Os -DF_CPU=$(CLOCK) -mmcu=$(DEVICE)# symbolic targets:all: main.hex.c.o: $(COMPILE) -c $< -o $@.S.o: $(COMPILE) -x assembler-with-cpp -c $< -o $@.c.s: $(COMPILE) -S $< -o $@flash: all $(AVRDUDE) -U flash:w:main.hex:ifuse: $(AVRDUDE) $(FUSES)# Xcode uses the Makefile targets "", "clean" and "install"install: flash fuse# if you use a bootloader, change the command below appropriately:load: all bootloadHID main.hexclean: rm -f main.hex main.elf $(OBJECTS)# file targets:main.elf: $(OBJECTS) $(COMPILE) -o main.elf $(OBJECTS)main.hex: main.elf rm -f main.hex avr-objcopy -j .text -j .data -O ihex main.elf main.hex avr-size --format=avr --mcu=$(DEVICE) main.elf# If you have an EEPROM section, you must also create a hex file for the# EEPROM and add it to the "flash" target.# Targets for code debugging and analysis:disasm: main.elf avr-objdump -d main.elfcpp: $(COMPILE) -E main.c

接线按照上面方法,因为这里是没有用使用bootloader,直接在blink目录下运行make flash就通过使用avrdude烧写到flash中.

也可以单独使用下面命令烧写.

1~$ avrdude -C /etc/avrdude.conf -c UM232H -P /dev/ttyUSB1 -b 19200 -p attiny85 -U flash:w:main.hex:i

高压编程恢复熔丝位(fuse)锁死

Links

Alex079.vscode-avr-helper

High Voltage programming/Unbricking for Attiny

ATTiny85_Fuse_Resetter

All you need to know about AVR fuses

恢复熔丝位(fuse)还是有一点麻烦,按照博文High Voltage programming/Unbricking for Attiny指导,需要有一个Arduino设备,或者说至少要一个有6个IO口的单片机.还需要6个1k的电阻,一个(npn)的三极管,一个12V的电压源.如图:

读取熔丝位(fuse)

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768~$ avrdude -C /etc/avrdude.conf -c UM232H -P /dev/ttyUSB1 -b 19200 -p attiny85 -U lfuse:r:-:i -vavrdude: Version 6.3-20171130 Copyright (c) 2000-2005 Brian Dean, http://www.bdmicro.com/ Copyright (c) 2007-2014 Joerg Wunsch System wide configuration file is "/etc/avrdude.conf" User configuration file is "/home/michael/.avrduderc" User configuration file does not exist or is not a regular file, skipping Using Port : /dev/ttyUSB1 Using Programmer : UM232H Overriding Baud Rate : 19200 AVR Part : ATtiny85 Chip Erase delay : 4500 us PAGEL : P00 BS2 : P00 RESET disposition : possible i/o RETRY pulse : SCK serial program mode : yes parallel program mode : yes Timeout : 200 StabDelay : 100 CmdexeDelay : 25 SyncLoops : 32 ByteDelay : 0 PollIndex : 3 PollValue : 0x53 Memory Detail : Block Poll Page Polled Memory Type Mode Delay Size Indx Paged Size Size #Pages MinW MaxW ReadBack ----------- ---- ----- ----- ---- ------ ------ ---- ------ ----- ----- --------- eeprom 65 6 4 0 no 512 4 0 4000 4500 0xff 0xff flash 65 6 32 0 yes 8192 64 128 4500 4500 0xff 0xff signature 0 0 0 0 no 3 0 0 0 0 0x00 0x00 lock 0 0 0 0 no 1 0 0 9000 9000 0x00 0x00 lfuse 0 0 0 0 no 1 0 0 9000 9000 0x00 0x00 hfuse 0 0 0 0 no 1 0 0 9000 9000 0x00 0x00 efuse 0 0 0 0 no 1 0 0 9000 9000 0x00 0x00 calibration 0 0 0 0 no 1 0 0 0 0 0x00 0x00 Programmer Type : avrftdi Description : FT232H based module from FTDI and Glyn.com.auavrdude: AVR device initialized and ready to accept instructionsReading | ################################################## | 100% 0.01savrdude: Device signature = 0x1e930b (probably t85)avrdude: safemode: lfuse reads as 62avrdude: safemode: hfuse reads as DFavrdude: safemode: efuse reads as FEavrdude: reading lfuse memory:Reading | ################################################## | 100% 0.00savrdude: writing output file "":01000000629D:00000001FFavrdude: safemode: lfuse reads as 62avrdude: safemode: hfuse reads as DFavrdude: safemode: efuse reads as FEavrdude: safemode: Fuses OK (E:FE, H:DF, L:62)avrdude done. Thank you.

内存爆掉的问题,定义了一个1024的数组.

1234567891011avr-size --format=avr --mcu=attiny85 main.elfAVR Memory Usage----------------Device: attiny85Program: 2454 bytes (30.0% Full)(.text + .data + .bootloader)Data: 1043 bytes (203.7% Full)(.data + .bss + .noinit)

ATTiny85/Atmega328p时钟计数器相关

Links:

AVR Timer Interrupts Calculator

Introduction to AVR Timers

ATtiny85 timer tutorial: generating time delay using Interrupts

Attiny85 timer programming using Timer1

ATtiny85 20MHz Internal Clock

NEC IR Remote Control Interface with 8051

8位定时器(timer0)

先确认手上的ATtiny85的时钟频是否在运行在8MHz,可以通过读取它的fuse位来判定,这里使用的是-U lfuse:w:0xe2:m -U hfuse:w:0xdf:m -U efuse:w:0xff:m.这里测试用的fuse配置如图

ATTiny85默认时钟频率是8MHz,表示它可以每秒进行8000000次周期开关(高电平,低电平),每一个周期的时间段(time period)是1/8000000s也就是0.000000125s,也就是125ns,而一个16位的定时器(0-65535),在每个时钟周期加一,从0到上65536上溢只需要8.192ms,8位的定时器只需要0.032ms就上溢了。如果我们需要更长时间的定时间隔,那么就需要预分频器对时钟进行分频处理,根据芯片手册14.9.2 TCCR0B - Timer/Counter Control Register B描述,通过设置TCCRB0B寄存器的Bit2:0位,可以进如下预分频

CS02

CS01

CS00

Description

0

0

0

No clock source (Timer/Counter stopped)

0

0

1

clk I/O /(no prescaling)

0

1

0

clk I/O /8 (from prescaler)

0

1

1

clk I/O /64 (from prescaler)

1

0

0

clk I/O /256 (from prescaler)

1

0

1

clk I/O /1024 (from prescaler)

1

1

0

External clock source on T0 pin. Clock on falling edge.

1

1

1

External clock source on T0 pin. Clock on rising edge.

下面这个程序使用8位定时器来延时1秒,每秒翻转一次状态的blink示例。ATtiny85默认是8MHz,每个周期是1/8MHz = 0.125us = 125ns,按1024预频后得到7812.5Hz。也就是说,定时器每隔7812.5Hz加1,换算成时间是1/7812.5 = 0.000128s,8位定时器只能计数到0.000128s * 255 = 0.032639999999999995。

设定T/C0的工作状态为CTC模式,开启T/C0输出比较匹配中断使能位,使用OCR0A比较寄存器保存数值做比较。这里设置OCR0A=250,当TCNT0的值达到250后就会产生比较中断(250 < 255>).中断32次后,也是就约等于1秒钟,并且对PB1的状态进行翻转。

12345678910111213141516171819202122232425262728293031323334353637~$ cat timer0.c#include #include int intr_count = 0;void setupTimer0() { cli(); // Clear registers TCCR0A = 0; TCCR0B = 0; // 7812.5 Hz (8000000/((0+1)*1024)) OCR0A = 250; // 0.000128s * 250 = 32ms // CTC 比较匹配时清零定时器模式 TCCR0A |= (1 << WGM01); // Prescaler 1024 TCCR0B |= (1 << CS02) | (1 << CS00); // Output Compare Match A Interrupt Enable TIMSK |= (1 << OCIE0A); sei(); //enabling global interrupt, or SREG |= 0x80}ISR(TIMER0_COMPA_vect) { if(intr_count == 31) { intr_count = 0; PORTB^=(1<

ATtiny85的timer1也是一个8bit定时器,但是支持最大14-bit(MAX=16384)的预分频,下面是一个测试。设置比较寄存器的值为248,中断两次逻辑采样得到1.006s的方波。1/488.28125 = 0.002048s,也等于0.000000125s * 16384 = 0.002048s.

12345678910111213141516171819202122232425262728293031323334353637~$ cat timer1.cint intr_count = 0;void setupTimer1() { noInterrupts(); // Clear registers TCNT1 = 0; TCCR1 = 0; // 488.28125 Hz (8000000/((0+1)*16384)) OCR1C = 248; // interrupt COMPA OCR1A = OCR1C; // CTC TCCR1 |= (1 << CTC1); // Prescaler 16384 TCCR1 |= (1 << CS13) | (1 << CS12) | (1 << CS11) | (1 << CS10); // Output Compare Match A Interrupt Enable TIMSK |= (1 << OCIE1A); sei();}int main (){ DDRB = 0b00000010; // enable PB1 setupTimer0(); while(1) {}}ISR(TIMER0_COMPA_vect) { if(intr_count == 1) { intr_count = 0; PORTB^=(1<

16位定时器(timer1)

下面这个程序使用ATmega328p的16位定时器1来延时1秒,ATmega328p默认是16MHz,每个周期是1/16MHz = 0.0625us,把它1024的预分频后得到15625Hz,这里的设置与上面ATtiny85雷同,只是这里使用的是16位定时器(0-65535), 下面把比较器设置成15640通过逻辑采样得到一个1s的方波,而使用15625得到是0.9993s的方波。

1234567891011121314151617181920212223242526272829303132333435363738~$ cat timer1.ino// AVR Timer CTC Interrupts Calculator// v. 8// http://www.arduinoslovakia.eu/application/timer-calculator// Microcontroller: ATmega328P// Created: 2022-04-27T14:02:45.452Z#define ledPin 13void setupTimer1() { noInterrupts(); // Clear registers TCCR1A = 0; TCCR1B = 0; TCNT1 = 0; // 15625 Hz (16000000/((0+1)*1024)) OCR1A = 15640; // CTC TCCR1B |= (1 << WGM12); // Prescaler 1024 TCCR1B |= (1 << CS12) | (1 << CS10); // Output Compare Match A Interrupt Enable TIMSK1 |= (1 << OCIE1A); interrupts();}void setup() { pinMode(ledPin, OUTPUT); setupTimer1();}void loop() {}ISR(TIMER1_COMPA_vect) { digitalWrite(ledPin, digitalRead(ledPin) ^ 1);}

ATmega8-16PULink:

Programming ATmega8 Using Arduino IDE

ATMEGA8-16PU

AVR Tutorial - Getting Started: Blinking an LED

下面是使用一块ATmega8-16PU与一块面包板,搭的简单测试

添加Arduino IDE支持

open File menu, click on Preferences.Now in Additional Boards Manger URLs, enter the following URL:https://mcudude.github.io/MiniCore/package_MCUdude_MiniCore_index.json

Go to Tools menu and then select Board > Boards Manager,In Boards Manager window, search for MiniCore and then install the latest version.

ATmega8-16pu连接UM232H1234567 UM232H ATmega8-16pu arduino pin outAD0 (CK) <-------> Pin19 PB5 (SCK) digital pin 13AD1 (DO) <-------> Pin17 PB3 (MOSI) digital pin 11AD2 (DI) <-------> Pin18 PB4 (MISO) digital pin 12AD3 (CS) <-------> Pin1 PC6 (RESET) GND <-------> Pin8 GND +5v <-------> Pin7 VCC

读写fuse

下面是读取它的fuse设置。

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364~$ avrdude -c UM232H -P /dev/ttyUSB1 -b 19200 -p m8 -U lfuse:r:-:i -vavrdude: Version 6.3-20171130 Copyright (c) 2000-2005 Brian Dean, http://www.bdmicro.com/ Copyright (c) 2007-2014 Joerg Wunsch System wide configuration file is "/etc/avrdude.conf" User configuration file is "/home/michael/.avrduderc" User configuration file does not exist or is not a regular file, skipping Using Port : /dev/ttyUSB1 Using Programmer : UM232H Overriding Baud Rate : 19200 AVR Part : ATmega8 Chip Erase delay : 10000 us PAGEL : PD7 BS2 : PC2 RESET disposition : dedicated RETRY pulse : SCK serial program mode : yes parallel program mode : yes Timeout : 200 StabDelay : 100 CmdexeDelay : 25 SyncLoops : 32 ByteDelay : 0 PollIndex : 3 PollValue : 0x53 Memory Detail : Block Poll Page Polled Memory Type Mode Delay Size Indx Paged Size Size #Pages MinW MaxW ReadBack ----------- ---- ----- ----- ---- ------ ------ ---- ------ ----- ----- --------- eeprom 4 20 128 0 no 512 4 0 9000 9000 0xff 0xff flash 33 10 64 0 yes 8192 64 128 4500 4500 0xff 0x00 lfuse 0 0 0 0 no 1 0 0 2000 2000 0x00 0x00 hfuse 0 0 0 0 no 1 0 0 2000 2000 0x00 0x00 lock 0 0 0 0 no 1 0 0 2000 2000 0x00 0x00 calibration 0 0 0 0 no 4 0 0 0 0 0x00 0x00 signature 0 0 0 0 no 3 0 0 0 0 0x00 0x00 Programmer Type : avrftdi Description : FT232H based module from FTDI and Glyn.com.auavrdude: AVR device initialized and ready to accept instructionsReading | ################################################## | 100% 0.01savrdude: Device signature = 0x1e9307 (probably m8)avrdude: safemode: lfuse reads as 62avrdude: safemode: hfuse reads as DFavrdude: reading lfuse memory:Reading | ################################################## | 100% 0.00savrdude: writing output file "":01000000629D:00000001FFavrdude: safemode: lfuse reads as 62avrdude: safemode: hfuse reads as DFavrdude: safemode: Fuses OK (E:FF, H:DF, L:62)avrdude done. Thank you.

写入fuse的配置,这里是通过AVR® Fuse Calculator配置计算出来的。

123456789101112131415161718192021222324252627282930313233343536373839404142~$avrdude -c UM232H -P /dev/ttyUSB1 -b 19200 -p m8 -U lfuse:w:0xd4:m -U hfuse:w:0xc9:mavrdude: AVR device initialized and ready to accept instructionsReading | ################################################## | 100% 0.01savrdude: Device signature = 0x1e9307 (probably m8)avrdude: reading input file "0xd4"avrdude: writing lfuse (1 bytes):Writing | ################################################## | 100% 0.01savrdude: 1 bytes of lfuse writtenavrdude: verifying lfuse memory against 0xd4:avrdude: load data lfuse data from input file 0xd4:avrdude: input file 0xd4 contains 1 bytesavrdude: reading on-chip lfuse data:Reading | ################################################## | 100% 0.00savrdude: verifying ...avrdude: 1 bytes of lfuse verifiedavrdude: reading input file "0xc9"avrdude: writing hfuse (1 bytes):Writing | ################################################## | 100% 0.00savrdude: 1 bytes of hfuse writtenavrdude: verifying hfuse memory against 0xc9:avrdude: load data hfuse data from input file 0xc9:avrdude: input file 0xc9 contains 1 bytesavrdude: reading on-chip hfuse data:Reading | ################################################## | 100% 0.00savrdude: verifying ...avrdude: 1 bytes of hfuse verifiedavrdude: safemode: Fuses OK (E:FF, H:C9, L:D4)avrdude done. Thank you.

基于Rust语言开发测试

Links:

Rust on a Digispark ATtiny85

Prerequistes1~$ sudo apt install binutils-avr avr-libc gcc-avr pkg-config avrdude libudev-dev

Install Micronucleus (Optional)

ft2232h Link to Lilytiny Attiny85

12345678 FT2232H ATTiny85ADBUS0 <------> SCK PB2ADBUS1 <------> MOSI PB0ADBUS2 <------> MISO PB1ADBUS3 <------> Reset PB5 GND <------> GND +5V <------> VIN

Build and Flash firmware

123~$ git clone https://github.com/micronucleus/micronucleus~$ cd micronucleus~$ make PROGRAMMER="-c UM232H -P /dev/ttyUSB0 -b 19200" flash

Build micronucleus flash CLI tool

123~$ sudo apt-get install libusb-dev~$ cd micronucleus/commandline~$ make && cp micronucleus /usr/bin

Connected to board USB

1234567891011121314151617181920212223242526272829303132333435363738394041424344~$ lsusb -v -s 001:030Bus 001 Device 030: ID 16d0:0753 MCS Digistump DigiSparkDevice Descriptor: bLength 18 bDescriptorType 1 bcdUSB 1.10 bDeviceClass 255 Vendor Specific Class bDeviceSubClass 0 bDeviceProtocol 0 bMaxPacketSize0 8 idVendor 0x16d0 MCS idProduct 0x0753 Digistump DigiSpark bcdDevice 2.06 iManufacturer 0 iProduct 0 iSerial 0 bNumConfigurations 1 Configuration Descriptor: bLength 9 bDescriptorType 2 wTotalLength 0x0012 bNumInterfaces 1 bConfigurationValue 1 iConfiguration 0 bmAttributes 0x80 (Bus Powered) MaxPower 100mA Interface Descriptor: bLength 9 bDescriptorType 4 bInterfaceNumber 0 bAlternateSetting 0 bNumEndpoints 0 bInterfaceClass 0 bInterfaceSubClass 0 bInterfaceProtocol 0 iInterface 0Device Status: 0xffff Self Powered Remote Wakeup Enabled Test Mode Debug Mode

Install Rust env

min-sized-rust

avr-hal

1~$ cargo +stable install ravedude

Build blink project12345~$ git clone https://github.com/Rahix/avr-hal~$ cd avr-hal/example/trinket~$ cargo build~$ avr-objcopy --output-target=ihex ../../target/avr-attiny85/debug/trinket-simple-pwm.elf ../../target/avr-attiny85/debug/trinket-simple-pwm.hex~$ micronucleus --timeout 60 --run --no-ansi ../../target/avr-attiny85/debug/trinket-simple-pwm.hex

Build release Minimzing Rust Binary Size test

added following lines into the Cargo.toml

1234567[profile.release]strip = trueopt-level = "z" # Optimize for size.lto = truepanic = "abort"debug = false

Build Release

12345678910111213141516171819202122232425262728293031323334353637~$ RUSTFLAGS="-Zlocation-detail=none" cargo build --releasewarning: profiles for the non root package will be ignored, specify profiles at the workspace root:package: /fullpath//github/AVR/avr-hal/examples/trinket/Cargo.tomlworkspace: /fullpath//github/AVR/avr-hal/Cargo.toml Compiling compiler_builtins v0.1.98 Compiling core v0.0.0 (/home/michael/.rustup/toolchains/nightly-2023-08-08-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core) Compiling proc-macro2 v1.0.69 Compiling unicode-ident v1.0.12 Compiling syn v1.0.109 Compiling proc-macro-hack v0.5.20+deprecated Compiling rustversion v1.0.14 Compiling paste v1.0.14 Compiling quote v1.0.33 Compiling avr-hal-generic v0.1.0 (/fullpath//github/AVR/avr-hal/avr-hal-generic) Compiling avr-device-macros v0.5.2 Compiling ufmt-macros v0.1.1 (https://github.com/Rahix/ufmt.git?rev=12225dc1678e42fecb0e8635bf80f501e24817d9#12225dc1) Compiling rustc-std-workspace-core v1.99.0 (/home/michael/.rustup/toolchains/nightly-2023-08-08-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/rustc-std-workspace-core) Compiling nb v1.1.0 Compiling ufmt-write v0.1.0 (https://github.com/Rahix/ufmt.git?rev=12225dc1678e42fecb0e8635bf80f501e24817d9#12225dc1) Compiling bare-metal v1.0.0 Compiling vcell v0.1.3 Compiling cfg-if v1.0.0 Compiling void v1.0.2 Compiling cfg-if v0.1.10 Compiling embedded-storage v0.2.0 Compiling panic-halt v0.2.0 Compiling ufmt v0.1.0 (https://github.com/Rahix/ufmt.git?rev=12225dc1678e42fecb0e8635bf80f501e24817d9#12225dc1) Compiling avr-device v0.5.2 Compiling nb v0.1.3 Compiling embedded-hal v0.2.7 Compiling attiny-hal v0.1.0 (/fullpath//github/AVR/avr-hal/mcu/attiny-hal) Compiling arduino-hal v0.1.0 (/fullpath//github/AVR/avr-hal/arduino-hal) Compiling trinket-examples v0.0.0 (/fullpath//github/AVR/avr-hal/examples/trinket)WARN rustc_codegen_ssa::back::link Linker does not support -no-pie command line option. Retrying without.WARN rustc_codegen_ssa::back::link Linker does not support -no-pie command line option. Retrying without. Finished release [optimized + debuginfo] target(s) in 6.60s

驱动NRF24l01Links:

nrf24l01+ control with 3 ATtiny85 pins

[nRF24l01 control with 2 MCU pins using time-division duplexed SPI](https://nerdralph.blogspot.com/2015/05/ nrf24l01-control-with-2-mcu-pins-using.html)

Fastest AVR software SPI in the West

nerdralph

ATtiny84/85 SPI Interface Pin Reuse

[ATtiny85 SPI protocol – Master and Slave mode tutorial](https://www.gadgetronicx.com/ attiny85-spi-protocol-master-slave-mode-tutorial/)

NRF24l01正常工作的要寄存器值如下:

1234567891011121314151617181920CONFIG: 0bEN_AA: 3eEN_RXADDR: 01SETUP_AW: 02SETUP_RETR:30RF_CH: 02RF_SETUP: 05STATUS: 0eOBS_TX: 00TX_ADDR: 71917d6bCD: 00RX_PW_P0: 20RX_PW_P1: 00RX_PW_P2: 00RX_PW_P3: 00RX_PW_P4: 00RX_PW_P5: 00FIFO_STAT: 11DYNPD: 00FEATURE: 05

驱动SSD1306

Tiny Graphics Library

ATtiny85 Graphics Display

ATTiny85 – OLED (I2C)

ATtiny-USI-I2C-Master

TinyI2C Library

lexus2k/ssd1306

Send a single pulse low/high pulse then stay high

OLED_Interface_With_8051

Debugging SSD1306 Display Problems

调试GDB

Debugging attiny85 code, part 2: Automating GDB with scripts

buserror/simavr

逻辑分析仪的问题

Fx2lafw

PulseView

Use a raspberry pi pico (rp2040) as a logic

Raspberry Pi PinOut

连接逻辑分析仪时,不知为何,有时会出现干扰,让程序跑飞,而断开后运行的很正常.

字符相关

fontconverter

Custom Fonts for Microcontrollers

fontbm

Making graphics and fonts for embedded systems

fontbuilder

LCD Character Set

AVR-GCC汇编相关

AVR GCC assembler techniques

Inline Assembler Cookbook

Basic Assembly Language programming

Introduction to AVR assembler programming for beginners

MCUCR Detial

GCC asm Statement

Let’s start with a simple example of reading a value from port D:

1asm("in %0, %1" : "=r" (value) : "I" (_SFR_IO_ADDR(PORTD)) );

Eachasmstatement is devided by colons into (up to) four parts:

The assembler instructions, defined as a single string constant: "in %0, %1"

A list of output operands, separated by commas. Our example uses just one: "=r" (value)

A comma separated list of input operands. Again our example uses one operand only:"I" (_SFR_IO_ADDR(PORTD))

Clobbered registers, left empty in our example.

You can write assembler instructions in much the same way as you would write assembler programs. However, registers andconstants are used in a different way if they refer to expressions of your C program. The connection between registersand C operands is specified in the second and third part of the asm instruction, the list of input and output operands,respectively. The general form is

1asm(code : output operand list : input operand list [: clobber list]);

In the code section, operands are referenced by a percent sign followed by a single digit. %0 refers to the first %1 tothe second operand and so forth. From the above example:

12%0 refers to "=r" (value) and%1 refers to "I" (_SFR_IO_ADDR(PORTD)).

Input and Output Operands

Each input and output operand is described by a constraint string followed by a C expression in parantheses. AVR-GCC 3.3knows the following constraint characters:

Note

The most up-to-date and detailed information on contraints for the avr can be found in the gcc manual.

The x register is r27:r26, the y register is r29:r28, and the z register is r31:r30

Constraint

Used for

Range

a

Simple upper registers

r16 to r23

b

Base pointer registers pairs

y, z

d

Upper register

r16 to r31

e

Pointer register pairs

x, y, z

q

Stack pointer register

SPH:SPL

r

Any register

r0 to r31

t

Temporary register

r0

w

Special upper register pairs

r24, r26, r28, r30

x

Pointer register pair X

x (r27:r26)

y

Pointer register pair Y

y (r29:r28)

z

Pointer register pair Z

z (r31:r30)

G

Floating point constant

0.0

I

6-bit positive integer constant

0 to 63

J

6-bit negative integer constant

-63 to 0

K

Integer constant

2

L

Integer constant

0

l

Lower registers

r0 to r15

M

8-bit integer constant

0 to 255

N

Integer constant

-1

O

Integer constant

8, 16, 24

P

Integer constant

1

Q

(GCC >= 4.2.x) A memory address based on Y or Z pointer with displacementa.

R

(GCC >= 4.3.x) Integer constant.

-6 to 5

Mnemonic

Constraints

Mnemonic

Constraints

adc

r,r

add

r,r

adiw

w,I

and

r,r

andi

d,M

asr

r

bclr

I

bld

r,I

brbc

I,label

brbs

I,label

bset

I

bst

r,I

cbi

I,I

cbr

d,I

com

r

cp

r,r

cpc

r,r

cpi

d,M

cpse

r,r

dec

r

elpm

t,z

eor

r,r

in

r,I

inc

r

ld

r,e

ldd

r,b

ldi

d,M

lds

r,label

lpm

t,z

lsl

r

lsr

r

mov

r,r

movw

r,r

mul

r,r

neg

r

or

r,r

ori

d,M

out

I,r

pop

r

push

r

rol

r

ror

r

sbc

r,r

sbci

d,M

sbi

I,I

sbic

I,I

sbiw

w,I

sbr

d,M

sbrc

r,I

sbrs

r,I

ser

d

st

e,r

std

b,r

sts

label,r

sub

r,r

subi

d,M

swap

r

Constraint characters may be prepended by a single constraint modifier. Contraints without a modifier specify read-only operands. Modifiers are:

Modifier Specifies

123= Write-only operand, usually used for all output operands.+ Read-write operand& Register should be used for output only

comment In assembler programming, the term clobbered registers is used to denote any registers whose value may beoverwritten during the course of executing an instruction or procedure.

谢谢支持

微信二维码: